linux/drivers/staging/comedi/drivers/das16.c
<<
>>
Prefs
   1/*
   2 * das16.c
   3 * DAS16 driver
   4 *
   5 * COMEDI - Linux Control and Measurement Device Interface
   6 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   7 * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
   8 * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
   9 *
  10 * This program is free software; you can redistribute it and/or modify
  11 * it under the terms of the GNU General Public License as published by
  12 * the Free Software Foundation; either version 2 of the License, or
  13 * (at your option) any later version.
  14 *
  15 * This program is distributed in the hope that it will be useful,
  16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18 * GNU General Public License for more details.
  19 */
  20
  21/*
  22 * Driver: das16
  23 * Description: DAS16 compatible boards
  24 * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
  25 * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
  26 *   DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
  27 *   DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
  28 *   DAS-1602 (das-1602),
  29 *   [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
  30 *   PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16),
  31 *   CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr),
  32 *   CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12),
  33 *   CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
  34 *   CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
  35 *   CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
  36 * Status: works
  37 * Updated: 2003-10-12
  38 *
  39 * A rewrite of the das16 and das1600 drivers.
  40 *
  41 * Options:
  42 *      [0] - base io address
  43 *      [1] - irq (does nothing, irq is not used anymore)
  44 *      [2] - dma channel (optional, required for comedi_command support)
  45 *      [3] - master clock speed in MHz (optional, 1 or 10, ignored if
  46 *              board can probe clock, defaults to 1)
  47 *      [4] - analog input range lowest voltage in microvolts (optional,
  48 *              only useful if your board does not have software
  49 *              programmable gain)
  50 *      [5] - analog input range highest voltage in microvolts (optional,
  51 *              only useful if board does not have software programmable
  52 *              gain)
  53 *      [6] - analog output range lowest voltage in microvolts (optional)
  54 *      [7] - analog output range highest voltage in microvolts (optional)
  55 *
  56 * Passing a zero for an option is the same as leaving it unspecified.
  57 */
  58
  59/*
  60 * Testing and debugging help provided by Daniel Koch.
  61 *
  62 * Keithley Manuals:
  63 *      2309.PDF (das16)
  64 *      4919.PDF (das1400, 1600)
  65 *      4922.PDF (das-1400)
  66 *      4923.PDF (das1200, 1400, 1600)
  67 *
  68 * Computer boards manuals also available from their website
  69 * www.measurementcomputing.com
  70 */
  71
  72#include <linux/module.h>
  73#include <linux/slab.h>
  74#include <linux/interrupt.h>
  75
  76#include "../comedidev.h"
  77
  78#include "comedi_isadma.h"
  79#include "comedi_8254.h"
  80#include "8255.h"
  81
  82#define DAS16_DMA_SIZE 0xff00   /*  size in bytes of allocated dma buffer */
  83
  84/*
  85 * Register I/O map
  86 */
  87#define DAS16_TRIG_REG                  0x00
  88#define DAS16_AI_LSB_REG                0x00
  89#define DAS16_AI_MSB_REG                0x01
  90#define DAS16_MUX_REG                   0x02
  91#define DAS16_DIO_REG                   0x03
  92#define DAS16_AO_LSB_REG(x)             ((x) ? 0x06 : 0x04)
  93#define DAS16_AO_MSB_REG(x)             ((x) ? 0x07 : 0x05)
  94#define DAS16_STATUS_REG                0x08
  95#define DAS16_STATUS_BUSY               BIT(7)
  96#define DAS16_STATUS_UNIPOLAR           BIT(6)
  97#define DAS16_STATUS_MUXBIT             BIT(5)
  98#define DAS16_STATUS_INT                BIT(4)
  99#define DAS16_CTRL_REG                  0x09
 100#define DAS16_CTRL_INTE                 BIT(7)
 101#define DAS16_CTRL_IRQ(x)               (((x) & 0x7) << 4)
 102#define DAS16_CTRL_DMAE                 BIT(2)
 103#define DAS16_CTRL_PACING_MASK          (3 << 0)
 104#define DAS16_CTRL_INT_PACER            (3 << 0)
 105#define DAS16_CTRL_EXT_PACER            (2 << 0)
 106#define DAS16_CTRL_SOFT_PACER           (0 << 0)
 107#define DAS16_PACER_REG                 0x0a
 108#define DAS16_PACER_BURST_LEN(x)        (((x) & 0xf) << 4)
 109#define DAS16_PACER_CTR0                BIT(1)
 110#define DAS16_PACER_TRIG0               BIT(0)
 111#define DAS16_GAIN_REG                  0x0b
 112#define DAS16_TIMER_BASE_REG            0x0c    /* to 0x0f */
 113
 114#define DAS1600_CONV_REG                0x404
 115#define DAS1600_CONV_DISABLE            BIT(6)
 116#define DAS1600_BURST_REG               0x405
 117#define DAS1600_BURST_VAL               BIT(6)
 118#define DAS1600_ENABLE_REG              0x406
 119#define DAS1600_ENABLE_VAL              BIT(6)
 120#define DAS1600_STATUS_REG              0x407
 121#define DAS1600_STATUS_BME              BIT(6)
 122#define DAS1600_STATUS_ME               BIT(5)
 123#define DAS1600_STATUS_CD               BIT(4)
 124#define DAS1600_STATUS_WS               BIT(1)
 125#define DAS1600_STATUS_CLK_10MHZ        BIT(0)
 126
 127static const struct comedi_lrange range_das1x01_bip = {
 128        4, {
 129                BIP_RANGE(10),
 130                BIP_RANGE(1),
 131                BIP_RANGE(0.1),
 132                BIP_RANGE(0.01)
 133        }
 134};
 135
 136static const struct comedi_lrange range_das1x01_unip = {
 137        4, {
 138                UNI_RANGE(10),
 139                UNI_RANGE(1),
 140                UNI_RANGE(0.1),
 141                UNI_RANGE(0.01)
 142        }
 143};
 144
 145static const struct comedi_lrange range_das1x02_bip = {
 146        4, {
 147                BIP_RANGE(10),
 148                BIP_RANGE(5),
 149                BIP_RANGE(2.5),
 150                BIP_RANGE(1.25)
 151        }
 152};
 153
 154static const struct comedi_lrange range_das1x02_unip = {
 155        4, {
 156                UNI_RANGE(10),
 157                UNI_RANGE(5),
 158                UNI_RANGE(2.5),
 159                UNI_RANGE(1.25)
 160        }
 161};
 162
 163static const struct comedi_lrange range_das16jr = {
 164        9, {
 165                BIP_RANGE(10),
 166                BIP_RANGE(5),
 167                BIP_RANGE(2.5),
 168                BIP_RANGE(1.25),
 169                BIP_RANGE(0.625),
 170                UNI_RANGE(10),
 171                UNI_RANGE(5),
 172                UNI_RANGE(2.5),
 173                UNI_RANGE(1.25)
 174        }
 175};
 176
 177static const struct comedi_lrange range_das16jr_16 = {
 178        8, {
 179                BIP_RANGE(10),
 180                BIP_RANGE(5),
 181                BIP_RANGE(2.5),
 182                BIP_RANGE(1.25),
 183                UNI_RANGE(10),
 184                UNI_RANGE(5),
 185                UNI_RANGE(2.5),
 186                UNI_RANGE(1.25)
 187        }
 188};
 189
 190static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
 191static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 192static const int das1600_gainlist[] = { 0, 1, 2, 3 };
 193
 194enum {
 195        das16_pg_none = 0,
 196        das16_pg_16jr,
 197        das16_pg_16jr_16,
 198        das16_pg_1601,
 199        das16_pg_1602,
 200};
 201
 202static const int *const das16_gainlists[] = {
 203        NULL,
 204        das16jr_gainlist,
 205        das16jr_16_gainlist,
 206        das1600_gainlist,
 207        das1600_gainlist,
 208};
 209
 210static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
 211        &range_unknown,
 212        &range_das16jr,
 213        &range_das16jr_16,
 214        &range_das1x01_unip,
 215        &range_das1x02_unip,
 216};
 217
 218static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
 219        &range_unknown,
 220        &range_das16jr,
 221        &range_das16jr_16,
 222        &range_das1x01_bip,
 223        &range_das1x02_bip,
 224};
 225
 226struct das16_board {
 227        const char *name;
 228        unsigned int ai_maxdata;
 229        unsigned int ai_speed;  /*  max conversion speed in nanosec */
 230        unsigned int ai_pg;
 231        unsigned int has_ao:1;
 232        unsigned int has_8255:1;
 233
 234        unsigned int i8255_offset;
 235
 236        unsigned int size;
 237        unsigned int id;
 238};
 239
 240static const struct das16_board das16_boards[] = {
 241        {
 242                .name           = "das-16",
 243                .ai_maxdata     = 0x0fff,
 244                .ai_speed       = 15000,
 245                .ai_pg          = das16_pg_none,
 246                .has_ao         = 1,
 247                .has_8255       = 1,
 248                .i8255_offset   = 0x10,
 249                .size           = 0x14,
 250                .id             = 0x00,
 251        }, {
 252                .name           = "das-16g",
 253                .ai_maxdata     = 0x0fff,
 254                .ai_speed       = 15000,
 255                .ai_pg          = das16_pg_none,
 256                .has_ao         = 1,
 257                .has_8255       = 1,
 258                .i8255_offset   = 0x10,
 259                .size           = 0x14,
 260                .id             = 0x00,
 261        }, {
 262                .name           = "das-16f",
 263                .ai_maxdata     = 0x0fff,
 264                .ai_speed       = 8500,
 265                .ai_pg          = das16_pg_none,
 266                .has_ao         = 1,
 267                .has_8255       = 1,
 268                .i8255_offset   = 0x10,
 269                .size           = 0x14,
 270                .id             = 0x00,
 271        }, {
 272                .name           = "cio-das16",
 273                .ai_maxdata     = 0x0fff,
 274                .ai_speed       = 20000,
 275                .ai_pg          = das16_pg_none,
 276                .has_ao         = 1,
 277                .has_8255       = 1,
 278                .i8255_offset   = 0x10,
 279                .size           = 0x14,
 280                .id             = 0x80,
 281        }, {
 282                .name           = "cio-das16/f",
 283                .ai_maxdata     = 0x0fff,
 284                .ai_speed       = 10000,
 285                .ai_pg          = das16_pg_none,
 286                .has_ao         = 1,
 287                .has_8255       = 1,
 288                .i8255_offset   = 0x10,
 289                .size           = 0x14,
 290                .id             = 0x80,
 291        }, {
 292                .name           = "cio-das16/jr",
 293                .ai_maxdata     = 0x0fff,
 294                .ai_speed       = 7692,
 295                .ai_pg          = das16_pg_16jr,
 296                .size           = 0x10,
 297                .id             = 0x00,
 298        }, {
 299                .name           = "pc104-das16jr",
 300                .ai_maxdata     = 0x0fff,
 301                .ai_speed       = 3300,
 302                .ai_pg          = das16_pg_16jr,
 303                .size           = 0x10,
 304                .id             = 0x00,
 305        }, {
 306                .name           = "cio-das16jr/16",
 307                .ai_maxdata     = 0xffff,
 308                .ai_speed       = 10000,
 309                .ai_pg          = das16_pg_16jr_16,
 310                .size           = 0x10,
 311                .id             = 0x00,
 312        }, {
 313                .name           = "pc104-das16jr/16",
 314                .ai_maxdata     = 0xffff,
 315                .ai_speed       = 10000,
 316                .ai_pg          = das16_pg_16jr_16,
 317                .size           = 0x10,
 318                .id             = 0x00,
 319        }, {
 320                .name           = "das-1201",
 321                .ai_maxdata     = 0x0fff,
 322                .ai_speed       = 20000,
 323                .ai_pg          = das16_pg_none,
 324                .has_8255       = 1,
 325                .i8255_offset   = 0x400,
 326                .size           = 0x408,
 327                .id             = 0x20,
 328        }, {
 329                .name           = "das-1202",
 330                .ai_maxdata     = 0x0fff,
 331                .ai_speed       = 10000,
 332                .ai_pg          = das16_pg_none,
 333                .has_8255       = 1,
 334                .i8255_offset   = 0x400,
 335                .size           = 0x408,
 336                .id             = 0x20,
 337        }, {
 338                .name           = "das-1401",
 339                .ai_maxdata     = 0x0fff,
 340                .ai_speed       = 10000,
 341                .ai_pg          = das16_pg_1601,
 342                .size           = 0x408,
 343                .id             = 0xc0,
 344        }, {
 345                .name           = "das-1402",
 346                .ai_maxdata     = 0x0fff,
 347                .ai_speed       = 10000,
 348                .ai_pg          = das16_pg_1602,
 349                .size           = 0x408,
 350                .id             = 0xc0,
 351        }, {
 352                .name           = "das-1601",
 353                .ai_maxdata     = 0x0fff,
 354                .ai_speed       = 10000,
 355                .ai_pg          = das16_pg_1601,
 356                .has_ao         = 1,
 357                .has_8255       = 1,
 358                .i8255_offset   = 0x400,
 359                .size           = 0x408,
 360                .id             = 0xc0,
 361        }, {
 362                .name           = "das-1602",
 363                .ai_maxdata     = 0x0fff,
 364                .ai_speed       = 10000,
 365                .ai_pg          = das16_pg_1602,
 366                .has_ao         = 1,
 367                .has_8255       = 1,
 368                .i8255_offset   = 0x400,
 369                .size           = 0x408,
 370                .id             = 0xc0,
 371        }, {
 372                .name           = "cio-das1401/12",
 373                .ai_maxdata     = 0x0fff,
 374                .ai_speed       = 6250,
 375                .ai_pg          = das16_pg_1601,
 376                .size           = 0x408,
 377                .id             = 0xc0,
 378        }, {
 379                .name           = "cio-das1402/12",
 380                .ai_maxdata     = 0x0fff,
 381                .ai_speed       = 6250,
 382                .ai_pg          = das16_pg_1602,
 383                .size           = 0x408,
 384                .id             = 0xc0,
 385        }, {
 386                .name           = "cio-das1402/16",
 387                .ai_maxdata     = 0xffff,
 388                .ai_speed       = 10000,
 389                .ai_pg          = das16_pg_1602,
 390                .size           = 0x408,
 391                .id             = 0xc0,
 392        }, {
 393                .name           = "cio-das1601/12",
 394                .ai_maxdata     = 0x0fff,
 395                .ai_speed       = 6250,
 396                .ai_pg          = das16_pg_1601,
 397                .has_ao         = 1,
 398                .has_8255       = 1,
 399                .i8255_offset   = 0x400,
 400                .size           = 0x408,
 401                .id             = 0xc0,
 402        }, {
 403                .name           = "cio-das1602/12",
 404                .ai_maxdata     = 0x0fff,
 405                .ai_speed       = 10000,
 406                .ai_pg          = das16_pg_1602,
 407                .has_ao         = 1,
 408                .has_8255       = 1,
 409                .i8255_offset   = 0x400,
 410                .size           = 0x408,
 411                .id             = 0xc0,
 412        }, {
 413                .name           = "cio-das1602/16",
 414                .ai_maxdata     = 0xffff,
 415                .ai_speed       = 10000,
 416                .ai_pg          = das16_pg_1602,
 417                .has_ao         = 1,
 418                .has_8255       = 1,
 419                .i8255_offset   = 0x400,
 420                .size           = 0x408,
 421                .id             = 0xc0,
 422        }, {
 423                .name           = "cio-das16/330",
 424                .ai_maxdata     = 0x0fff,
 425                .ai_speed       = 3030,
 426                .ai_pg          = das16_pg_16jr,
 427                .size           = 0x14,
 428                .id             = 0xf0,
 429        },
 430};
 431
 432/*
 433 * Period for timer interrupt in jiffies.  It's a function
 434 * to deal with possibility of dynamic HZ patches
 435 */
 436static inline int timer_period(void)
 437{
 438        return HZ / 20;
 439}
 440
 441struct das16_private_struct {
 442        struct comedi_isadma    *dma;
 443        unsigned int            clockbase;
 444        unsigned int            ctrl_reg;
 445        unsigned int            divisor1;
 446        unsigned int            divisor2;
 447        struct timer_list       timer;
 448        unsigned long           extra_iobase;
 449        unsigned int            can_burst:1;
 450        unsigned int            timer_running:1;
 451};
 452
 453static void das16_ai_setup_dma(struct comedi_device *dev,
 454                               struct comedi_subdevice *s,
 455                               unsigned int unread_samples)
 456{
 457        struct das16_private_struct *devpriv = dev->private;
 458        struct comedi_isadma *dma = devpriv->dma;
 459        struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 460        unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize);
 461        unsigned int nsamples;
 462
 463        /*
 464         * Determine dma size based on the buffer size plus the number of
 465         * unread samples and the number of samples remaining in the command.
 466         */
 467        nsamples = comedi_nsamples_left(s, max_samples + unread_samples);
 468        if (nsamples > unread_samples) {
 469                nsamples -= unread_samples;
 470                desc->size = comedi_samples_to_bytes(s, nsamples);
 471                comedi_isadma_program(desc);
 472        }
 473}
 474
 475static void das16_interrupt(struct comedi_device *dev)
 476{
 477        struct das16_private_struct *devpriv = dev->private;
 478        struct comedi_subdevice *s = dev->read_subdev;
 479        struct comedi_async *async = s->async;
 480        struct comedi_cmd *cmd = &async->cmd;
 481        struct comedi_isadma *dma = devpriv->dma;
 482        struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 483        unsigned long spin_flags;
 484        unsigned int residue;
 485        unsigned int nbytes;
 486        unsigned int nsamples;
 487
 488        spin_lock_irqsave(&dev->spinlock, spin_flags);
 489        if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
 490                spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 491                return;
 492        }
 493
 494        /*
 495         * The pc104-das16jr (at least) has problems if the dma
 496         * transfer is interrupted in the middle of transferring
 497         * a 16 bit sample.
 498         */
 499        residue = comedi_isadma_disable_on_sample(desc->chan,
 500                                                  comedi_bytes_per_sample(s));
 501
 502        /* figure out how many samples to read */
 503        if (residue > desc->size) {
 504                dev_err(dev->class_dev, "residue > transfer size!\n");
 505                async->events |= COMEDI_CB_ERROR;
 506                nbytes = 0;
 507        } else {
 508                nbytes = desc->size - residue;
 509        }
 510        nsamples = comedi_bytes_to_samples(s, nbytes);
 511
 512        /* restart DMA if more samples are needed */
 513        if (nsamples) {
 514                dma->cur_dma = 1 - dma->cur_dma;
 515                das16_ai_setup_dma(dev, s, nsamples);
 516        }
 517
 518        spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 519
 520        comedi_buf_write_samples(s, desc->virt_addr, nsamples);
 521
 522        if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
 523                async->events |= COMEDI_CB_EOA;
 524
 525        comedi_handle_events(dev, s);
 526}
 527
 528static void das16_timer_interrupt(unsigned long arg)
 529{
 530        struct comedi_device *dev = (struct comedi_device *)arg;
 531        struct das16_private_struct *devpriv = dev->private;
 532        unsigned long flags;
 533
 534        das16_interrupt(dev);
 535
 536        spin_lock_irqsave(&dev->spinlock, flags);
 537        if (devpriv->timer_running)
 538                mod_timer(&devpriv->timer, jiffies + timer_period());
 539        spin_unlock_irqrestore(&dev->spinlock, flags);
 540}
 541
 542static void das16_ai_set_mux_range(struct comedi_device *dev,
 543                                   unsigned int first_chan,
 544                                   unsigned int last_chan,
 545                                   unsigned int range)
 546{
 547        const struct das16_board *board = dev->board_ptr;
 548
 549        /* set multiplexer */
 550        outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG);
 551
 552        /* some boards do not have programmable gain */
 553        if (board->ai_pg == das16_pg_none)
 554                return;
 555
 556        /*
 557         * Set gain (this is also burst rate register but according to
 558         * computer boards manual, burst rate does nothing, even on
 559         * keithley cards).
 560         */
 561        outb((das16_gainlists[board->ai_pg])[range],
 562             dev->iobase + DAS16_GAIN_REG);
 563}
 564
 565static int das16_ai_check_chanlist(struct comedi_device *dev,
 566                                   struct comedi_subdevice *s,
 567                                   struct comedi_cmd *cmd)
 568{
 569        unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
 570        unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 571        int i;
 572
 573        for (i = 1; i < cmd->chanlist_len; i++) {
 574                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 575                unsigned int range = CR_RANGE(cmd->chanlist[i]);
 576
 577                if (chan != ((chan0 + i) % s->n_chan)) {
 578                        dev_dbg(dev->class_dev,
 579                                "entries in chanlist must be consecutive channels, counting upwards\n");
 580                        return -EINVAL;
 581                }
 582
 583                if (range != range0) {
 584                        dev_dbg(dev->class_dev,
 585                                "entries in chanlist must all have the same gain\n");
 586                        return -EINVAL;
 587                }
 588        }
 589
 590        return 0;
 591}
 592
 593static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 594                          struct comedi_cmd *cmd)
 595{
 596        const struct das16_board *board = dev->board_ptr;
 597        struct das16_private_struct *devpriv = dev->private;
 598        int err = 0;
 599        unsigned int trig_mask;
 600        unsigned int arg;
 601
 602        /* Step 1 : check if triggers are trivially valid */
 603
 604        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
 605
 606        trig_mask = TRIG_FOLLOW;
 607        if (devpriv->can_burst)
 608                trig_mask |= TRIG_TIMER | TRIG_EXT;
 609        err |= comedi_check_trigger_src(&cmd->scan_begin_src, trig_mask);
 610
 611        trig_mask = TRIG_TIMER | TRIG_EXT;
 612        if (devpriv->can_burst)
 613                trig_mask |= TRIG_NOW;
 614        err |= comedi_check_trigger_src(&cmd->convert_src, trig_mask);
 615
 616        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 617        err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 618
 619        if (err)
 620                return 1;
 621
 622        /* Step 2a : make sure trigger sources are unique */
 623
 624        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 625        err |= comedi_check_trigger_is_unique(cmd->convert_src);
 626        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 627
 628        /* Step 2b : and mutually compatible */
 629
 630        /*  make sure scan_begin_src and convert_src dont conflict */
 631        if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
 632                err |= -EINVAL;
 633        if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
 634                err |= -EINVAL;
 635
 636        if (err)
 637                return 2;
 638
 639        /* Step 3: check if arguments are trivially valid */
 640
 641        err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 642
 643        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 644                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 645
 646        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 647                                           cmd->chanlist_len);
 648
 649        /* check against maximum frequency */
 650        if (cmd->scan_begin_src == TRIG_TIMER) {
 651                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 652                                                    board->ai_speed *
 653                                                    cmd->chanlist_len);
 654        }
 655
 656        if (cmd->convert_src == TRIG_TIMER) {
 657                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 658                                                    board->ai_speed);
 659        }
 660
 661        if (cmd->stop_src == TRIG_COUNT)
 662                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 663        else    /* TRIG_NONE */
 664                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 665
 666        if (err)
 667                return 3;
 668
 669        /*  step 4: fix up arguments */
 670        if (cmd->scan_begin_src == TRIG_TIMER) {
 671                arg = cmd->scan_begin_arg;
 672                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 673                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 674        }
 675        if (cmd->convert_src == TRIG_TIMER) {
 676                arg = cmd->convert_arg;
 677                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 678                err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 679        }
 680        if (err)
 681                return 4;
 682
 683        /* Step 5: check channel list if it exists */
 684        if (cmd->chanlist && cmd->chanlist_len > 0)
 685                err |= das16_ai_check_chanlist(dev, s, cmd);
 686
 687        if (err)
 688                return 5;
 689
 690        return 0;
 691}
 692
 693static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 694                                    unsigned int flags)
 695{
 696        comedi_8254_cascade_ns_to_timer(dev->pacer, &ns, flags);
 697        comedi_8254_update_divisors(dev->pacer);
 698        comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 699
 700        return ns;
 701}
 702
 703static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 704{
 705        struct das16_private_struct *devpriv = dev->private;
 706        struct comedi_isadma *dma = devpriv->dma;
 707        struct comedi_async *async = s->async;
 708        struct comedi_cmd *cmd = &async->cmd;
 709        unsigned int first_chan = CR_CHAN(cmd->chanlist[0]);
 710        unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
 711        unsigned int range = CR_RANGE(cmd->chanlist[0]);
 712        unsigned int byte;
 713        unsigned long flags;
 714
 715        if (cmd->flags & CMDF_PRIORITY) {
 716                dev_err(dev->class_dev,
 717                        "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
 718                return -1;
 719        }
 720
 721        if (devpriv->can_burst)
 722                outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
 723
 724        /* set mux and range for chanlist scan */
 725        das16_ai_set_mux_range(dev, first_chan, last_chan, range);
 726
 727        /* set counter mode and counts */
 728        cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
 729
 730        /* enable counters */
 731        byte = 0;
 732        if (devpriv->can_burst) {
 733                if (cmd->convert_src == TRIG_NOW) {
 734                        outb(DAS1600_BURST_VAL,
 735                             dev->iobase + DAS1600_BURST_REG);
 736                        /*  set burst length */
 737                        byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
 738                } else {
 739                        outb(0, dev->iobase + DAS1600_BURST_REG);
 740                }
 741        }
 742        outb(byte, dev->iobase + DAS16_PACER_REG);
 743
 744        /* set up dma transfer */
 745        dma->cur_dma = 0;
 746        das16_ai_setup_dma(dev, s, 0);
 747
 748        /*  set up timer */
 749        spin_lock_irqsave(&dev->spinlock, flags);
 750        devpriv->timer_running = 1;
 751        devpriv->timer.expires = jiffies + timer_period();
 752        add_timer(&devpriv->timer);
 753
 754        /* enable DMA interrupt with external or internal pacing */
 755        devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK);
 756        devpriv->ctrl_reg |= DAS16_CTRL_DMAE;
 757        if (cmd->convert_src == TRIG_EXT)
 758                devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
 759        else
 760                devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
 761        outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
 762
 763        if (devpriv->can_burst)
 764                outb(0, dev->iobase + DAS1600_CONV_REG);
 765        spin_unlock_irqrestore(&dev->spinlock, flags);
 766
 767        return 0;
 768}
 769
 770static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 771{
 772        struct das16_private_struct *devpriv = dev->private;
 773        struct comedi_isadma *dma = devpriv->dma;
 774        unsigned long flags;
 775
 776        spin_lock_irqsave(&dev->spinlock, flags);
 777
 778        /* disable interrupts, dma and pacer clocked conversions */
 779        devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE |
 780                               DAS16_CTRL_PACING_MASK);
 781        outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
 782
 783        comedi_isadma_disable(dma->chan);
 784
 785        /*  disable SW timer */
 786        if (devpriv->timer_running) {
 787                devpriv->timer_running = 0;
 788                del_timer(&devpriv->timer);
 789        }
 790
 791        if (devpriv->can_burst)
 792                outb(0, dev->iobase + DAS1600_BURST_REG);
 793
 794        spin_unlock_irqrestore(&dev->spinlock, flags);
 795
 796        return 0;
 797}
 798
 799static void das16_ai_munge(struct comedi_device *dev,
 800                           struct comedi_subdevice *s, void *array,
 801                           unsigned int num_bytes,
 802                           unsigned int start_chan_index)
 803{
 804        unsigned short *data = array;
 805        unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
 806        unsigned int i;
 807        __le16 *buf = array;
 808
 809        for (i = 0; i < num_samples; i++) {
 810                data[i] = le16_to_cpu(buf[i]);
 811                if (s->maxdata == 0x0fff)
 812                        data[i] >>= 4;
 813                data[i] &= s->maxdata;
 814        }
 815}
 816
 817static int das16_ai_eoc(struct comedi_device *dev,
 818                        struct comedi_subdevice *s,
 819                        struct comedi_insn *insn,
 820                        unsigned long context)
 821{
 822        unsigned int status;
 823
 824        status = inb(dev->iobase + DAS16_STATUS_REG);
 825        if ((status & DAS16_STATUS_BUSY) == 0)
 826                return 0;
 827        return -EBUSY;
 828}
 829
 830static int das16_ai_insn_read(struct comedi_device *dev,
 831                              struct comedi_subdevice *s,
 832                              struct comedi_insn *insn,
 833                              unsigned int *data)
 834{
 835        unsigned int chan = CR_CHAN(insn->chanspec);
 836        unsigned int range = CR_RANGE(insn->chanspec);
 837        unsigned int val;
 838        int ret;
 839        int i;
 840
 841        /* set mux and range for single channel */
 842        das16_ai_set_mux_range(dev, chan, chan, range);
 843
 844        for (i = 0; i < insn->n; i++) {
 845                /* trigger conversion */
 846                outb_p(0, dev->iobase + DAS16_TRIG_REG);
 847
 848                ret = comedi_timeout(dev, s, insn, das16_ai_eoc, 0);
 849                if (ret)
 850                        return ret;
 851
 852                val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
 853                val |= inb(dev->iobase + DAS16_AI_LSB_REG);
 854                if (s->maxdata == 0x0fff)
 855                        val >>= 4;
 856                val &= s->maxdata;
 857
 858                data[i] = val;
 859        }
 860
 861        return insn->n;
 862}
 863
 864static int das16_ao_insn_write(struct comedi_device *dev,
 865                               struct comedi_subdevice *s,
 866                               struct comedi_insn *insn,
 867                               unsigned int *data)
 868{
 869        unsigned int chan = CR_CHAN(insn->chanspec);
 870        int i;
 871
 872        for (i = 0; i < insn->n; i++) {
 873                unsigned int val = data[i];
 874
 875                s->readback[chan] = val;
 876
 877                val <<= 4;
 878
 879                outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
 880                outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
 881        }
 882
 883        return insn->n;
 884}
 885
 886static int das16_di_insn_bits(struct comedi_device *dev,
 887                              struct comedi_subdevice *s,
 888                              struct comedi_insn *insn,
 889                              unsigned int *data)
 890{
 891        data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
 892
 893        return insn->n;
 894}
 895
 896static int das16_do_insn_bits(struct comedi_device *dev,
 897                              struct comedi_subdevice *s,
 898                              struct comedi_insn *insn,
 899                              unsigned int *data)
 900{
 901        if (comedi_dio_update_state(s, data))
 902                outb(s->state, dev->iobase + DAS16_DIO_REG);
 903
 904        data[1] = s->state;
 905
 906        return insn->n;
 907}
 908
 909static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 910{
 911        const struct das16_board *board = dev->board_ptr;
 912        int diobits;
 913
 914        /* diobits indicates boards */
 915        diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
 916        if (board->id != diobits) {
 917                dev_err(dev->class_dev,
 918                        "requested board's id bits are incorrect (0x%x != 0x%x)\n",
 919                        board->id, diobits);
 920                return -EINVAL;
 921        }
 922
 923        return 0;
 924}
 925
 926static void das16_reset(struct comedi_device *dev)
 927{
 928        outb(0, dev->iobase + DAS16_STATUS_REG);
 929        outb(0, dev->iobase + DAS16_CTRL_REG);
 930        outb(0, dev->iobase + DAS16_PACER_REG);
 931}
 932
 933static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
 934{
 935        struct das16_private_struct *devpriv = dev->private;
 936
 937        /* only DMA channels 3 and 1 are valid */
 938        if (!(dma_chan == 1 || dma_chan == 3))
 939                return;
 940
 941        /* DMA uses two buffers */
 942        devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan,
 943                                           DAS16_DMA_SIZE, COMEDI_ISADMA_READ);
 944        if (devpriv->dma) {
 945                setup_timer(&devpriv->timer, das16_timer_interrupt,
 946                            (unsigned long)dev);
 947        }
 948}
 949
 950static void das16_free_dma(struct comedi_device *dev)
 951{
 952        struct das16_private_struct *devpriv = dev->private;
 953
 954        if (devpriv) {
 955                if (devpriv->timer.data)
 956                        del_timer_sync(&devpriv->timer);
 957                comedi_isadma_free(devpriv->dma);
 958        }
 959}
 960
 961static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev,
 962                                                  struct comedi_subdevice *s,
 963                                                  struct comedi_devconfig *it,
 964                                                  unsigned int pg_type,
 965                                                  unsigned int status)
 966{
 967        unsigned int min = it->options[4];
 968        unsigned int max = it->options[5];
 969
 970        /* get any user-defined input range */
 971        if (pg_type == das16_pg_none && (min || max)) {
 972                struct comedi_lrange *lrange;
 973                struct comedi_krange *krange;
 974
 975                /* allocate single-range range table */
 976                lrange = comedi_alloc_spriv(s,
 977                                            sizeof(*lrange) + sizeof(*krange));
 978                if (!lrange)
 979                        return &range_unknown;
 980
 981                /* initialize ai range */
 982                lrange->length = 1;
 983                krange = lrange->range;
 984                krange->min = min;
 985                krange->max = max;
 986                krange->flags = UNIT_volt;
 987
 988                return lrange;
 989        }
 990
 991        /* use software programmable range */
 992        if (status & DAS16_STATUS_UNIPOLAR)
 993                return das16_ai_uni_lranges[pg_type];
 994        return das16_ai_bip_lranges[pg_type];
 995}
 996
 997static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev,
 998                                                  struct comedi_subdevice *s,
 999                                                  struct comedi_devconfig *it)
