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