linux/drivers/staging/comedi/drivers/das1800.c
<<
>>
Prefs
   1/*
   2 * Comedi driver for Keithley DAS-1700/DAS-1800 series boards
   3 * Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
   4 *
   5 * COMEDI - Linux Control and Measurement Device Interface
   6 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License as published by
  10 * the Free Software Foundation; either version 2 of the License, or
  11 * (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 */
  18
  19/*
  20 * Driver: das1800
  21 * Description: Keithley Metrabyte DAS1800 (& compatibles)
  22 * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
  23 * Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
  24 *   DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
  25 *   DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
  26 *   DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
  27 *   DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
  28 *   DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
  29 *   DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
  30 *   DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
  31 *   DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
  32 *   DAS-1802AO (das-1802ao)
  33 * Status: works
  34 *
  35 * Configuration options:
  36 *   [0] - I/O port base address
  37 *   [1] - IRQ (optional, required for analog input cmd support)
  38 *   [2] - DMA0 (optional, requires irq)
  39 *   [3] - DMA1 (optional, requires irq and dma0)
  40 *
  41 * analog input cmd triggers supported:
  42 *
  43 *   start_src          TRIG_NOW        command starts immediately
  44 *                      TRIG_EXT        command starts on external pin TGIN
  45 *
  46 *   scan_begin_src     TRIG_FOLLOW     paced/external scans start immediately
  47 *                      TRIG_TIMER      burst scans start periodically
  48 *                      TRIG_EXT        burst scans start on external pin XPCLK
  49 *
  50 *   scan_end_src       TRIG_COUNT      scan ends after last channel
  51 *
  52 *   convert_src        TRIG_TIMER      paced/burst conversions are timed
  53 *                      TRIG_EXT        conversions on external pin XPCLK
  54 *                                      (requires scan_begin_src == TRIG_FOLLOW)
  55 *
  56 *   stop_src           TRIG_COUNT      command stops after stop_arg scans
  57 *                      TRIG_EXT        command stops on external pin TGIN
  58 *                      TRIG_NONE       command runs until canceled
  59 *
  60 * If TRIG_EXT is used for both the start_src and stop_src, the first TGIN
  61 * trigger starts the command, and the second trigger will stop it. If only
  62 * one is TRIG_EXT, the first trigger will either stop or start the command.
  63 * The external pin TGIN is normally set for negative edge triggering. It
  64 * can be set to positive edge with the CR_INVERT flag. If TRIG_EXT is used
  65 * for both the start_src and stop_src they must have the same polarity.
  66 *
  67 * Minimum conversion speed is limited to 64 microseconds (convert_arg <= 64000)
  68 * for 'burst' scans. This limitation does not apply for 'paced' scans. The
  69 * maximum conversion speed is limited by the board (convert_arg >= ai_speed).
  70 * Maximum conversion speeds are not always achievable depending on the
  71 * board setup (see user manual).
  72 *
  73 * NOTES:
  74 * Only the DAS-1801ST has been tested by me.
  75 * Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
  76 *
  77 * The waveform analog output on the 'ao' cards is not supported.
  78 * If you need it, send me (Frank Hess) an email.
  79 */
  80
  81#include <linux/module.h>
  82#include <linux/interrupt.h>
  83#include <linux/slab.h>
  84#include <linux/io.h>
  85
  86#include "../comedidev.h"
  87
  88#include "comedi_isadma.h"
  89#include "comedi_8254.h"
  90
  91/* misc. defines */
  92#define DAS1800_SIZE           16       /* uses 16 io addresses */
  93#define FIFO_SIZE              1024     /*  1024 sample fifo */
  94#define DMA_BUF_SIZE           0x1ff00  /*  size in bytes of dma buffers */
  95
  96/* Registers for the das1800 */
  97#define DAS1800_FIFO            0x0
  98#define DAS1800_QRAM            0x0
  99#define DAS1800_DAC             0x0
 100#define DAS1800_SELECT          0x2
 101#define   ADC                     0x0
 102#define   QRAM                    0x1
 103#define   DAC(a)                  (0x2 + a)
 104#define DAS1800_DIGITAL         0x3
 105#define DAS1800_CONTROL_A       0x4
 106#define   FFEN                    0x1
 107#define   CGEN                    0x4
 108#define   CGSL                    0x8
 109#define   TGEN                    0x10
 110#define   TGSL                    0x20
 111#define   TGPL                    0x40
 112#define   ATEN                    0x80
 113#define DAS1800_CONTROL_B       0x5
 114#define   DMA_CH5                 0x1
 115#define   DMA_CH6                 0x2
 116#define   DMA_CH7                 0x3
 117#define   DMA_CH5_CH6             0x5
 118#define   DMA_CH6_CH7             0x6
 119#define   DMA_CH7_CH5             0x7
 120#define   DMA_ENABLED             0x3
 121#define   DMA_DUAL                0x4
 122#define   IRQ3                    0x8
 123#define   IRQ5                    0x10
 124#define   IRQ7                    0x18
 125#define   IRQ10                   0x28
 126#define   IRQ11                   0x30
 127#define   IRQ15                   0x38
 128#define   FIMD                    0x40
 129#define DAS1800_CONTROL_C       0X6
 130#define   IPCLK                   0x1
 131#define   XPCLK                   0x3
 132#define   BMDE                    0x4
 133#define   CMEN                    0x8
 134#define   UQEN                    0x10
 135#define   SD                      0x40
 136#define   UB                      0x80
 137#define DAS1800_STATUS          0x7
 138#define   INT                     0x1
 139#define   DMATC                   0x2
 140#define   CT0TC                   0x8
 141#define   OVF                     0x10
 142#define   FHF                     0x20
 143#define   FNE                     0x40
 144#define   CVEN                    0x80
 145#define   CVEN_MASK               0x40
 146#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
 147#define DAS1800_BURST_LENGTH    0x8
 148#define DAS1800_BURST_RATE      0x9
 149#define DAS1800_QRAM_ADDRESS    0xa
 150#define DAS1800_COUNTER         0xc
 151
 152#define IOBASE2                   0x400
 153
 154static const struct comedi_lrange das1801_ai_range = {
 155        8, {
 156                BIP_RANGE(5),           /* bipolar gain = 1 */
 157                BIP_RANGE(1),           /* bipolar gain = 10 */
 158                BIP_RANGE(0.1),         /* bipolar gain = 50 */
 159                BIP_RANGE(0.02),        /* bipolar gain = 250 */
 160                UNI_RANGE(5),           /* unipolar gain = 1 */
 161                UNI_RANGE(1),           /* unipolar gain = 10 */
 162                UNI_RANGE(0.1),         /* unipolar gain = 50 */
 163                UNI_RANGE(0.02)         /* unipolar gain = 250 */
 164        }
 165};
 166
 167static const struct comedi_lrange das1802_ai_range = {
 168        8, {
 169                BIP_RANGE(10),          /* bipolar gain = 1 */
 170                BIP_RANGE(5),           /* bipolar gain = 2 */
 171                BIP_RANGE(2.5),         /* bipolar gain = 4 */
 172                BIP_RANGE(1.25),        /* bipolar gain = 8 */
 173                UNI_RANGE(10),          /* unipolar gain = 1 */
 174                UNI_RANGE(5),           /* unipolar gain = 2 */
 175                UNI_RANGE(2.5),         /* unipolar gain = 4 */
 176                UNI_RANGE(1.25)         /* unipolar gain = 8 */
 177        }
 178};
 179
 180/*
 181 * The waveform analog outputs on the 'ao' boards are not currently
 182 * supported. They have a comedi_lrange of:
 183 * { 2, { BIP_RANGE(10), BIP_RANGE(5) } }
 184 */
 185
 186enum das1800_boardid {
 187        BOARD_DAS1701ST,
 188        BOARD_DAS1701ST_DA,
 189        BOARD_DAS1702ST,
 190        BOARD_DAS1702ST_DA,
 191        BOARD_DAS1702HR,
 192        BOARD_DAS1702HR_DA,
 193        BOARD_DAS1701AO,
 194        BOARD_DAS1702AO,
 195        BOARD_DAS1801ST,
 196        BOARD_DAS1801ST_DA,
 197        BOARD_DAS1802ST,
 198        BOARD_DAS1802ST_DA,
 199        BOARD_DAS1802HR,
 200        BOARD_DAS1802HR_DA,
 201        BOARD_DAS1801HC,
 202        BOARD_DAS1802HC,
 203        BOARD_DAS1801AO,
 204        BOARD_DAS1802AO
 205};
 206
 207/* board probe id values (hi byte of the digital input register) */
 208#define DAS1800_ID_ST_DA                0x3
 209#define DAS1800_ID_HR_DA                0x4
 210#define DAS1800_ID_AO                   0x5
 211#define DAS1800_ID_HR                   0x6
 212#define DAS1800_ID_ST                   0x7
 213#define DAS1800_ID_HC                   0x8
 214
 215struct das1800_board {
 216        const char *name;
 217        unsigned char id;
 218        unsigned int ai_speed;
 219        unsigned int is_01_series:1;
 220};
 221
 222static const struct das1800_board das1800_boards[] = {
 223        [BOARD_DAS1701ST] = {
 224                .name           = "das-1701st",
 225                .id             = DAS1800_ID_ST,
 226                .ai_speed       = 6250,
 227                .is_01_series   = 1,
 228        },
 229        [BOARD_DAS1701ST_DA] = {
 230                .name           = "das-1701st-da",
 231                .id             = DAS1800_ID_ST_DA,
 232                .ai_speed       = 6250,
 233                .is_01_series   = 1,
 234        },
 235        [BOARD_DAS1702ST] = {
 236                .name           = "das-1702st",
 237                .id             = DAS1800_ID_ST,
 238                .ai_speed       = 6250,
 239        },
 240        [BOARD_DAS1702ST_DA] = {
 241                .name           = "das-1702st-da",
 242                .id             = DAS1800_ID_ST_DA,
 243                .ai_speed       = 6250,
 244        },
 245        [BOARD_DAS1702HR] = {
 246                .name           = "das-1702hr",
 247                .id             = DAS1800_ID_HR,
 248                .ai_speed       = 20000,
 249        },
 250        [BOARD_DAS1702HR_DA] = {
 251                .name           = "das-1702hr-da",
 252                .id             = DAS1800_ID_HR_DA,
 253                .ai_speed       = 20000,
 254        },
 255        [BOARD_DAS1701AO] = {
 256                .name           = "das-1701ao",
 257                .id             = DAS1800_ID_AO,
 258                .ai_speed       = 6250,
 259                .is_01_series   = 1,
 260        },
 261        [BOARD_DAS1702AO] = {
 262                .name           = "das-1702ao",
 263                .id             = DAS1800_ID_AO,
 264                .ai_speed       = 6250,
 265        },
 266        [BOARD_DAS1801ST] = {
 267                .name           = "das-1801st",
 268                .id             = DAS1800_ID_ST,
 269                .ai_speed       = 3000,
 270                .is_01_series   = 1,
 271        },
 272        [BOARD_DAS1801ST_DA] = {
 273                .name           = "das-1801st-da",
 274                .id             = DAS1800_ID_ST_DA,
 275                .ai_speed       = 3000,
 276                .is_01_series   = 1,
 277        },
 278        [BOARD_DAS1802ST] = {
 279                .name           = "das-1802st",
 280                .id             = DAS1800_ID_ST,
 281                .ai_speed       = 3000,
 282        },
 283        [BOARD_DAS1802ST_DA] = {
 284                .name           = "das-1802st-da",
 285                .id             = DAS1800_ID_ST_DA,
 286                .ai_speed       = 3000,
 287        },
 288        [BOARD_DAS1802HR] = {
 289                .name           = "das-1802hr",
 290                .id             = DAS1800_ID_HR,
 291                .ai_speed       = 10000,
 292        },
 293        [BOARD_DAS1802HR_DA] = {
 294                .name           = "das-1802hr-da",
 295                .id             = DAS1800_ID_HR_DA,
 296                .ai_speed       = 10000,
 297        },
 298        [BOARD_DAS1801HC] = {
 299                .name           = "das-1801hc",
 300                .id             = DAS1800_ID_HC,
 301                .ai_speed       = 3000,
 302                .is_01_series   = 1,
 303        },
 304        [BOARD_DAS1802HC] = {
 305                .name           = "das-1802hc",
 306                .id             = DAS1800_ID_HC,
 307                .ai_speed       = 3000,
 308        },
 309        [BOARD_DAS1801AO] = {
 310                .name           = "das-1801ao",
 311                .id             = DAS1800_ID_AO,
 312                .ai_speed       = 3000,
 313                .is_01_series   = 1,
 314        },
 315        [BOARD_DAS1802AO] = {
 316                .name           = "das-1802ao",
 317                .id             = DAS1800_ID_AO,
 318                .ai_speed       = 3000,
 319        },
 320};
 321
 322struct das1800_private {
 323        struct comedi_isadma *dma;
 324        int irq_dma_bits;
 325        int dma_bits;
 326        unsigned short *fifo_buf;
 327        unsigned long iobase2;
 328        bool ai_is_unipolar;
 329};
 330
 331static void das1800_ai_munge(struct comedi_device *dev,
 332                             struct comedi_subdevice *s,
 333                             void *data, unsigned int num_bytes,
 334                             unsigned int start_chan_index)
 335{
 336        struct das1800_private *devpriv = dev->private;
 337        unsigned short *array = data;
 338        unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
 339        unsigned int i;
 340
 341        if (devpriv->ai_is_unipolar)
 342                return;
 343
 344        for (i = 0; i < num_samples; i++)
 345                array[i] = comedi_offset_munge(s, array[i]);
 346}
 347
 348static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 349                                          struct comedi_subdevice *s)
 350{
 351        struct das1800_private *devpriv = dev->private;
 352        unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
 353
 354        insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
 355        comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
 356}
 357
 358static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 359                                          struct comedi_subdevice *s)
 360{
 361        struct comedi_cmd *cmd = &s->async->cmd;
 362        unsigned short dpnt;
 363
 364        while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
 365                dpnt = inw(dev->iobase + DAS1800_FIFO);
 366                comedi_buf_write_samples(s, &dpnt, 1);
 367
 368                if (cmd->stop_src == TRIG_COUNT &&
 369                    s->async->scans_done >= cmd->stop_arg)
 370                        break;
 371        }
 372}
 373
 374static void das1800_flush_dma_channel(struct comedi_device *dev,
 375                                      struct comedi_subdevice *s,
 376                                      struct comedi_isadma_desc *desc)
 377{
 378        unsigned int residue = comedi_isadma_disable(desc->chan);
 379        unsigned int nbytes = desc->size - residue;
 380        unsigned int nsamples;
 381
 382        /*  figure out how many points to read */
 383        nsamples = comedi_bytes_to_samples(s, nbytes);
 384        nsamples = comedi_nsamples_left(s, nsamples);
 385
 386        comedi_buf_write_samples(s, desc->virt_addr, nsamples);
 387}
 388
 389static void das1800_flush_dma(struct comedi_device *dev,
 390                              struct comedi_subdevice *s)
 391{
 392        struct das1800_private *devpriv = dev->private;
 393        struct comedi_isadma *dma = devpriv->dma;
 394        struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 395        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 396
 397        das1800_flush_dma_channel(dev, s, desc);
 398
 399        if (dual_dma) {
 400                /*  switch to other channel and flush it */
 401                dma->cur_dma = 1 - dma->cur_dma;
 402                desc = &dma->desc[dma->cur_dma];
 403                das1800_flush_dma_channel(dev, s, desc);
 404        }
 405
 406        /*  get any remaining samples in fifo */
 407        das1800_handle_fifo_not_empty(dev, s);
 408}
 409
 410static void das1800_handle_dma(struct comedi_device *dev,
 411                               struct comedi_subdevice *s, unsigned int status)
 412{
 413        struct das1800_private *devpriv = dev->private;
 414        struct comedi_isadma *dma = devpriv->dma;
 415        struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 416        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 417
 418        das1800_flush_dma_channel(dev, s, desc);
 419
 420        /* re-enable dma channel */
 421        comedi_isadma_program(desc);
 422
 423        if (status & DMATC) {
 424                /*  clear DMATC interrupt bit */
 425                outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
 426                /*  switch dma channels for next time, if appropriate */
 427                if (dual_dma)
 428                        dma->cur_dma = 1 - dma->cur_dma;
 429        }
 430}
 431
 432static int das1800_ai_cancel(struct comedi_device *dev,
 433                             struct comedi_subdevice *s)
 434{
 435        struct das1800_private *devpriv = dev->private;
 436        struct comedi_isadma *dma = devpriv->dma;
 437        struct comedi_isadma_desc *desc;
 438        int i;
 439
 440        /* disable and stop conversions */
 441        outb(0x0, dev->iobase + DAS1800_STATUS);
 442        outb(0x0, dev->iobase + DAS1800_CONTROL_B);
 443        outb(0x0, dev->iobase + DAS1800_CONTROL_A);
 444
 445        if (dma) {
 446                for (i = 0; i < 2; i++) {
 447                        desc = &dma->desc[i];
 448                        if (desc->chan)
 449                                comedi_isadma_disable(desc->chan);
 450                }
 451        }
 452
 453        return 0;
 454}
 455
 456static void das1800_ai_handler(struct comedi_device *dev)
 457{
 458        struct das1800_private *devpriv = dev->private;
 459        struct comedi_subdevice *s = dev->read_subdev;
 460        struct comedi_async *async = s->async;
 461        struct comedi_cmd *cmd = &async->cmd;
 462        unsigned int status = inb(dev->iobase + DAS1800_STATUS);
 463
 464        /* select adc register (spinlock is already held) */
 465        outb(ADC, dev->iobase + DAS1800_SELECT);
 466
 467        /* get samples with dma, fifo, or polled as necessary */
 468        if (devpriv->irq_dma_bits & DMA_ENABLED)
 469                das1800_handle_dma(dev, s, status);
 470        else if (status & FHF)
 471                das1800_handle_fifo_half_full(dev, s);
 472        else if (status & FNE)
 473                das1800_handle_fifo_not_empty(dev, s);
 474
 475        /* if the card's fifo has overflowed */
 476        if (status & OVF) {
 477                /*  clear OVF interrupt bit */
 478                outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
 479                dev_err(dev->class_dev, "FIFO overflow\n");
 480                async->events |= COMEDI_CB_ERROR;
 481                comedi_handle_events(dev, s);
 482                return;
 483        }
 484        /*  stop taking data if appropriate */
 485        /* stop_src TRIG_EXT */
 486        if (status & CT0TC) {
 487                /*  clear CT0TC interrupt bit */
 488                outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
 489                /* get all remaining samples before quitting */
 490                if (devpriv->irq_dma_bits & DMA_ENABLED)
 491                        das1800_flush_dma(dev, s);
 492                else
 493                        das1800_handle_fifo_not_empty(dev, s);
 494                async->events |= COMEDI_CB_EOA;
 495        } else if (cmd->stop_src == TRIG_COUNT &&
 496                   async->scans_done >= cmd->stop_arg) {
 497                async->events |= COMEDI_CB_EOA;
 498        }
 499
 500        comedi_handle_events(dev, s);
 501}
 502
 503static int das1800_ai_poll(struct comedi_device *dev,
 504                           struct comedi_subdevice *s)
 505{
 506        unsigned long flags;
 507
 508        /*
 509         * Protects the indirect addressing selected by DAS1800_SELECT
 510         * in das1800_ai_handler() also prevents race with das1800_interrupt().
 511         */
 512        spin_lock_irqsave(&dev->spinlock, flags);
 513
 514        das1800_ai_handler(dev);
 515
 516        spin_unlock_irqrestore(&dev->spinlock, flags);
 517
 518        return comedi_buf_n_bytes_ready(s);
 519}
 520
 521static irqreturn_t das1800_interrupt(int irq, void *d)
 522{
 523        struct comedi_device *dev = d;
 524        unsigned int status;
 525
 526        if (!dev->attached) {
 527                dev_err(dev->class_dev, "premature interrupt\n");
 528                return IRQ_HANDLED;
 529        }
 530
 531        /*
 532         * Protects the indirect addressing selected by DAS1800_SELECT
 533         * in das1800_ai_handler() also prevents race with das1800_ai_poll().
 534         */
 535        spin_lock(&dev->spinlock);
 536
 537        status = inb(dev->iobase + DAS1800_STATUS);
 538
 539        /* if interrupt was not caused by das-1800 */
 540        if (!(status & INT)) {
 541                spin_unlock(&dev->spinlock);
 542                return IRQ_NONE;
 543        }
 544        /* clear the interrupt status bit INT */
 545        outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
 546        /*  handle interrupt */
 547        das1800_ai_handler(dev);
 548
 549        spin_unlock(&dev->spinlock);
 550        return IRQ_HANDLED;
 551}
 552
 553static int das1800_ai_fixup_paced_timing(struct comedi_device *dev,
 554                                         struct comedi_cmd *cmd)
 555{
 556        unsigned int arg = cmd->convert_arg;
 557
 558        /*
 559         * Paced mode:
 560         *      scan_begin_src is TRIG_FOLLOW
 561         *      convert_src is TRIG_TIMER
 562         *
 563         * The convert_arg sets the pacer sample acquisition time.
 564         * The max acquisition speed is limited to the boards
 565         * 'ai_speed' (this was already verified). The min speed is
 566         * limited by the cascaded 8254 timer.
 567         */
 568        comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 569        return comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 570}
 571
 572static int das1800_ai_fixup_burst_timing(struct comedi_device *dev,
 573                                         struct comedi_cmd *cmd)
 574{
 575        unsigned int arg = cmd->convert_arg;
 576        int err = 0;
 577
 578        /*
 579         * Burst mode:
 580         *      scan_begin_src is TRIG_TIMER or TRIG_EXT
 581         *      convert_src is TRIG_TIMER
 582         *
 583         * The convert_arg sets burst sample acquisition time.
 584         * The max acquisition speed is limited to the boards
 585         * 'ai_speed' (this was already verified). The min speed is
 586         * limiited to 64 microseconds,
 587         */
 588        err |= comedi_check_trigger_arg_max(&arg, 64000);
 589
 590        /* round to microseconds then verify */
 591        switch (cmd->flags & CMDF_ROUND_MASK) {
 592        case CMDF_ROUND_NEAREST:
 593        default:
 594                arg = DIV_ROUND_CLOSEST(arg, 1000);
 595                break;
 596        case CMDF_ROUND_DOWN:
 597                arg = arg / 1000;
 598                break;
 599        case CMDF_ROUND_UP:
 600                arg = DIV_ROUND_UP(arg, 1000);
 601                break;
 602        }
 603        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg * 1000);
 604
 605        /*
 606         * The pacer can be used to set the scan sample rate. The max scan
 607         * speed is limited by the conversion speed and the number of channels
 608         * to convert. The min speed is limited by the cascaded 8254 timer.
 609         */
 610        if (cmd->scan_begin_src == TRIG_TIMER) {
 611                arg = cmd->convert_arg * cmd->chanlist_len;
 612                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 613
 614                arg = cmd->scan_begin_arg;
 615                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 616                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 617        }
 618
 619        return err;
 620}
 621
 622static int das1800_ai_check_chanlist(struct comedi_device *dev,
 623                                     struct comedi_subdevice *s,
 624                                     struct comedi_cmd *cmd)
 625{
 626        unsigned int range = CR_RANGE(cmd->chanlist[0]);
 627        bool unipolar0 = comedi_range_is_unipolar(s, range);
 628        int i;
 629
 630        for (i = 1; i < cmd->chanlist_len; i++) {
 631                range = CR_RANGE(cmd->chanlist[i]);
 632
 633                if (unipolar0 != comedi_range_is_unipolar(s, range)) {
 634                        dev_dbg(dev->class_dev,
 635                                "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
 636                        return -EINVAL;
 637                }
 638        }
 639
 640        return 0;
 641}
 642
 643static int das1800_ai_cmdtest(struct comedi_device *dev,
 644                              struct comedi_subdevice *s,
 645                              struct comedi_cmd *cmd)
 646{
 647        const struct das1800_board *board = dev->board_ptr;
 648        int err = 0;
 649
 650        /* Step 1 : check if triggers are trivially valid */
 651
 652        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 653        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 654                                        TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
 655        err |= comedi_check_trigger_src(&cmd->convert_src,
 656                                        TRIG_TIMER | TRIG_EXT);
 657        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 658        err |= comedi_check_trigger_src(&cmd->stop_src,
 659                                        TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 660
 661        if (err)
 662                return 1;
 663
 664        /* Step 2a : make sure trigger sources are unique */
 665
 666        err |= comedi_check_trigger_is_unique(cmd->start_src);
 667        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 668        err |= comedi_check_trigger_is_unique(cmd->convert_src);
 669        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 670
 671        /* Step 2b : and mutually compatible */
 672
 673        /* burst scans must use timed conversions */
 674        if (cmd->scan_begin_src != TRIG_FOLLOW &&
 675            cmd->convert_src != TRIG_TIMER)
 676                err |= -EINVAL;
 677
 678        /* the external pin TGIN must use the same polarity */
 679        if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
 680                err |= comedi_check_trigger_arg_is(&cmd->start_arg,
 681                                                   cmd->stop_arg);
 682
 683        if (err)
 684                return 2;
 685
 686        /* Step 3: check if arguments are trivially valid */
 687
 688        if (cmd->start_arg == TRIG_NOW)
 689                err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 690
 691        if (cmd->convert_src == TRIG_TIMER) {
 692                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 693                                                    board->ai_speed);
 694        }
 695
 696        err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
 697        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 698                                           cmd->chanlist_len);
 699
 700        switch (cmd->stop_src) {
 701        case TRIG_COUNT:
 702                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 703                break;
 704        case TRIG_NONE:
 705                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 706                break;
 707        default:
 708                break;
 709        }
 710
 711        if (err)
 712                return 3;
 713
 714        /* Step 4: fix up any arguments */
 715
 716        if (cmd->convert_src == TRIG_TIMER) {
 717                if (cmd->scan_begin_src == TRIG_FOLLOW)
 718                        err |= das1800_ai_fixup_paced_timing(dev, cmd);
 719                else /* TRIG_TIMER or TRIG_EXT */
 720                        err |= das1800_ai_fixup_burst_timing(dev, cmd);
 721        }
 722
 723        if (err)
 724                return 4;
 725
 726        /* Step 5: check channel list if it exists */
 727        if (cmd->chanlist && cmd->chanlist_len > 0)
 728                err |= das1800_ai_check_chanlist(dev, s, cmd);
 729
 730        if (err)
 731                return 5;
 732
 733        return 0;
 734}
 735
 736static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s,
 737                                              unsigned int chanspec)
 738{
 739        unsigned int range = CR_RANGE(chanspec);
 740        unsigned int aref = CR_AREF(chanspec);
 741        unsigned char bits;
 742
 743        bits = UQEN;
 744        if (aref != AREF_DIFF)
 745                bits |= SD;
 746        if (aref == AREF_COMMON)
 747                bits |= CMEN;
 748        if (comedi_range_is_unipolar(s, range))
 749                bits |= UB;
 750
 751        return bits;
 752}
 753
 754static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
 755                                             struct comedi_subdevice *s,
 756                                             unsigned int maxbytes,
 757                                             unsigned int ns)
 758{
 759        struct comedi_cmd *cmd = &s->async->cmd;
 760        unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
 761        unsigned int samples;
 762
 763        samples = max_samples;
 764
 765        /* for timed modes, make dma buffer fill in 'ns' time */
 766        switch (cmd->scan_begin_src) {
 767        case TRIG_FOLLOW:       /* not in burst mode */
 768                if (cmd->convert_src == TRIG_TIMER)
 769                        samples = ns / cmd->convert_arg;
 770                break;
 771        case TRIG_TIMER:
 772                samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
 773                break;
 774        }
 775
 776        /* limit samples to what is remaining in the command */
 777        samples = comedi_nsamples_left(s, samples);
 778
 779        if (samples > max_samples)
 780                samples = max_samples;
 781        if (samples < 1)
 782                samples = 1;
 783
 784        return comedi_samples_to_bytes(s, samples);
 785}
 786
 787static void das1800_ai_setup_dma(struct comedi_device *dev,
 788                                 struct comedi_subdevice *s)
 789{
 790        struct das1800_private *devpriv = dev->private;
 791        struct comedi_isadma *dma = devpriv->dma;
 792        struct comedi_isadma_desc *desc;
 793        unsigned int bytes;
 794
 795        if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
 796                return;
 797
 798        dma->cur_dma = 0;
 799        desc = &dma->desc[0];
 800
 801        /* determine a dma transfer size to fill buffer in 0.3 sec */
 802        bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
 803
 804        desc->size = bytes;
 805        comedi_isadma_program(desc);
 806
 807        /* set up dual dma if appropriate */
 808        if (devpriv->irq_dma_bits & DMA_DUAL) {
 809                desc = &dma->desc[1];
 810                desc->size = bytes;
 811                comedi_isadma_program(desc);
 812        }
 813}
 814
 815static void das1800_ai_set_chanlist(struct comedi_device *dev,
 816                                    unsigned int *chanlist, unsigned int len)
 817{
 818        unsigned long flags;
 819        unsigned int i;
 820
 821        /* protects the indirect addressing selected by DAS1800_SELECT */
 822        spin_lock_irqsave(&dev->spinlock, flags);
 823
 824        /* select QRAM register and set start address */
 825        outb(QRAM, dev->iobase + DAS1800_SELECT);
 826        outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
 827
 828        /* make channel / gain list */
 829        for (i = 0; i < len; i++) {
 830                unsigned int chan = CR_CHAN(chanlist[i]);
 831                unsigned int range = CR_RANGE(chanlist[i]);
 832                unsigned short val;
 833
 834                val = chan | ((range & 0x3) << 8);
 835                outw(val, dev->iobase + DAS1800_QRAM);
 836        }
 837
 838        /* finish write to QRAM */
 839        outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
 840
 841        spin_unlock_irqrestore(&dev->spinlock, flags);
 842}
 843
 844static int das1800_ai_cmd(struct comedi_device *dev,
 845                          struct comedi_subdevice *s)
 846{
 847        struct das1800_private *devpriv = dev->private;
 848        int control_a, control_c;
 849        struct comedi_async *async = s->async;
 850        const struct comedi_cmd *cmd = &async->cmd;
 851        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 852
 853        /*
 854         * Disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY (because dma in
 855         * handler is unsafe at hard real-time priority).
 856         */
 857        if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
 858                devpriv->irq_dma_bits &= ~DMA_ENABLED;
 859        else
 860                devpriv->irq_dma_bits |= devpriv->dma_bits;
 861        /*  interrupt on end of conversion for CMDF_WAKE_EOS */
 862        if (cmd->flags & CMDF_WAKE_EOS) {
 863                /*  interrupt fifo not empty */
 864                devpriv->irq_dma_bits &= ~FIMD;
 865        } else {
 866                /*  interrupt fifo half full */
 867                devpriv->irq_dma_bits |= FIMD;
 868        }
 869
 870        das1800_ai_cancel(dev, s);
 871
 872        devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0);
 873
 874        control_a = FFEN;
 875        if (cmd->stop_src == TRIG_EXT)
 876                control_a |= ATEN;
 877        if (cmd->start_src == TRIG_EXT)
 878                control_a |= TGEN | CGSL;
 879        else /* TRIG_NOW */
 880                control_a |= CGEN;
 881        if (control_a & (ATEN | TGEN)) {
 882                if ((cmd->start_arg & CR_INVERT) || (cmd->stop_arg & CR_INVERT))
 883                        control_a |= TGPL;
 884        }
 885
 886        control_c = das1800_ai_chanspec_bits(s, cmd->chanlist[0]);
 887        /* set clock source to internal or external */
 888        if (cmd->scan_begin_src == TRIG_FOLLOW) {
 889                /* not in burst mode */
 890                if (cmd->convert_src == TRIG_TIMER) {
 891                        /* trig on cascaded counters */
 892                        control_c |= IPCLK;
 893                } else { /* TRIG_EXT */
 894                        /* trig on falling edge of external trigger */
 895                        control_c |= XPCLK;
 896                }
 897        } else if (cmd->scan_begin_src == TRIG_TIMER) {
 898                /* burst mode with internal pacer clock */
 899                control_c |= BMDE | IPCLK;
 900        } else { /* TRIG_EXT */
 901                /* burst mode with external trigger */
 902                control_c |= BMDE | XPCLK;
 903        }
 904
 905        das1800_ai_set_chanlist(dev, cmd->chanlist, cmd->chanlist_len);
 906
 907        /* setup cascaded counters for conversion/scan frequency */
 908        if ((cmd->scan_begin_src == TRIG_FOLLOW ||
 909             cmd->scan_begin_src == TRIG_TIMER) &&
 910            cmd->convert_src == TRIG_TIMER) {
 911                comedi_8254_update_divisors(dev->pacer);
 912                comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 913        }
 914
 915        /* setup counter 0 for 'about triggering' */
 916        if (cmd->stop_src == TRIG_EXT)
 917                comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
 918
 919        das1800_ai_setup_dma(dev, s);
 920        outb(control_c, dev->iobase + DAS1800_CONTROL_C);
 921        /*  set conversion rate and length for burst mode */
 922        if (control_c & BMDE) {
 923                outb(cmd->convert_arg / 1000 - 1,       /* microseconds - 1 */
 924                     dev->iobase + DAS1800_BURST_RATE);
 925                outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
 926        }
 927
 928        /* enable and start conversions */
 929        outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);
 930        outb(control_a, dev->iobase + DAS1800_CONTROL_A);
 931        outb(CVEN, dev->iobase + DAS1800_STATUS);
 932
 933        return 0;
 934}
 935
 936static int das1800_ai_eoc(struct comedi_device *dev,
 937                          struct comedi_subdevice *s,
 938                          struct comedi_insn *insn,
 939                          unsigned long context)
 940{
 941        unsigned char status;
 942
 943        status = inb(dev->iobase + DAS1800_STATUS);
 944        if (status & FNE)
 945                return 0;
 946        return -EBUSY;
 947}
 948
 949static int das1800_ai_insn_read(struct comedi_device *dev,
 950                                struct comedi_subdevice *s,
 951                                struct comedi_insn *insn,
 952                                unsigned int *data)
 953{
 954        unsigned int range = CR_RANGE(insn->chanspec);
 955        bool is_unipolar = comedi_range_is_unipolar(s, range);
 956        int ret = 0;
 957        int n;
 958        unsigned short dpnt;
 959        unsigned long flags;
 960
 961        outb(das1800_ai_chanspec_bits(s, insn->chanspec),
 962             dev->iobase + DAS1800_CONTROL_C);          /* software pacer */
 963        outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
 964        outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* reset fifo */
 965        outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
 966
 967        das1800_ai_set_chanlist(dev, &insn->chanspec, 1);
 968
 969        /* protects the indirect addressing selected by DAS1800_SELECT */
 970        spin_lock_irqsave(&dev->spinlock, flags);
 971
 972        /* select ai fifo register */
 973        outb(ADC, dev->iobase + DAS1800_SELECT);
 974
 975        for (n = 0; n < insn->n; n++) {
 976                /* trigger conversion */
 977                outb(0, dev->iobase + DAS1800_FIFO);
 978
 979                ret = comedi_timeout(dev, s, insn, das1800_ai_eoc, 0);
 980                if (ret)
 981                        break;
 982
 983                dpnt = inw(dev->iobase + DAS1800_FIFO);
 984                if (!is_unipolar)
 985                        dpnt = comedi_offset_munge(s, dpnt);
 986                data[n] = dpnt;
 987        }
 988        spin_unlock_irqrestore(&dev->spinlock, flags);
 989
 990        return ret ? ret : insn->n;
 991}
 992
 993static int das1800_ao_insn_write(struct comedi_device *dev,
 994                                 struct comedi_subdevice *s,
 995                                 struct comedi_insn *insn,
 996                                 unsigned int *data)
 997{
 998        unsigned int chan = CR_CHAN(insn->chanspec);
 999        unsigned int update_chan = s->n_chan - 1;
1000        unsigned long flags;
1001        int i;
1002
1003        /* protects the indirect addressing selected by DAS1800_SELECT */
1004        spin_lock_irqsave(&dev->spinlock, flags);
1005
1006        for (i = 0; i < insn->n; i++) {
1007                unsigned int val = data[i];
1008
1009                s->readback[chan] = val;
1010
1011                val = comedi_offset_munge(s, val);
1012
1013                /* load this channel (and update if it's the last channel) */
1014                outb(DAC(chan), dev->iobase + DAS1800_SELECT);
1015                outw(val, dev->iobase + DAS1800_DAC);
1016
1017                /* update all channels */
1018                if (chan != update_chan) {
1019                        val = comedi_offset_munge(s, s->readback[update_chan]);
1020
1021                        outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);
1022                        outw(val, dev->iobase + DAS1800_DAC);
1023                }
1024        }
1025        spin_unlock_irqrestore(&dev->spinlock, flags);
1026
1027        return insn->n;
1028}
1029
1030static int das1800_di_insn_bits(struct comedi_device *dev,
1031                                struct comedi_subdevice *s,
1032                                struct comedi_insn *insn,
1033                                unsigned int *data)
1034{
1035        data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1036        data[0] = 0;
1037
1038        return insn->n;
1039}
1040
1041static int das1800_do_insn_bits(struct comedi_device *dev,
1042                                struct comedi_subdevice *s,
1043                                struct comedi_insn *insn,
1044                                unsigned int *data)
1045{
1046        if (comedi_dio_update_state(s, data))
1047                outb(s->state, dev->iobase + DAS1800_DIGITAL);
1048
1049        data[1] = s->state;
1050
1051        return insn->n;
1052}
1053
1054static void das1800_init_dma(struct comedi_device *dev,
1055                             struct comedi_devconfig *it)
1056{
1057        struct das1800_private *devpriv = dev->private;
1058        unsigned int *dma_chan;
1059
1060        /*
1061         * it->options[2] is DMA channel 0
1062         * it->options[3] is DMA channel 1
1063         *
1064         * Encode the DMA channels into 2 digit hexadecimal for switch.
1065         */
1066        dma_chan = &it->options[2];
1067
1068        switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1069        case 0x5:       /*  dma0 == 5 */
1070                devpriv->dma_bits = DMA_CH5;
1071                break;
1072        case 0x6:       /*  dma0 == 6 */
1073                devpriv->dma_bits = DMA_CH6;
1074                break;
1075        case 0x7:       /*  dma0 == 7 */
1076                devpriv->dma_bits = DMA_CH7;
1077                break;
1078        case 0x65:      /*  dma0 == 5, dma1 == 6 */
1079                devpriv->dma_bits = DMA_CH5_CH6;
1080                break;
1081        case 0x76:      /*  dma0 == 6, dma1 == 7 */
1082                devpriv->dma_bits = DMA_CH6_CH7;
1083                break;
1084        case 0x57:      /*  dma0 == 7, dma1 == 5 */
1085                devpriv->dma_bits = DMA_CH7_CH5;
1086                break;
1087        default:
1088                return;
1089        }
1090
1091        /* DMA can use 1 or 2 buffers, each with a separate channel */
1092        devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1093                                           dma_chan[0], dma_chan[1],
1094                                           DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1095        if (!devpriv->dma)
1096                devpriv->dma_bits = 0;
1097}
1098
1099static void das1800_free_dma(struct comedi_device *dev)
1100{
1101        struct das1800_private *devpriv = dev->private;
1102
1103        if (devpriv)
1104                comedi_isadma_free(devpriv->dma);
1105}
1106
1107static int das1800_probe(struct comedi_device *dev)
1108{
1109        const struct das1800_board *board = dev->board_ptr;
1110        unsigned char id;
1111
1112        id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1113
1114        /*
1115         * The dev->board_ptr will be set by comedi_device_attach() if the
1116         * board name provided by the user matches a board->name in this
1117         * driver. If so, this function sanity checks the id to verify that
1118         * the board is correct.
1119         */
1120        if (board) {
1121                if (board->id == id)
1122                        return 0;
1123                dev_err(dev->class_dev,
1124                        "probed id does not match board id (0x%x != 0x%x)\n",
1125                        id, board->id);
1126                return -ENODEV;
1127        }
1128
1129         /*
1130          * If the dev->board_ptr is not set, the user is trying to attach
1131          * an unspecified board to this driver. In this case the id is used
1132          * to 'probe' for the dev->board_ptr.
1133          */
1134        switch (id) {
1135        case DAS1800_ID_ST_DA:
1136                /* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */
1137                board = &das1800_boards[BOARD_DAS1801ST_DA];
1138                break;
1139        case DAS1800_ID_HR_DA:
1140                /* das-1702hr-da, das-1802hr-da */
1141                board = &das1800_boards[BOARD_DAS1802HR_DA];
1142                break;
1143        case DAS1800_ID_AO:
1144                /* das-1701ao, das-1702ao, das-1801ao, das-1802ao */
1145                board = &das1800_boards[BOARD_DAS1801AO];
1146                break;
1147        case DAS1800_ID_HR:
1148                /*  das-1702hr, das-1802hr */
1149                board = &das1800_boards[BOARD_DAS1802HR];
1150                break;
1151        case DAS1800_ID_ST:
1152                /* das-1701st, das-1702st, das-1801st, das-1802st */
1153                board = &das1800_boards[BOARD_DAS1801ST];
1154                break;
1155        case DAS1800_ID_HC:
1156                /* das-1801hc, das-1802hc */
1157                board = &das1800_boards[BOARD_DAS1801HC];
1158                break;
1159        default:
1160                dev_err(dev->class_dev, "invalid probe id 0x%x\n", id);
1161                return -ENODEV;
1162        }
1163        dev->board_ptr = board;
1164        dev->board_name = board->name;
1165        dev_warn(dev->class_dev,
1166                 "probed id 0x%0x: %s series (not recommended)\n",
1167                 id, board->name);
1168        return 0;
1169}
1170
1171static int das1800_attach(struct comedi_device *dev,
1172                          struct comedi_devconfig *it)
1173{
1174        const struct das1800_board *board;
1175        struct das1800_private *devpriv;
1176        struct comedi_subdevice *s;
1177        unsigned int irq = it->options[1];
1178        bool is_16bit;
1179        int ret;
1180        int i;
1181
1182        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1183        if (!devpriv)
1184                return -ENOMEM;
1185
1186        ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1187        if (ret)
1188                return ret;
1189
1190        ret = das1800_probe(dev);
1191        if (ret)
1192                return ret;
1193        board = dev->board_ptr;
1194
1195        is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;
1196
1197        /* waveform 'ao' boards have additional io ports */
1198        if (board->id == DAS1800_ID_AO) {
1199                unsigned long iobase2 = dev->iobase + IOBASE2;
1200
1201                ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1202                if (ret)
1203                        return ret;
1204                devpriv->iobase2 = iobase2;
1205        }
1206
1207        if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1208            irq == 15) {
1209                ret = request_irq(irq, das1800_interrupt, 0,
1210                                  dev->board_name, dev);
1211                if (ret == 0) {
1212                        dev->irq = irq;
1213
1214                        switch (irq) {
1215                        case 3:
1216                                devpriv->irq_dma_bits |= 0x8;
1217                                break;
1218                        case 5:
1219                                devpriv->irq_dma_bits |= 0x10;
1220                                break;
1221                        case 7:
1222                                devpriv->irq_dma_bits |= 0x18;
1223                                break;
1224                        case 10:
1225                                devpriv->irq_dma_bits |= 0x28;
1226                                break;
1227                        case 11:
1228                                devpriv->irq_dma_bits |= 0x30;
1229                                break;
1230                        case 15:
1231                                devpriv->irq_dma_bits |= 0x38;
1232                                break;
1233                        }
1234                }
1235        }
1236
1237        /* an irq and one dma channel is required to use dma */
1238        if (dev->irq & it->options[2])
1239                das1800_init_dma(dev, it);
1240
1241        devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
1242                                          sizeof(*devpriv->fifo_buf),
1243                                          GFP_KERNEL);
1244        if (!devpriv->fifo_buf)
1245                return -ENOMEM;
1246
1247        dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1248                                      I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1249        if (!dev->pacer)
1250                return -ENOMEM;
1251
1252        ret = comedi_alloc_subdevices(dev, 4);
1253        if (ret)
1254                return ret;
1255
1256        /*
1257         * Analog Input subdevice
1258         *
1259         * The "hc" type boards have 64 analog input channels and a 64
1260         * entry QRAM fifo.
1261         *
1262         * All the other board types have 16 on-board channels. Each channel
1263         * can be expanded to 16 channels with the addition of an EXP-1800
1264         * expansion board for a total of 256 channels. The QRAM fifo on
1265         * these boards has 256 entries.
1266         *
1267         * From the datasheets it's not clear what the comedi channel to
1268         * actual physical channel mapping is when EXP-1800 boards are used.
1269         */
1270        s = &dev->subdevices[0];
1271        s->type         = COMEDI_SUBD_AI;
1272        s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1273        if (board->id != DAS1800_ID_HC)
1274                s->subdev_flags |= SDF_COMMON;
1275        s->n_chan       = (board->id == DAS1800_ID_HC) ? 64 : 256;
1276        s->maxdata      = is_16bit ? 0xffff : 0x0fff;
1277        s->range_table  = board->is_01_series ? &das1801_ai_range
1278                                              : &das1802_ai_range;
1279        s->insn_read    = das1800_ai_insn_read;
1280        if (dev->irq) {
1281                dev->read_subdev = s;
1282                s->subdev_flags |= SDF_CMD_READ;
1283                s->len_chanlist = s->n_chan;
1284                s->do_cmd       = das1800_ai_cmd;
1285                s->do_cmdtest   = das1800_ai_cmdtest;
1286                s->poll         = das1800_ai_poll;
1287                s->cancel       = das1800_ai_cancel;
1288                s->munge        = das1800_ai_munge;
1289        }
1290
1291        /* Analog Output subdevice */
1292        s = &dev->subdevices[1];
1293        if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
1294                s->type         = COMEDI_SUBD_AO;
1295                s->subdev_flags = SDF_WRITABLE;
1296                s->n_chan       = (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
1297                s->maxdata      = is_16bit ? 0xffff : 0x0fff;
1298                s->range_table  = &range_bipolar10;
1299                s->insn_write   = das1800_ao_insn_write;
1300
1301                ret = comedi_alloc_subdev_readback(s);
1302                if (ret)
1303                        return ret;
1304
1305                /* initialize all channels to 0V */
1306                for (i = 0; i < s->n_chan; i++) {
1307                        /* spinlock is not necessary during the attach */
1308                        outb(DAC(i), dev->iobase + DAS1800_SELECT);
1309                        outw(0, dev->iobase + DAS1800_DAC);
1310                }
1311        } else if (board->id == DAS1800_ID_AO) {
1312                /*
1313                 * 'ao' boards have waveform analog outputs that are not
1314                 * currently supported.
1315                 */
1316                s->type         = COMEDI_SUBD_UNUSED;
1317        } else {
1318                s->type         = COMEDI_SUBD_UNUSED;
1319        }
1320
1321        /* Digital Input subdevice */
1322        s = &dev->subdevices[2];
1323        s->type         = COMEDI_SUBD_DI;
1324        s->subdev_flags = SDF_READABLE;
1325        s->n_chan       = 4;
1326        s->maxdata      = 1;
1327        s->range_table  = &range_digital;
1328        s->insn_bits    = das1800_di_insn_bits;
1329
1330        /* Digital Output subdevice */
1331        s = &dev->subdevices[3];
1332        s->type         = COMEDI_SUBD_DO;
1333        s->subdev_flags = SDF_WRITABLE;
1334        s->n_chan       = (board->id == DAS1800_ID_HC) ? 8 : 4;
1335        s->maxdata      = 1;
1336        s->range_table  = &range_digital;
1337        s->insn_bits    = das1800_do_insn_bits;
1338
1339        das1800_ai_cancel(dev, dev->read_subdev);
1340
1341        /*  initialize digital out channels */
1342        outb(0, dev->iobase + DAS1800_DIGITAL);
1343
1344        return 0;
1345};
1346
1347static void das1800_detach(struct comedi_device *dev)
1348{
1349        struct das1800_private *devpriv = dev->private;
1350
1351        das1800_free_dma(dev);
1352        if (devpriv) {
1353                kfree(devpriv->fifo_buf);
1354                if (devpriv->iobase2)
1355                        release_region(devpriv->iobase2, DAS1800_SIZE);
1356        }
1357        comedi_legacy_detach(dev);
1358}
1359
1360static struct comedi_driver das1800_driver = {
1361        .driver_name    = "das1800",
1362        .module         = THIS_MODULE,
1363        .attach         = das1800_attach,
1364        .detach         = das1800_detach,
1365        .num_names      = ARRAY_SIZE(das1800_boards),
1366        .board_name     = &das1800_boards[0].name,
1367        .offset         = sizeof(struct das1800_board),
1368};
1369module_comedi_driver(das1800_driver);
1370
1371MODULE_AUTHOR("Comedi http://www.comedi.org");
1372MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards");
1373MODULE_LICENSE("GPL");
1374