linux/drivers/comedi/drivers/cb_pcidas.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * cb_pcidas.c
   4 * Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
   5 * David Schleef and the rest of the Comedi developers comunity.
   6 *
   7 * Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
   8 * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
   9 *
  10 * COMEDI - Linux Control and Measurement Device Interface
  11 * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
  12 */
  13
  14/*
  15 * Driver: cb_pcidas
  16 * Description: MeasurementComputing PCI-DAS series
  17 *   with the AMCC S5933 PCI controller
  18 * Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
  19 *   PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
  20 *   PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
  21 * Author: Ivan Martinez <imr@oersted.dtu.dk>,
  22 *   Frank Mori Hess <fmhess@users.sourceforge.net>
  23 * Updated: 2003-3-11
  24 *
  25 * Status:
  26 * There are many reports of the driver being used with most of the
  27 * supported cards. Despite no detailed log is maintained, it can
  28 * be said that the driver is quite tested and stable.
  29 *
  30 * The boards may be autocalibrated using the comedi_calibrate
  31 * utility.
  32 *
  33 * Configuration options: not applicable, uses PCI auto config
  34 *
  35 * For commands, the scanned channels must be consecutive
  36 * (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
  37 * range and aref.
  38 *
  39 * AI Triggering:
  40 * For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
  41 * For 1602 series, the start_arg is interpreted as follows:
  42 *      start_arg == 0                   => gated trigger (level high)
  43 *      start_arg == CR_INVERT           => gated trigger (level low)
  44 *      start_arg == CR_EDGE             => Rising edge
  45 *      start_arg == CR_EDGE | CR_INVERT => Falling edge
  46 * For the other boards the trigger will be done on rising edge
  47 */
  48
  49/*
  50 * TODO:
  51 * analog triggering on 1602 series
  52 */
  53
  54#include <linux/module.h>
  55#include <linux/delay.h>
  56#include <linux/interrupt.h>
  57#include <linux/comedi/comedi_pci.h>
  58#include <linux/comedi/comedi_8255.h>
  59#include <linux/comedi/comedi_8254.h>
  60
  61#include "amcc_s5933.h"
  62
  63#define AI_BUFFER_SIZE          1024    /* max ai fifo size */
  64#define AO_BUFFER_SIZE          1024    /* max ao fifo size */
  65
  66/*
  67 * PCI BAR1 Register map (devpriv->pcibar1)
  68 */
  69#define PCIDAS_CTRL_REG         0x00    /* INTERRUPT / ADC FIFO register */
  70#define PCIDAS_CTRL_INT(x)      (((x) & 0x3) << 0)
  71#define PCIDAS_CTRL_INT_NONE    PCIDAS_CTRL_INT(0) /* no int selected */
  72#define PCIDAS_CTRL_INT_EOS     PCIDAS_CTRL_INT(1) /* int on end of scan */
  73#define PCIDAS_CTRL_INT_FHF     PCIDAS_CTRL_INT(2) /* int on fifo half full */
  74#define PCIDAS_CTRL_INT_FNE     PCIDAS_CTRL_INT(3) /* int on fifo not empty */
  75#define PCIDAS_CTRL_INT_MASK    PCIDAS_CTRL_INT(3) /* mask of int select bits */
  76#define PCIDAS_CTRL_INTE        BIT(2)  /* int enable */
  77#define PCIDAS_CTRL_DAHFIE      BIT(3)  /* dac half full int enable */
  78#define PCIDAS_CTRL_EOAIE       BIT(4)  /* end of acq. int enable */
  79#define PCIDAS_CTRL_DAHFI       BIT(5)  /* dac half full status / clear */
  80#define PCIDAS_CTRL_EOAI        BIT(6)  /* end of acq. int status / clear */
  81#define PCIDAS_CTRL_INT_CLR     BIT(7)  /* int status / clear */
  82#define PCIDAS_CTRL_EOBI        BIT(9)  /* end of burst int status */
  83#define PCIDAS_CTRL_ADHFI       BIT(10) /* half-full int status */
  84#define PCIDAS_CTRL_ADNEI       BIT(11) /* fifo not empty int status (latch) */
  85#define PCIDAS_CTRL_ADNE        BIT(12) /* fifo not empty status (realtime) */
  86#define PCIDAS_CTRL_DAEMIE      BIT(12) /* dac empty int enable */
  87#define PCIDAS_CTRL_LADFUL      BIT(13) /* fifo overflow / clear */
  88#define PCIDAS_CTRL_DAEMI       BIT(14) /* dac fifo empty int status / clear */
  89
  90#define PCIDAS_CTRL_AI_INT      (PCIDAS_CTRL_EOAI | PCIDAS_CTRL_EOBI |   \
  91                                 PCIDAS_CTRL_ADHFI | PCIDAS_CTRL_ADNEI | \
  92                                 PCIDAS_CTRL_LADFUL)
  93#define PCIDAS_CTRL_AO_INT      (PCIDAS_CTRL_DAHFI | PCIDAS_CTRL_DAEMI)
  94
  95#define PCIDAS_AI_REG           0x02    /* ADC CHANNEL MUX AND CONTROL reg */
  96#define PCIDAS_AI_FIRST(x)      ((x) & 0xf)
  97#define PCIDAS_AI_LAST(x)       (((x) & 0xf) << 4)
  98#define PCIDAS_AI_CHAN(x)       (PCIDAS_AI_FIRST(x) | PCIDAS_AI_LAST(x))
  99#define PCIDAS_AI_GAIN(x)       (((x) & 0x3) << 8)
 100#define PCIDAS_AI_SE            BIT(10) /* Inputs in single-ended mode */
 101#define PCIDAS_AI_UNIP          BIT(11) /* Analog front-end unipolar mode */
 102#define PCIDAS_AI_PACER(x)      (((x) & 0x3) << 12)
 103#define PCIDAS_AI_PACER_SW      PCIDAS_AI_PACER(0) /* software pacer */
 104#define PCIDAS_AI_PACER_INT     PCIDAS_AI_PACER(1) /* int. pacer */
 105#define PCIDAS_AI_PACER_EXTN    PCIDAS_AI_PACER(2) /* ext. falling edge */
 106#define PCIDAS_AI_PACER_EXTP    PCIDAS_AI_PACER(3) /* ext. rising edge */
 107#define PCIDAS_AI_PACER_MASK    PCIDAS_AI_PACER(3) /* pacer source bits */
 108#define PCIDAS_AI_EOC           BIT(14) /* adc not busy */
 109
 110#define PCIDAS_TRIG_REG         0x04    /* TRIGGER CONTROL/STATUS register */
 111#define PCIDAS_TRIG_SEL(x)      (((x) & 0x3) << 0)
 112#define PCIDAS_TRIG_SEL_NONE    PCIDAS_TRIG_SEL(0) /* no start trigger */
 113#define PCIDAS_TRIG_SEL_SW      PCIDAS_TRIG_SEL(1) /* software start trigger */
 114#define PCIDAS_TRIG_SEL_EXT     PCIDAS_TRIG_SEL(2) /* ext. start trigger */
 115#define PCIDAS_TRIG_SEL_ANALOG  PCIDAS_TRIG_SEL(3) /* ext. analog trigger */
 116#define PCIDAS_TRIG_SEL_MASK    PCIDAS_TRIG_SEL(3) /* start trigger mask */
 117#define PCIDAS_TRIG_POL         BIT(2)  /* invert trigger (1602 only) */
 118#define PCIDAS_TRIG_MODE        BIT(3)  /* edge/level triggered (1602 only) */
 119#define PCIDAS_TRIG_EN          BIT(4)  /* enable external start trigger */
 120#define PCIDAS_TRIG_BURSTE      BIT(5)  /* burst mode enable */
 121#define PCIDAS_TRIG_CLR         BIT(7)  /* clear external trigger */
 122
 123#define PCIDAS_CALIB_REG        0x06    /* CALIBRATION register */
 124#define PCIDAS_CALIB_8800_SEL   BIT(8)  /* select 8800 caldac */
 125#define PCIDAS_CALIB_TRIM_SEL   BIT(9)  /* select ad7376 trim pot */
 126#define PCIDAS_CALIB_DAC08_SEL  BIT(10) /* select dac08 caldac */
 127#define PCIDAS_CALIB_SRC(x)     (((x) & 0x7) << 11)
 128#define PCIDAS_CALIB_EN         BIT(14) /* calibration source enable */
 129#define PCIDAS_CALIB_DATA       BIT(15) /* serial data bit going to caldac */
 130
 131#define PCIDAS_AO_REG           0x08    /* dac control and status register */
 132#define PCIDAS_AO_EMPTY         BIT(0)  /* fifo empty, write clear (1602) */
 133#define PCIDAS_AO_DACEN         BIT(1)  /* dac enable */
 134#define PCIDAS_AO_START         BIT(2)  /* start/arm fifo (1602) */
 135#define PCIDAS_AO_PACER(x)      (((x) & 0x3) << 3) /* (1602) */
 136#define PCIDAS_AO_PACER_SW      PCIDAS_AO_PACER(0) /* software pacer */
 137#define PCIDAS_AO_PACER_INT     PCIDAS_AO_PACER(1) /* int. pacer */
 138#define PCIDAS_AO_PACER_EXTN    PCIDAS_AO_PACER(2) /* ext. falling edge */
 139#define PCIDAS_AO_PACER_EXTP    PCIDAS_AO_PACER(3) /* ext. rising edge */
 140#define PCIDAS_AO_PACER_MASK    PCIDAS_AO_PACER(3) /* pacer source bits */
 141#define PCIDAS_AO_CHAN_EN(c)    BIT(5 + ((c) & 0x1))
 142#define PCIDAS_AO_CHAN_MASK     (PCIDAS_AO_CHAN_EN(0) | PCIDAS_AO_CHAN_EN(1))
 143#define PCIDAS_AO_UPDATE_BOTH   BIT(7)  /* update both dacs */
 144#define PCIDAS_AO_RANGE(c, r)   (((r) & 0x3) << (8 + 2 * ((c) & 0x1)))
 145#define PCIDAS_AO_RANGE_MASK(c) PCIDAS_AO_RANGE((c), 0x3)
 146
 147/*
 148 * PCI BAR2 Register map (devpriv->pcibar2)
 149 */
 150#define PCIDAS_AI_DATA_REG      0x00
 151#define PCIDAS_AI_FIFO_CLR_REG  0x02
 152
 153/*
 154 * PCI BAR3 Register map (dev->iobase)
 155 */
 156#define PCIDAS_AI_8254_BASE     0x00
 157#define PCIDAS_8255_BASE        0x04
 158#define PCIDAS_AO_8254_BASE     0x08
 159
 160/*
 161 * PCI BAR4 Register map (devpriv->pcibar4)
 162 */
 163#define PCIDAS_AO_DATA_REG(x)   (0x00 + ((x) * 2))
 164#define PCIDAS_AO_FIFO_REG      0x00
 165#define PCIDAS_AO_FIFO_CLR_REG  0x02
 166
 167/* analog input ranges for most boards */
 168static const struct comedi_lrange cb_pcidas_ranges = {
 169        8, {
 170                BIP_RANGE(10),
 171                BIP_RANGE(5),
 172                BIP_RANGE(2.5),
 173                BIP_RANGE(1.25),
 174                UNI_RANGE(10),
 175                UNI_RANGE(5),
 176                UNI_RANGE(2.5),
 177                UNI_RANGE(1.25)
 178        }
 179};
 180
 181/* pci-das1001 input ranges */
 182static const struct comedi_lrange cb_pcidas_alt_ranges = {
 183        8, {
 184                BIP_RANGE(10),
 185                BIP_RANGE(1),
 186                BIP_RANGE(0.1),
 187                BIP_RANGE(0.01),
 188                UNI_RANGE(10),
 189                UNI_RANGE(1),
 190                UNI_RANGE(0.1),
 191                UNI_RANGE(0.01)
 192        }
 193};
 194
 195/* analog output ranges */
 196static const struct comedi_lrange cb_pcidas_ao_ranges = {
 197        4, {
 198                BIP_RANGE(5),
 199                BIP_RANGE(10),
 200                UNI_RANGE(5),
 201                UNI_RANGE(10)
 202        }
 203};
 204
 205enum cb_pcidas_boardid {
 206        BOARD_PCIDAS1602_16,
 207        BOARD_PCIDAS1200,
 208        BOARD_PCIDAS1602_12,
 209        BOARD_PCIDAS1200_JR,
 210        BOARD_PCIDAS1602_16_JR,
 211        BOARD_PCIDAS1000,
 212        BOARD_PCIDAS1001,
 213        BOARD_PCIDAS1002,
 214};
 215
 216struct cb_pcidas_board {
 217        const char *name;
 218        int ai_speed;           /*  fastest conversion period in ns */
 219        int ao_scan_speed;      /*  analog output scan speed for 1602 series */
 220        int fifo_size;          /*  number of samples fifo can hold */
 221        unsigned int is_16bit;          /* ai/ao is 1=16-bit; 0=12-bit */
 222        unsigned int use_alt_range:1;   /* use alternate ai range table */
 223        unsigned int has_ao:1;          /* has 2 analog output channels */
 224        unsigned int has_ao_fifo:1;     /* analog output has fifo */
 225        unsigned int has_ad8402:1;      /* trimpot type 1=AD8402; 0=AD7376 */
 226        unsigned int has_dac08:1;
 227        unsigned int is_1602:1;
 228};
 229
 230static const struct cb_pcidas_board cb_pcidas_boards[] = {
 231        [BOARD_PCIDAS1602_16] = {
 232                .name           = "pci-das1602/16",
 233                .ai_speed       = 5000,
 234                .ao_scan_speed  = 10000,
 235                .fifo_size      = 512,
 236                .is_16bit       = 1,
 237                .has_ao         = 1,
 238                .has_ao_fifo    = 1,
 239                .has_ad8402     = 1,
 240                .has_dac08      = 1,
 241                .is_1602        = 1,
 242        },
 243        [BOARD_PCIDAS1200] = {
 244                .name           = "pci-das1200",
 245                .ai_speed       = 3200,
 246                .fifo_size      = 1024,
 247                .has_ao         = 1,
 248        },
 249        [BOARD_PCIDAS1602_12] = {
 250                .name           = "pci-das1602/12",
 251                .ai_speed       = 3200,
 252                .ao_scan_speed  = 4000,
 253                .fifo_size      = 1024,
 254                .has_ao         = 1,
 255                .has_ao_fifo    = 1,
 256                .is_1602        = 1,
 257        },
 258        [BOARD_PCIDAS1200_JR] = {
 259                .name           = "pci-das1200/jr",
 260                .ai_speed       = 3200,
 261                .fifo_size      = 1024,
 262        },
 263        [BOARD_PCIDAS1602_16_JR] = {
 264                .name           = "pci-das1602/16/jr",
 265                .ai_speed       = 5000,
 266                .fifo_size      = 512,
 267                .is_16bit       = 1,
 268                .has_ad8402     = 1,
 269                .has_dac08      = 1,
 270                .is_1602        = 1,
 271        },
 272        [BOARD_PCIDAS1000] = {
 273                .name           = "pci-das1000",
 274                .ai_speed       = 4000,
 275                .fifo_size      = 1024,
 276        },
 277        [BOARD_PCIDAS1001] = {
 278                .name           = "pci-das1001",
 279                .ai_speed       = 6800,
 280                .fifo_size      = 1024,
 281                .use_alt_range  = 1,
 282                .has_ao         = 1,
 283        },
 284        [BOARD_PCIDAS1002] = {
 285                .name           = "pci-das1002",
 286                .ai_speed       = 6800,
 287                .fifo_size      = 1024,
 288                .has_ao         = 1,
 289        },
 290};
 291
 292struct cb_pcidas_private {
 293        struct comedi_8254 *ao_pacer;
 294        /* base addresses */
 295        unsigned long amcc;     /* pcibar0 */
 296        unsigned long pcibar1;
 297        unsigned long pcibar2;
 298        unsigned long pcibar4;
 299        /* bits to write to registers */
 300        unsigned int ctrl;
 301        unsigned int amcc_intcsr;
 302        unsigned int ao_ctrl;
 303        /* fifo buffers */
 304        unsigned short ai_buffer[AI_BUFFER_SIZE];
 305        unsigned short ao_buffer[AO_BUFFER_SIZE];
 306        unsigned int calib_src;
 307};
 308
 309static int cb_pcidas_ai_eoc(struct comedi_device *dev,
 310                            struct comedi_subdevice *s,
 311                            struct comedi_insn *insn,
 312                            unsigned long context)
 313{
 314        struct cb_pcidas_private *devpriv = dev->private;
 315        unsigned int status;
 316
 317        status = inw(devpriv->pcibar1 + PCIDAS_AI_REG);
 318        if (status & PCIDAS_AI_EOC)
 319                return 0;
 320        return -EBUSY;
 321}
 322
 323static int cb_pcidas_ai_insn_read(struct comedi_device *dev,
 324                                  struct comedi_subdevice *s,
 325                                  struct comedi_insn *insn,
 326                                  unsigned int *data)
 327{
 328        struct cb_pcidas_private *devpriv = dev->private;
 329        unsigned int chan = CR_CHAN(insn->chanspec);
 330        unsigned int range = CR_RANGE(insn->chanspec);
 331        unsigned int aref = CR_AREF(insn->chanspec);
 332        unsigned int bits;
 333        int ret;
 334        int n;
 335
 336        /* enable calibration input if appropriate */
 337        if (insn->chanspec & CR_ALT_SOURCE) {
 338                outw(PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src),
 339                     devpriv->pcibar1 + PCIDAS_CALIB_REG);
 340                chan = 0;
 341        } else {
 342                outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 343        }
 344
 345        /* set mux limits and gain */
 346        bits = PCIDAS_AI_CHAN(chan) | PCIDAS_AI_GAIN(range);
 347        /* set unipolar/bipolar */
 348        if (comedi_range_is_unipolar(s, range))
 349                bits |= PCIDAS_AI_UNIP;
 350        /* set single-ended/differential */
 351        if (aref != AREF_DIFF)
 352                bits |= PCIDAS_AI_SE;
 353        outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
 354
 355        /* clear fifo */
 356        outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
 357
 358        /* convert n samples */
 359        for (n = 0; n < insn->n; n++) {
 360                /* trigger conversion */
 361                outw(0, devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
 362
 363                /* wait for conversion to end */
 364                ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0);
 365                if (ret)
 366                        return ret;
 367
 368                /* read data */
 369                data[n] = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
 370        }
 371
 372        /* return the number of samples read/written */
 373        return n;
 374}
 375
 376static int cb_pcidas_ai_insn_config(struct comedi_device *dev,
 377                                    struct comedi_subdevice *s,
 378                                    struct comedi_insn *insn,
 379                                    unsigned int *data)
 380{
 381        struct cb_pcidas_private *devpriv = dev->private;
 382        int id = data[0];
 383        unsigned int source = data[1];
 384
 385        switch (id) {
 386        case INSN_CONFIG_ALT_SOURCE:
 387                if (source >= 8) {
 388                        dev_err(dev->class_dev,
 389                                "invalid calibration source: %i\n",
 390                                source);
 391                        return -EINVAL;
 392                }
 393                devpriv->calib_src = source;
 394                break;
 395        default:
 396                return -EINVAL;
 397        }
 398        return insn->n;
 399}
 400
 401/* analog output insn for pcidas-1000 and 1200 series */
 402static int cb_pcidas_ao_nofifo_insn_write(struct comedi_device *dev,
 403                                          struct comedi_subdevice *s,
 404                                          struct comedi_insn *insn,
 405                                          unsigned int *data)
 406{
 407        struct cb_pcidas_private *devpriv = dev->private;
 408        unsigned int chan = CR_CHAN(insn->chanspec);
 409        unsigned int range = CR_RANGE(insn->chanspec);
 410        unsigned int val = s->readback[chan];
 411        unsigned long flags;
 412        int i;
 413
 414        /* set channel and range */
 415        spin_lock_irqsave(&dev->spinlock, flags);
 416        devpriv->ao_ctrl &= ~(PCIDAS_AO_UPDATE_BOTH |
 417                              PCIDAS_AO_RANGE_MASK(chan));
 418        devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range);
 419        outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
 420        spin_unlock_irqrestore(&dev->spinlock, flags);
 421
 422        for (i = 0; i < insn->n; i++) {
 423                val = data[i];
 424                outw(val, devpriv->pcibar4 + PCIDAS_AO_DATA_REG(chan));
 425        }
 426
 427        s->readback[chan] = val;
 428
 429        return insn->n;
 430}
 431
 432/* analog output insn for pcidas-1602 series */
 433static int cb_pcidas_ao_fifo_insn_write(struct comedi_device *dev,
 434                                        struct comedi_subdevice *s,
 435                                        struct comedi_insn *insn,
 436                                        unsigned int *data)
 437{
 438        struct cb_pcidas_private *devpriv = dev->private;
 439        unsigned int chan = CR_CHAN(insn->chanspec);
 440        unsigned int range = CR_RANGE(insn->chanspec);
 441        unsigned int val = s->readback[chan];
 442        unsigned long flags;
 443        int i;
 444
 445        /* clear dac fifo */
 446        outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
 447
 448        /* set channel and range */
 449        spin_lock_irqsave(&dev->spinlock, flags);
 450        devpriv->ao_ctrl &= ~(PCIDAS_AO_CHAN_MASK | PCIDAS_AO_RANGE_MASK(chan) |
 451                              PCIDAS_AO_PACER_MASK);
 452        devpriv->ao_ctrl |= PCIDAS_AO_DACEN | PCIDAS_AO_RANGE(chan, range) |
 453                            PCIDAS_AO_CHAN_EN(chan) | PCIDAS_AO_START;
 454        outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
 455        spin_unlock_irqrestore(&dev->spinlock, flags);
 456
 457        for (i = 0; i < insn->n; i++) {
 458                val = data[i];
 459                outw(val, devpriv->pcibar4 + PCIDAS_AO_FIFO_REG);
 460        }
 461
 462        s->readback[chan] = val;
 463
 464        return insn->n;
 465}
 466
 467static int cb_pcidas_eeprom_ready(struct comedi_device *dev,
 468                                  struct comedi_subdevice *s,
 469                                  struct comedi_insn *insn,
 470                                  unsigned long context)
 471{
 472        struct cb_pcidas_private *devpriv = dev->private;
 473        unsigned int status;
 474
 475        status = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
 476        if ((status & MCSR_NV_BUSY) == 0)
 477                return 0;
 478        return -EBUSY;
 479}
 480
 481static int cb_pcidas_eeprom_insn_read(struct comedi_device *dev,
 482                                      struct comedi_subdevice *s,
 483                                      struct comedi_insn *insn,
 484                                      unsigned int *data)
 485{
 486        struct cb_pcidas_private *devpriv = dev->private;
 487        unsigned int chan = CR_CHAN(insn->chanspec);
 488        int ret;
 489        int i;
 490
 491        for (i = 0; i < insn->n; i++) {
 492                /* make sure eeprom is ready */
 493                ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
 494                if (ret)
 495                        return ret;
 496
 497                /* set address (chan) and read operation */
 498                outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
 499                     devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
 500                outb(chan & 0xff, devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
 501                outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
 502                     devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
 503                outb((chan >> 8) & 0xff,
 504                     devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
 505                outb(MCSR_NV_ENABLE | MCSR_NV_READ,
 506                     devpriv->amcc + AMCC_OP_REG_MCSR_NVCMD);
 507
 508                /* wait for data to be returned */
 509                ret = comedi_timeout(dev, s, insn, cb_pcidas_eeprom_ready, 0);
 510                if (ret)
 511                        return ret;
 512
 513                data[i] = inb(devpriv->amcc + AMCC_OP_REG_MCSR_NVDATA);
 514        }
 515
 516        return insn->n;
 517}
 518
 519static void cb_pcidas_calib_write(struct comedi_device *dev,
 520                                  unsigned int val, unsigned int len,
 521                                  bool trimpot)
 522{
 523        struct cb_pcidas_private *devpriv = dev->private;
 524        unsigned int calib_bits;
 525        unsigned int bit;
 526
 527        calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
 528        if (trimpot) {
 529                /* select trimpot */
 530                calib_bits |= PCIDAS_CALIB_TRIM_SEL;
 531                outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 532        }
 533
 534        /* write bitstream to calibration device */
 535        for (bit = 1 << (len - 1); bit; bit >>= 1) {
 536                if (val & bit)
 537                        calib_bits |= PCIDAS_CALIB_DATA;
 538                else
 539                        calib_bits &= ~PCIDAS_CALIB_DATA;
 540                udelay(1);
 541                outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 542        }
 543        udelay(1);
 544
 545        calib_bits = PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
 546
 547        if (!trimpot) {
 548                /* select caldac */
 549                outw(calib_bits | PCIDAS_CALIB_8800_SEL,
 550                     devpriv->pcibar1 + PCIDAS_CALIB_REG);
 551                udelay(1);
 552        }
 553
 554        /* latch value to trimpot/caldac */
 555        outw(calib_bits, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 556}
 557
 558static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
 559                                       struct comedi_subdevice *s,
 560                                       struct comedi_insn *insn,
 561                                       unsigned int *data)
 562{
 563        unsigned int chan = CR_CHAN(insn->chanspec);
 564
 565        if (insn->n) {
 566                unsigned int val = data[insn->n - 1];
 567
 568                if (s->readback[chan] != val) {
 569                        /* write 11-bit channel/value to caldac */
 570                        cb_pcidas_calib_write(dev, (chan << 8) | val, 11,
 571                                              false);
 572                        s->readback[chan] = val;
 573                }
 574        }
 575
 576        return insn->n;
 577}
 578
 579static void cb_pcidas_dac08_write(struct comedi_device *dev, unsigned int val)
 580{
 581        struct cb_pcidas_private *devpriv = dev->private;
 582
 583        val |= PCIDAS_CALIB_EN | PCIDAS_CALIB_SRC(devpriv->calib_src);
 584
 585        /* latch the new value into the caldac */
 586        outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 587        udelay(1);
 588        outw(val | PCIDAS_CALIB_DAC08_SEL,
 589             devpriv->pcibar1 + PCIDAS_CALIB_REG);
 590        udelay(1);
 591        outw(val, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 592        udelay(1);
 593}
 594
 595static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
 596                                      struct comedi_subdevice *s,
 597                                      struct comedi_insn *insn,
 598                                      unsigned int *data)
 599{
 600        unsigned int chan = CR_CHAN(insn->chanspec);
 601
 602        if (insn->n) {
 603                unsigned int val = data[insn->n - 1];
 604
 605                if (s->readback[chan] != val) {
 606                        cb_pcidas_dac08_write(dev, val);
 607                        s->readback[chan] = val;
 608                }
 609        }
 610
 611        return insn->n;
 612}
 613
 614static void cb_pcidas_trimpot_write(struct comedi_device *dev,
 615                                    unsigned int chan, unsigned int val)
 616{
 617        const struct cb_pcidas_board *board = dev->board_ptr;
 618
 619        if (board->has_ad8402) {
 620                /* write 10-bit channel/value to AD8402 trimpot */
 621                cb_pcidas_calib_write(dev, (chan << 8) | val, 10, true);
 622        } else {
 623                /* write 7-bit value to AD7376 trimpot */
 624                cb_pcidas_calib_write(dev, val, 7, true);
 625        }
 626}
 627
 628static int cb_pcidas_trimpot_insn_write(struct comedi_device *dev,
 629                                        struct comedi_subdevice *s,
 630                                        struct comedi_insn *insn,
 631                                        unsigned int *data)
 632{
 633        unsigned int chan = CR_CHAN(insn->chanspec);
 634
 635        if (insn->n) {
 636                unsigned int val = data[insn->n - 1];
 637
 638                if (s->readback[chan] != val) {
 639                        cb_pcidas_trimpot_write(dev, chan, val);
 640                        s->readback[chan] = val;
 641                }
 642        }
 643
 644        return insn->n;
 645}
 646
 647static int cb_pcidas_ai_check_chanlist(struct comedi_device *dev,
 648                                       struct comedi_subdevice *s,
 649                                       struct comedi_cmd *cmd)
 650{
 651        unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
 652        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 653        int i;
 654
 655        for (i = 1; i < cmd->chanlist_len; i++) {
 656                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 657                unsigned int range = CR_RANGE(cmd->chanlist[i]);
 658
 659                if (chan != (chan0 + i) % s->n_chan) {
 660                        dev_dbg(dev->class_dev,
 661                                "entries in chanlist must be consecutive channels, counting upwards\n");
 662                        return -EINVAL;
 663                }
 664
 665                if (range != range0) {
 666                        dev_dbg(dev->class_dev,
 667                                "entries in chanlist must all have the same gain\n");
 668                        return -EINVAL;
 669                }
 670        }
 671        return 0;
 672}
 673
 674static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
 675                                struct comedi_subdevice *s,
 676                                struct comedi_cmd *cmd)
 677{
 678        const struct cb_pcidas_board *board = dev->board_ptr;
 679        int err = 0;
 680        unsigned int arg;
 681
 682        /* Step 1 : check if triggers are trivially valid */
 683
 684        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 685        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 686                                        TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
 687        err |= comedi_check_trigger_src(&cmd->convert_src,
 688                                        TRIG_TIMER | TRIG_NOW | TRIG_EXT);
 689        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 690        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 691
 692        if (err)
 693                return 1;
 694
 695        /* Step 2a : make sure trigger sources are unique */
 696
 697        err |= comedi_check_trigger_is_unique(cmd->start_src);
 698        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 699        err |= comedi_check_trigger_is_unique(cmd->convert_src);
 700        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 701
 702        /* Step 2b : and mutually compatible */
 703
 704        if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
 705                err |= -EINVAL;
 706        if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
 707                err |= -EINVAL;
 708        if (cmd->start_src == TRIG_EXT &&
 709            (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
 710                err |= -EINVAL;
 711
 712        if (err)
 713                return 2;
 714
 715        /* Step 3: check if arguments are trivially valid */
 716
 717        switch (cmd->start_src) {
 718        case TRIG_NOW:
 719                err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 720                break;
 721        case TRIG_EXT:
 722                /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
 723                if ((cmd->start_arg
 724                     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
 725                        cmd->start_arg &= ~(CR_FLAGS_MASK &
 726                                                ~(CR_EDGE | CR_INVERT));
 727                        err |= -EINVAL;
 728                }
 729                if (!board->is_1602 && (cmd->start_arg & CR_INVERT)) {
 730                        cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
 731                        err |= -EINVAL;
 732                }
 733                break;
 734        }
 735
 736        if (cmd->scan_begin_src == TRIG_TIMER) {
 737                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 738                                                    board->ai_speed *
 739                                                    cmd->chanlist_len);
 740        }
 741
 742        if (cmd->convert_src == TRIG_TIMER) {
 743                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 744                                                    board->ai_speed);
 745        }
 746
 747        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 748                                           cmd->chanlist_len);
 749
 750        if (cmd->stop_src == TRIG_COUNT)
 751                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 752        else    /* TRIG_NONE */
 753                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 754
 755        if (err)
 756                return 3;
 757
 758        /* step 4: fix up any arguments */
 759
 760        if (cmd->scan_begin_src == TRIG_TIMER) {
 761                arg = cmd->scan_begin_arg;
 762                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 763                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 764        }
 765        if (cmd->convert_src == TRIG_TIMER) {
 766                arg = cmd->convert_arg;
 767                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 768                err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 769        }
 770
 771        if (err)
 772                return 4;
 773
 774        /* Step 5: check channel list if it exists */
 775        if (cmd->chanlist && cmd->chanlist_len > 0)
 776                err |= cb_pcidas_ai_check_chanlist(dev, s, cmd);
 777
 778        if (err)
 779                return 5;
 780
 781        return 0;
 782}
 783
 784static int cb_pcidas_ai_cmd(struct comedi_device *dev,
 785                            struct comedi_subdevice *s)
 786{
 787        const struct cb_pcidas_board *board = dev->board_ptr;
 788        struct cb_pcidas_private *devpriv = dev->private;
 789        struct comedi_async *async = s->async;
 790        struct comedi_cmd *cmd = &async->cmd;
 791        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 792        unsigned int bits;
 793        unsigned long flags;
 794
 795        /*  make sure PCIDAS_CALIB_EN is disabled */
 796        outw(0, devpriv->pcibar1 + PCIDAS_CALIB_REG);
 797        /*  initialize before settings pacer source and count values */
 798        outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
 799        /*  clear fifo */
 800        outw(0, devpriv->pcibar2 + PCIDAS_AI_FIFO_CLR_REG);
 801
 802        /*  set mux limits, gain and pacer source */
 803        bits = PCIDAS_AI_FIRST(CR_CHAN(cmd->chanlist[0])) |
 804               PCIDAS_AI_LAST(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
 805               PCIDAS_AI_GAIN(range0);
 806        /*  set unipolar/bipolar */
 807        if (comedi_range_is_unipolar(s, range0))
 808                bits |= PCIDAS_AI_UNIP;
 809        /*  set singleended/differential */
 810        if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
 811                bits |= PCIDAS_AI_SE;
 812        /*  set pacer source */
 813        if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
 814                bits |= PCIDAS_AI_PACER_EXTP;
 815        else
 816                bits |= PCIDAS_AI_PACER_INT;
 817        outw(bits, devpriv->pcibar1 + PCIDAS_AI_REG);
 818
 819        /*  load counters */
 820        if (cmd->scan_begin_src == TRIG_TIMER ||
 821            cmd->convert_src == TRIG_TIMER) {
 822                comedi_8254_update_divisors(dev->pacer);
 823                comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 824        }
 825
 826        /*  enable interrupts */
 827        spin_lock_irqsave(&dev->spinlock, flags);
 828        devpriv->ctrl |= PCIDAS_CTRL_INTE;
 829        devpriv->ctrl &= ~PCIDAS_CTRL_INT_MASK;
 830        if (cmd->flags & CMDF_WAKE_EOS) {
 831                if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
 832                        /* interrupt end of burst */
 833                        devpriv->ctrl |= PCIDAS_CTRL_INT_EOS;
 834                } else {
 835                        /* interrupt fifo not empty */
 836                        devpriv->ctrl |= PCIDAS_CTRL_INT_FNE;
 837                }
 838        } else {
 839                /* interrupt fifo half full */
 840                devpriv->ctrl |= PCIDAS_CTRL_INT_FHF;
 841        }
 842
 843        /*  enable (and clear) interrupts */
 844        outw(devpriv->ctrl |
 845             PCIDAS_CTRL_EOAI | PCIDAS_CTRL_INT_CLR | PCIDAS_CTRL_LADFUL,
 846             devpriv->pcibar1 + PCIDAS_CTRL_REG);
 847        spin_unlock_irqrestore(&dev->spinlock, flags);
 848
 849        /*  set start trigger and burst mode */
 850        bits = 0;
 851        if (cmd->start_src == TRIG_NOW) {
 852                bits |= PCIDAS_TRIG_SEL_SW;
 853        } else {        /* TRIG_EXT */
 854                bits |= PCIDAS_TRIG_SEL_EXT | PCIDAS_TRIG_EN | PCIDAS_TRIG_CLR;
 855                if (board->is_1602) {
 856                        if (cmd->start_arg & CR_INVERT)
 857                                bits |= PCIDAS_TRIG_POL;
 858                        if (cmd->start_arg & CR_EDGE)
 859                                bits |= PCIDAS_TRIG_MODE;
 860                }
 861        }
 862        if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
 863                bits |= PCIDAS_TRIG_BURSTE;
 864        outw(bits, devpriv->pcibar1 + PCIDAS_TRIG_REG);
 865
 866        return 0;
 867}
 868
 869static int cb_pcidas_ao_check_chanlist(struct comedi_device *dev,
 870                                       struct comedi_subdevice *s,
 871                                       struct comedi_cmd *cmd)
 872{
 873        unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
 874
 875        if (cmd->chanlist_len > 1) {
 876                unsigned int chan1 = CR_CHAN(cmd->chanlist[1]);
 877
 878                if (chan0 != 0 || chan1 != 1) {
 879                        dev_dbg(dev->class_dev,
 880                                "channels must be ordered channel 0, channel 1 in chanlist\n");
 881                        return -EINVAL;
 882                }
 883        }
 884
 885        return 0;
 886}
 887
 888static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
 889                                struct comedi_subdevice *s,
 890                                struct comedi_cmd *cmd)
 891{
 892        const struct cb_pcidas_board *board = dev->board_ptr;
 893        struct cb_pcidas_private *devpriv = dev->private;
 894        int err = 0;
 895
 896        /* Step 1 : check if triggers are trivially valid */
 897
 898        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
 899        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 900                                        TRIG_TIMER | TRIG_EXT);
 901        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 902        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 903        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 904
 905        if (err)
 906                return 1;
 907
 908        /* Step 2a : make sure trigger sources are unique */
 909
 910        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 911        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 912
 913        /* Step 2b : and mutually compatible */
 914
 915        if (err)
 916                return 2;
 917
 918        /* Step 3: check if arguments are trivially valid */
 919
 920        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 921
 922        if (cmd->scan_begin_src == TRIG_TIMER) {
 923                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 924                                                    board->ao_scan_speed);
 925        }
 926
 927        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 928                                           cmd->chanlist_len);
 929
 930        if (cmd->stop_src == TRIG_COUNT)
 931                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 932        else    /* TRIG_NONE */
 933                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 934
 935        if (err)
 936                return 3;
 937
 938        /* step 4: fix up any arguments */
 939
 940        if (cmd->scan_begin_src == TRIG_TIMER) {
 941                unsigned int arg = cmd->scan_begin_arg;
 942
 943                comedi_8254_cascade_ns_to_timer(devpriv->ao_pacer,
 944                                                &arg, cmd->flags);
 945                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 946        }
 947
 948        if (err)
 949                return 4;
 950
 951        /* Step 5: check channel list if it exists */
 952        if (cmd->chanlist && cmd->chanlist_len > 0)
 953                err |= cb_pcidas_ao_check_chanlist(dev, s, cmd);
 954
 955        if (err)
 956                return 5;
 957
 958        return 0;
 959}
 960
 961static int cb_pcidas_ai_cancel(struct comedi_device *dev,
 962                               struct comedi_subdevice *s)
 963{
 964        struct cb_pcidas_private *devpriv = dev->private;
 965        unsigned long flags;
 966
 967        spin_lock_irqsave(&dev->spinlock, flags);
 968        /*  disable interrupts */
 969        devpriv->ctrl &= ~(PCIDAS_CTRL_INTE | PCIDAS_CTRL_EOAIE);
 970        outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
 971        spin_unlock_irqrestore(&dev->spinlock, flags);
 972
 973        /*  disable start trigger source and burst mode */
 974        outw(PCIDAS_TRIG_SEL_NONE, devpriv->pcibar1 + PCIDAS_TRIG_REG);
 975        outw(PCIDAS_AI_PACER_SW, devpriv->pcibar1 + PCIDAS_AI_REG);
 976
 977        return 0;
 978}
 979
 980static void cb_pcidas_ao_load_fifo(struct comedi_device *dev,
 981                                   struct comedi_subdevice *s,
 982                                   unsigned int nsamples)
 983{
 984        struct cb_pcidas_private *devpriv = dev->private;
 985        unsigned int nbytes;
 986
 987        nsamples = comedi_nsamples_left(s, nsamples);
 988        nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples);
 989
 990        nsamples = comedi_bytes_to_samples(s, nbytes);
 991        outsw(devpriv->pcibar4 + PCIDAS_AO_FIFO_REG,
 992              devpriv->ao_buffer, nsamples);
 993}
 994
 995static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
 996                                struct comedi_subdevice *s,
 997                                unsigned int trig_num)
 998{
 999        const struct cb_pcidas_board *board = dev->board_ptr;
1000        struct cb_pcidas_private *devpriv = dev->private;
1001        struct comedi_async *async = s->async;
1002        struct comedi_cmd *cmd = &async->cmd;
1003        unsigned long flags;
1004
1005        if (trig_num != cmd->start_arg)
1006                return -EINVAL;
1007
1008        cb_pcidas_ao_load_fifo(dev, s, board->fifo_size);
1009
1010        /*  enable dac half-full and empty interrupts */
1011        spin_lock_irqsave(&dev->spinlock, flags);
1012        devpriv->ctrl |= PCIDAS_CTRL_DAEMIE | PCIDAS_CTRL_DAHFIE;
1013
1014        /*  enable and clear interrupts */
1015        outw(devpriv->ctrl | PCIDAS_CTRL_DAEMI | PCIDAS_CTRL_DAHFI,
1016             devpriv->pcibar1 + PCIDAS_CTRL_REG);
1017
1018        /*  start dac */
1019        devpriv->ao_ctrl |= PCIDAS_AO_START | PCIDAS_AO_DACEN | PCIDAS_AO_EMPTY;
1020        outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1021
1022        spin_unlock_irqrestore(&dev->spinlock, flags);
1023
1024        async->inttrig = NULL;
1025
1026        return 0;
1027}
1028
1029static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1030                            struct comedi_subdevice *s)
1031{
1032        struct cb_pcidas_private *devpriv = dev->private;
1033        struct comedi_async *async = s->async;
1034        struct comedi_cmd *cmd = &async->cmd;
1035        unsigned int i;
1036        unsigned long flags;
1037
1038        /*  set channel limits, gain */
1039        spin_lock_irqsave(&dev->spinlock, flags);
1040        for (i = 0; i < cmd->chanlist_len; i++) {
1041                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
1042                unsigned int range = CR_RANGE(cmd->chanlist[i]);
1043
1044                /*  enable channel */
1045                devpriv->ao_ctrl |= PCIDAS_AO_CHAN_EN(chan);
1046                /*  set range */
1047                devpriv->ao_ctrl |= PCIDAS_AO_RANGE(chan, range);
1048        }
1049
1050        /*  disable analog out before settings pacer source and count values */
1051        outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1052        spin_unlock_irqrestore(&dev->spinlock, flags);
1053
1054        /*  clear fifo */
1055        outw(0, devpriv->pcibar4 + PCIDAS_AO_FIFO_CLR_REG);
1056
1057        /*  load counters */
1058        if (cmd->scan_begin_src == TRIG_TIMER) {
1059                comedi_8254_update_divisors(devpriv->ao_pacer);
1060                comedi_8254_pacer_enable(devpriv->ao_pacer, 1, 2, true);
1061        }
1062
1063        /*  set pacer source */
1064        spin_lock_irqsave(&dev->spinlock, flags);
1065        switch (cmd->scan_begin_src) {
1066        case TRIG_TIMER:
1067                devpriv->ao_ctrl |= PCIDAS_AO_PACER_INT;
1068                break;
1069        case TRIG_EXT:
1070                devpriv->ao_ctrl |= PCIDAS_AO_PACER_EXTP;
1071                break;
1072        default:
1073                spin_unlock_irqrestore(&dev->spinlock, flags);
1074                dev_err(dev->class_dev, "error setting dac pacer source\n");
1075                return -1;
1076        }
1077        spin_unlock_irqrestore(&dev->spinlock, flags);
1078
1079        async->inttrig = cb_pcidas_ao_inttrig;
1080
1081        return 0;
1082}
1083
1084static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1085                               struct comedi_subdevice *s)
1086{
1087        struct cb_pcidas_private *devpriv = dev->private;
1088        unsigned long flags;
1089
1090        spin_lock_irqsave(&dev->spinlock, flags);
1091        /*  disable interrupts */
1092        devpriv->ctrl &= ~(PCIDAS_CTRL_DAHFIE | PCIDAS_CTRL_DAEMIE);
1093        outw(devpriv->ctrl, devpriv->pcibar1 + PCIDAS_CTRL_REG);
1094
1095        /*  disable output */
1096        devpriv->ao_ctrl &= ~(PCIDAS_AO_DACEN | PCIDAS_AO_PACER_MASK);
1097        outw(devpriv->ao_ctrl, devpriv->pcibar1 + PCIDAS_AO_REG);
1098        spin_unlock_irqrestore(&dev->spinlock, flags);
1099
1100        return 0;
1101}
1102
1103static unsigned int cb_pcidas_ao_interrupt(struct comedi_device *dev,
1104                                           unsigned int status)
1105{
1106        const struct cb_pcidas_board *board = dev->board_ptr;
1107        struct cb_pcidas_private *devpriv = dev->private;
1108        struct comedi_subdevice *s = dev->write_subdev;
1109        struct comedi_async *async = s->async;
1110        struct comedi_cmd *cmd = &async->cmd;
1111        unsigned int irq_clr = 0;
1112
1113        if (status & PCIDAS_CTRL_DAEMI) {
1114                irq_clr |= PCIDAS_CTRL_DAEMI;
1115
1116                if (inw(devpriv->pcibar4 + PCIDAS_AO_REG) & PCIDAS_AO_EMPTY) {
1117                        if (cmd->stop_src == TRIG_COUNT &&
1118                            async->scans_done >= cmd->stop_arg) {
1119                                async->events |= COMEDI_CB_EOA;
1120                        } else {
1121                                dev_err(dev->class_dev, "dac fifo underflow\n");
1122                                async->events |= COMEDI_CB_ERROR;
1123                        }
1124                }
1125        } else if (status & PCIDAS_CTRL_DAHFI) {
1126                irq_clr |= PCIDAS_CTRL_DAHFI;
1127
1128                cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
1129        }
1130
1131        comedi_handle_events(dev, s);
1132
1133        return irq_clr;
1134}
1135
1136static unsigned int cb_pcidas_ai_interrupt(struct comedi_device *dev,
1137                                           unsigned int status)
1138{
1139        const struct cb_pcidas_board *board = dev->board_ptr;
1140        struct cb_pcidas_private *devpriv = dev->private;
1141        struct comedi_subdevice *s = dev->read_subdev;
1142        struct comedi_async *async = s->async;
1143        struct comedi_cmd *cmd = &async->cmd;
1144        unsigned int irq_clr = 0;
1145
1146        if (status & PCIDAS_CTRL_ADHFI) {
1147                unsigned int num_samples;
1148
1149                irq_clr |= PCIDAS_CTRL_INT_CLR;
1150
1151                /* FIFO is half-full - read data */
1152                num_samples = comedi_nsamples_left(s, board->fifo_size / 2);
1153                insw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG,
1154                     devpriv->ai_buffer, num_samples);
1155                comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
1156
1157                if (cmd->stop_src == TRIG_COUNT &&
1158                    async->scans_done >= cmd->stop_arg)
1159                        async->events |= COMEDI_CB_EOA;
1160        } else if (status & (PCIDAS_CTRL_ADNEI | PCIDAS_CTRL_EOBI)) {
1161                unsigned int i;
1162
1163                irq_clr |= PCIDAS_CTRL_INT_CLR;
1164
1165                /* FIFO is not empty - read data until empty or timeoout */
1166                for (i = 0; i < 10000; i++) {
1167                        unsigned short val;
1168
1169                        /*  break if fifo is empty */
1170                        if ((inw(devpriv->pcibar1 + PCIDAS_CTRL_REG) &
1171                            PCIDAS_CTRL_ADNE) == 0)
1172                                break;
1173                        val = inw(devpriv->pcibar2 + PCIDAS_AI_DATA_REG);
1174                        comedi_buf_write_samples(s, &val, 1);
1175
1176                        if (cmd->stop_src == TRIG_COUNT &&
1177                            async->scans_done >= cmd->stop_arg) {
1178                                async->events |= COMEDI_CB_EOA;
1179                                break;
1180                        }
1181                }
1182        } else if (status & PCIDAS_CTRL_EOAI) {
1183                irq_clr |= PCIDAS_CTRL_EOAI;
1184
1185                dev_err(dev->class_dev,
1186                        "bug! encountered end of acquisition interrupt?\n");
1187        }
1188
1189        /* check for fifo overflow */
1190        if (status & PCIDAS_CTRL_LADFUL) {
1191                irq_clr |= PCIDAS_CTRL_LADFUL;
1192
1193                dev_err(dev->class_dev, "fifo overflow\n");
1194                async->events |= COMEDI_CB_ERROR;
1195        }
1196
1197        comedi_handle_events(dev, s);
1198
1199        return irq_clr;
1200}
1201
1202static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1203{
1204        struct comedi_device *dev = d;
1205        struct cb_pcidas_private *devpriv = dev->private;
1206        unsigned int irq_clr = 0;
1207        unsigned int amcc_status;
1208        unsigned int status;
1209
1210        if (!dev->attached)
1211                return IRQ_NONE;
1212
1213        amcc_status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
1214
1215        if ((INTCSR_INTR_ASSERTED & amcc_status) == 0)
1216                return IRQ_NONE;
1217
1218        /*  make sure mailbox 4 is empty */
1219        inl_p(devpriv->amcc + AMCC_OP_REG_IMB4);
1220        /*  clear interrupt on amcc s5933 */
1221        outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
1222             devpriv->amcc + AMCC_OP_REG_INTCSR);
1223
1224        status = inw(devpriv->pcibar1 + PCIDAS_CTRL_REG);
1225
1226        /* handle analog output interrupts */
1227        if (status & PCIDAS_CTRL_AO_INT)
1228                irq_clr |= cb_pcidas_ao_interrupt(dev, status);
1229
1230        /* handle analog input interrupts */
1231        if (status & PCIDAS_CTRL_AI_INT)
1232                irq_clr |= cb_pcidas_ai_interrupt(dev, status);
1233
1234        if (irq_clr) {
1235                unsigned long flags;
1236
1237                spin_lock_irqsave(&dev->spinlock, flags);
1238                outw(devpriv->ctrl | irq_clr,
1239                     devpriv->pcibar1 + PCIDAS_CTRL_REG);
1240                spin_unlock_irqrestore(&dev->spinlock, flags);
1241        }
1242
1243        return IRQ_HANDLED;
1244}
1245
1246static int cb_pcidas_auto_attach(struct comedi_device *dev,
1247                                 unsigned long context)
1248{
1249        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1250        const struct cb_pcidas_board *board = NULL;
1251        struct cb_pcidas_private *devpriv;
1252        struct comedi_subdevice *s;
1253        int i;
1254        int ret;
1255
1256        if (context < ARRAY_SIZE(cb_pcidas_boards))
1257                board = &cb_pcidas_boards[context];
1258        if (!board)
1259                return -ENODEV;
1260        dev->board_ptr  = board;
1261        dev->board_name = board->name;
1262
1263        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1264        if (!devpriv)
1265                return -ENOMEM;
1266
1267        ret = comedi_pci_enable(dev);
1268        if (ret)
1269                return ret;
1270
1271        devpriv->amcc = pci_resource_start(pcidev, 0);
1272        devpriv->pcibar1 = pci_resource_start(pcidev, 1);
1273        devpriv->pcibar2 = pci_resource_start(pcidev, 2);
1274        dev->iobase = pci_resource_start(pcidev, 3);
1275        if (board->has_ao)
1276                devpriv->pcibar4 = pci_resource_start(pcidev, 4);
1277
1278        /*  disable and clear interrupts on amcc s5933 */
1279        outl(INTCSR_INBOX_INTR_STATUS,
1280             devpriv->amcc + AMCC_OP_REG_INTCSR);
1281
1282        ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
1283                          "cb_pcidas", dev);
1284        if (ret) {
1285                dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1286                        pcidev->irq);
1287                return ret;
1288        }
1289        dev->irq = pcidev->irq;
1290
1291        dev->pacer = comedi_8254_init(dev->iobase + PCIDAS_AI_8254_BASE,
1292                                      I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1293        if (!dev->pacer)
1294                return -ENOMEM;
1295
1296        devpriv->ao_pacer = comedi_8254_init(dev->iobase + PCIDAS_AO_8254_BASE,
1297                                             I8254_OSC_BASE_10MHZ,
1298                                             I8254_IO8, 0);
1299        if (!devpriv->ao_pacer)
1300                return -ENOMEM;
1301
1302        ret = comedi_alloc_subdevices(dev, 7);
1303        if (ret)
1304                return ret;
1305
1306        /* Analog Input subdevice */
1307        s = &dev->subdevices[0];
1308        s->type         = COMEDI_SUBD_AI;
1309        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF;
1310        s->n_chan       = 16;
1311        s->maxdata      = board->is_16bit ? 0xffff : 0x0fff;
1312        s->range_table  = board->use_alt_range ? &cb_pcidas_alt_ranges
1313                                               : &cb_pcidas_ranges;
1314        s->insn_read    = cb_pcidas_ai_insn_read;
1315        s->insn_config  = cb_pcidas_ai_insn_config;
1316        if (dev->irq) {
1317                dev->read_subdev = s;
1318                s->subdev_flags |= SDF_CMD_READ;
1319                s->len_chanlist = s->n_chan;
1320                s->do_cmd       = cb_pcidas_ai_cmd;
1321                s->do_cmdtest   = cb_pcidas_ai_cmdtest;
1322                s->cancel       = cb_pcidas_ai_cancel;
1323        }
1324
1325        /* Analog Output subdevice */
1326        s = &dev->subdevices[1];
1327        if (board->has_ao) {
1328                s->type         = COMEDI_SUBD_AO;
1329                s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1330                s->n_chan       = 2;
1331                s->maxdata      = board->is_16bit ? 0xffff : 0x0fff;
1332                s->range_table  = &cb_pcidas_ao_ranges;
1333                s->insn_write   = (board->has_ao_fifo)
1334                                        ? cb_pcidas_ao_fifo_insn_write
1335                                        : cb_pcidas_ao_nofifo_insn_write;
1336
1337                ret = comedi_alloc_subdev_readback(s);
1338                if (ret)
1339                        return ret;
1340
1341                if (dev->irq && board->has_ao_fifo) {
1342                        dev->write_subdev = s;
1343                        s->subdev_flags |= SDF_CMD_WRITE;
1344                        s->len_chanlist = s->n_chan;
1345                        s->do_cmdtest   = cb_pcidas_ao_cmdtest;
1346                        s->do_cmd       = cb_pcidas_ao_cmd;
1347                        s->cancel       = cb_pcidas_ao_cancel;
1348                }
1349        } else {
1350                s->type         = COMEDI_SUBD_UNUSED;
1351        }
1352
1353        /* 8255 */
1354        s = &dev->subdevices[2];
1355        ret = subdev_8255_init(dev, s, NULL, PCIDAS_8255_BASE);
1356        if (ret)
1357                return ret;
1358
1359        /* Memory subdevice - serial EEPROM */
1360        s = &dev->subdevices[3];
1361        s->type         = COMEDI_SUBD_MEMORY;
1362        s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1363        s->n_chan       = 256;
1364        s->maxdata      = 0xff;
1365        s->insn_read    = cb_pcidas_eeprom_insn_read;
1366
1367        /* Calibration subdevice - 8800 caldac */
1368        s = &dev->subdevices[4];
1369        s->type         = COMEDI_SUBD_CALIB;
1370        s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1371        s->n_chan       = 8;
1372        s->maxdata      = 0xff;
1373        s->insn_write   = cb_pcidas_caldac_insn_write;
1374
1375        ret = comedi_alloc_subdev_readback(s);
1376        if (ret)
1377                return ret;
1378
1379        for (i = 0; i < s->n_chan; i++) {
1380                unsigned int val = s->maxdata / 2;
1381
1382                /* write 11-bit channel/value to caldac */
1383                cb_pcidas_calib_write(dev, (i << 8) | val, 11, false);
1384                s->readback[i] = val;
1385        }
1386
1387        /* Calibration subdevice - trim potentiometer */
1388        s = &dev->subdevices[5];
1389        s->type         = COMEDI_SUBD_CALIB;
1390        s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1391        if (board->has_ad8402) {
1392                /*
1393                 * pci-das1602/16 have an AD8402 trimpot:
1394                 *   chan 0 : adc gain
1395                 *   chan 1 : adc postgain offset
1396                 */
1397                s->n_chan       = 2;
1398                s->maxdata      = 0xff;
1399        } else {
1400                /* all other boards have an AD7376 trimpot */
1401                s->n_chan       = 1;
1402                s->maxdata      = 0x7f;
1403        }
1404        s->insn_write   = cb_pcidas_trimpot_insn_write;
1405
1406        ret = comedi_alloc_subdev_readback(s);
1407        if (ret)
1408                return ret;
1409
1410        for (i = 0; i < s->n_chan; i++) {
1411                cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1412                s->readback[i] = s->maxdata / 2;
1413        }
1414
1415        /* Calibration subdevice - pci-das1602/16 pregain offset (dac08) */
1416        s = &dev->subdevices[6];
1417        if (board->has_dac08) {
1418                s->type         = COMEDI_SUBD_CALIB;
1419                s->subdev_flags = SDF_WRITABLE | SDF_INTERNAL;
1420                s->n_chan       = 1;
1421                s->maxdata      = 0xff;
1422                s->insn_write   = cb_pcidas_dac08_insn_write;
1423
1424                ret = comedi_alloc_subdev_readback(s);
1425                if (ret)
1426                        return ret;
1427
1428                for (i = 0; i < s->n_chan; i++) {
1429                        cb_pcidas_dac08_write(dev, s->maxdata / 2);
1430                        s->readback[i] = s->maxdata / 2;
1431                }
1432        } else {
1433                s->type         = COMEDI_SUBD_UNUSED;
1434        }
1435
1436        /*  make sure mailbox 4 is empty */
1437        inl(devpriv->amcc + AMCC_OP_REG_IMB4);
1438        /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1439        devpriv->amcc_intcsr = INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1440                               INTCSR_INBOX_FULL_INT;
1441        /*  clear and enable interrupt on amcc s5933 */
1442        outl(devpriv->amcc_intcsr | INTCSR_INBOX_INTR_STATUS,
1443             devpriv->amcc + AMCC_OP_REG_INTCSR);
1444
1445        return 0;
1446}
1447
1448static void cb_pcidas_detach(struct comedi_device *dev)
1449{
1450        struct cb_pcidas_private *devpriv = dev->private;
1451
1452        if (devpriv) {
1453                if (devpriv->amcc)
1454                        outl(INTCSR_INBOX_INTR_STATUS,
1455                             devpriv->amcc + AMCC_OP_REG_INTCSR);
1456                kfree(devpriv->ao_pacer);
1457        }
1458        comedi_pci_detach(dev);
1459}
1460
1461static struct comedi_driver cb_pcidas_driver = {
1462        .driver_name    = "cb_pcidas",
1463        .module         = THIS_MODULE,
1464        .auto_attach    = cb_pcidas_auto_attach,
1465        .detach         = cb_pcidas_detach,
1466};
1467
1468static int cb_pcidas_pci_probe(struct pci_dev *dev,
1469                               const struct pci_device_id *id)
1470{
1471        return comedi_pci_auto_config(dev, &cb_pcidas_driver,
1472                                      id->driver_data);
1473}
1474
1475static const struct pci_device_id cb_pcidas_pci_table[] = {
1476        { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 },
1477        { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 },
1478        { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 },
1479        { PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR },
1480        { PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR },
1481        { PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 },
1482        { PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 },
1483        { PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 },
1484        { 0 }
1485};
1486MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
1487
1488static struct pci_driver cb_pcidas_pci_driver = {
1489        .name           = "cb_pcidas",
1490        .id_table       = cb_pcidas_pci_table,
1491        .probe          = cb_pcidas_pci_probe,
1492        .remove         = comedi_pci_auto_unconfig,
1493};
1494module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
1495
1496MODULE_AUTHOR("Comedi https://www.comedi.org");
1497MODULE_DESCRIPTION("Comedi driver for MeasurementComputing PCI-DAS series");
1498MODULE_LICENSE("GPL");
1499