1000{
1001        unsigned int min = it->options[6];
1002        unsigned int max = it->options[7];
1003
1004        /* get any user-defined output range */
1005        if (min || max) {
1006                struct comedi_lrange *lrange;
1007                struct comedi_krange *krange;
1008
1009                /* allocate single-range range table */
1010                lrange = comedi_alloc_spriv(s,
1011                                            sizeof(*lrange) + sizeof(*krange));
1012                if (!lrange)
1013                        return &range_unknown;
1014
1015                /* initialize ao range */
1016                lrange->length = 1;
1017                krange = lrange->range;
1018                krange->min = min;
1019                krange->max = max;
1020                krange->flags = UNIT_volt;
1021
1022                return lrange;
1023        }
1024
1025        return &range_unknown;
1026}
1027
1028static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1029{
1030        const struct das16_board *board = dev->board_ptr;
1031        struct das16_private_struct *devpriv;
1032        struct comedi_subdevice *s;
1033        unsigned int osc_base;
1034        unsigned int status;
1035        int ret;
1036
1037        /*  check that clock setting is valid */
1038        if (it->options[3]) {
1039                if (it->options[3] != 1 && it->options[3] != 10) {
1040                        dev_err(dev->class_dev,
1041                                "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1042                        return -EINVAL;
1043                }
1044        }
1045
1046        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1047        if (!devpriv)
1048                return -ENOMEM;
1049
1050        if (board->size < 0x400) {
1051                ret = comedi_request_region(dev, it->options[0], board->size);
1052                if (ret)
1053                        return ret;
1054        } else {
1055                ret = comedi_request_region(dev, it->options[0], 0x10);
1056                if (ret)
1057                        return ret;
1058                /* Request an additional region for the 8255 */
1059                ret = __comedi_request_region(dev, dev->iobase + 0x400,
1060                                              board->size & 0x3ff);
1061                if (ret)
1062                        return ret;
1063                devpriv->extra_iobase = dev->iobase + 0x400;
1064                devpriv->can_burst = 1;
1065        }
1066
1067        /*  probe id bits to make sure they are consistent */
1068        if (das16_probe(dev, it))
1069                return -EINVAL;
1070
1071        /*  get master clock speed */
1072        osc_base = I8254_OSC_BASE_1MHZ;
1073        if (devpriv->can_burst) {
1074                status = inb(dev->iobase + DAS1600_STATUS_REG);
1075                if (status & DAS1600_STATUS_CLK_10MHZ)
1076                        osc_base = I8254_OSC_BASE_10MHZ;
1077        } else {
1078                if (it->options[3])
1079                        osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
1080        }
1081
1082        dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
1083                                      osc_base, I8254_IO8, 0);
1084        if (!dev->pacer)
1085                return -ENOMEM;
1086
1087        das16_alloc_dma(dev, it->options[2]);
1088
1089        ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1090        if (ret)
1091                return ret;
1092
1093        status = inb(dev->iobase + DAS16_STATUS_REG);
1094
1095        /* Analog Input subdevice */
1096        s = &dev->subdevices[0];
1097        s->type         = COMEDI_SUBD_AI;
1098        s->subdev_flags = SDF_READABLE;
1099        if (status & DAS16_STATUS_MUXBIT) {
1100                s->subdev_flags |= SDF_GROUND;
1101                s->n_chan       = 16;
1102        } else {
1103                s->subdev_flags |= SDF_DIFF;
1104                s->n_chan       = 8;
1105        }
1106        s->len_chanlist = s->n_chan;
1107        s->maxdata      = board->ai_maxdata;
1108        s->range_table  = das16_ai_range(dev, s, it, board->ai_pg, status);
1109        s->insn_read    = das16_ai_insn_read;
1110        if (devpriv->dma) {
1111                dev->read_subdev = s;
1112                s->subdev_flags |= SDF_CMD_READ;
1113                s->do_cmdtest   = das16_cmd_test;
1114                s->do_cmd       = das16_cmd_exec;
1115                s->cancel       = das16_cancel;
1116                s->munge        = das16_ai_munge;
1117        }
1118
1119        /* Analog Output subdevice */
1120        s = &dev->subdevices[1];
1121        if (board->has_ao) {
1122                s->type         = COMEDI_SUBD_AO;
1123                s->subdev_flags = SDF_WRITABLE;
1124                s->n_chan       = 2;
1125                s->maxdata      = 0x0fff;
1126                s->range_table  = das16_ao_range(dev, s, it);
1127                s->insn_write   = das16_ao_insn_write;
1128
1129                ret = comedi_alloc_subdev_readback(s);
1130                if (ret)
1131                        return ret;
1132        } else {
1133                s->type         = COMEDI_SUBD_UNUSED;
1134        }
1135
1136        /* Digital Input subdevice */
1137        s = &dev->subdevices[2];
1138        s->type         = COMEDI_SUBD_DI;
1139        s->subdev_flags = SDF_READABLE;
1140        s->n_chan       = 4;
1141        s->maxdata      = 1;
1142        s->range_table  = &range_digital;
1143        s->insn_bits    = das16_di_insn_bits;
1144
1145        /* Digital Output subdevice */
1146        s = &dev->subdevices[3];
1147        s->type         = COMEDI_SUBD_DO;
1148        s->subdev_flags = SDF_WRITABLE;
1149        s->n_chan       = 4;
1150        s->maxdata      = 1;
1151        s->range_table  = &range_digital;
1152        s->insn_bits    = das16_do_insn_bits;
1153
1154        /* initialize digital output lines */
1155        outb(s->state, dev->iobase + DAS16_DIO_REG);
1156
1157        /* 8255 Digital I/O subdevice */
1158        if (board->has_8255) {
1159                s = &dev->subdevices[4];
1160                ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
1161                if (ret)
1162                        return ret;
1163        }
1164
1165        das16_reset(dev);
1166        /* set the interrupt level */
1167        devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1168        outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1169
1170        if (devpriv->can_burst) {
1171                outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1172                outb(0, dev->iobase + DAS1600_CONV_REG);
1173                outb(0, dev->iobase + DAS1600_BURST_REG);
1174        }
1175
1176        return 0;
1177}
1178
1179static void das16_detach(struct comedi_device *dev)
1180{
1181        const struct das16_board *board = dev->board_ptr;
1182        struct das16_private_struct *devpriv = dev->private;
1183
1184        if (devpriv) {
1185                if (dev->iobase)
1186                        das16_reset(dev);
1187                das16_free_dma(dev);
1188
1189                if (devpriv->extra_iobase)
1190                        release_region(devpriv->extra_iobase,
1191                                       board->size & 0x3ff);
1192        }
1193
1194        comedi_legacy_detach(dev);
1195}
1196
1197static struct comedi_driver das16_driver = {
1198        .driver_name    = "das16",
1199        .module         = THIS_MODULE,
1200        .attach         = das16_attach,
1201        .detach         = das16_detach,
1202        .board_name     = &das16_boards[0].name,
1203        .num_names      = ARRAY_SIZE(das16_boards),
1204        .offset         = sizeof(das16_boards[0]),
1205};
1206module_comedi_driver(das16_driver);
1207
1208MODULE_AUTHOR("Comedi http://www.comedi.org");
1209MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1210MODULE_LICENSE("GPL");
1211