linux/drivers/staging/comedi/drivers/das16.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/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    You should have received a copy of the GNU General Public License
  21    along with this program; if not, write to the Free Software
  22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23
  24************************************************************************
  25*/
  26/*
  27Driver: das16
  28Description: DAS16 compatible boards
  29Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
  30Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
  31  DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
  32  DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
  33  DAS-1602 (das-1602),
  34  [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
  35  PC104-DAS16JR/16 (pc104-das16jr/16),
  36  CIO-DAS16JR/16 (cio-das16jr/16),
  37  CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
  38  CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
  39  CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
  40  CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
  41Status: works
  42Updated: 2003-10-12
  43
  44A rewrite of the das16 and das1600 drivers.
  45Options:
  46        [0] - base io address
  47        [1] - irq (does nothing, irq is not used anymore)
  48        [2] - dma (optional, required for comedi_command support)
  49        [3] - master clock speed in MHz (optional, 1 or 10, ignored if
  50                board can probe clock, defaults to 1)
  51        [4] - analog input range lowest voltage in microvolts (optional,
  52                only useful if your board does not have software
  53                programmable gain)
  54        [5] - analog input range highest voltage in microvolts (optional,
  55                only useful if board does not have software programmable
  56                gain)
  57        [6] - analog output range lowest voltage in microvolts (optional)
  58        [7] - analog output range highest voltage in microvolts (optional)
  59        [8] - use timer mode for DMA.  Timer mode is needed e.g. for
  60                buggy DMA controllers in NS CS5530A (Geode Companion), and for
  61                'jr' cards that lack a hardware fifo.  This option is no
  62                longer needed, since timer mode is _always_ used.
  63
  64Passing a zero for an option is the same as leaving it unspecified.
  65
  66*/
  67/*
  68
  69Testing and debugging help provided by Daniel Koch.
  70
  71Keithley Manuals:
  72        2309.PDF (das16)
  73        4919.PDF (das1400, 1600)
  74        4922.PDF (das-1400)
  75        4923.PDF (das1200, 1400, 1600)
  76
  77Computer boards manuals also available from their website
  78www.measurementcomputing.com
  79
  80*/
  81
  82#include <linux/pci.h>
  83#include <linux/slab.h>
  84#include <linux/interrupt.h>
  85
  86#include <asm/dma.h>
  87
  88#include "../comedidev.h"
  89
  90#include "8253.h"
  91#include "8255.h"
  92#include "comedi_fc.h"
  93
  94#undef DEBUG
  95/* #define DEBUG */
  96
  97#ifdef DEBUG
  98#define DEBUG_PRINT(format, args...)    \
  99        printk(KERN_DEBUG "das16: " format, ## args)
 100#else
 101#define DEBUG_PRINT(format, args...)
 102#endif
 103
 104#define DAS16_SIZE 20           /*  number of ioports */
 105#define DAS16_DMA_SIZE 0xff00   /*  size in bytes of allocated dma buffer */
 106
 107/*
 108    cio-das16.pdf
 109
 110    "das16"
 111    "das16/f"
 112
 113  0     a/d bits 0-3            start 12 bit
 114  1     a/d bits 4-11           unused
 115  2     mux read                mux set
 116  3     di 4 bit                do 4 bit
 117  4     unused                  ao0_lsb
 118  5     unused                  ao0_msb
 119  6     unused                  ao1_lsb
 120  7     unused                  ao1_msb
 121  8     status eoc uni/bip      interrupt reset
 122  9     dma, int, trig ctrl     set dma, int
 123  a     pacer control           unused
 124  b     reserved                reserved
 125  cdef  8254
 126  0123  8255
 127
 128*/
 129
 130/*
 131    cio-das16jr.pdf
 132
 133    "das16jr"
 134
 135  0     a/d bits 0-3            start 12 bit
 136  1     a/d bits 4-11           unused
 137  2     mux read                mux set
 138  3     di 4 bit                do 4 bit
 139  4567  unused                  unused
 140  8     status eoc uni/bip      interrupt reset
 141  9     dma, int, trig ctrl     set dma, int
 142  a     pacer control           unused
 143  b     gain status             gain control
 144  cdef  8254
 145
 146*/
 147
 148/*
 149    cio-das16jr_16.pdf
 150
 151    "das16jr_16"
 152
 153  0     a/d bits 0-7            start 16 bit
 154  1     a/d bits 8-15           unused
 155  2     mux read                mux set
 156  3     di 4 bit                do 4 bit
 157  4567  unused                  unused
 158  8     status eoc uni/bip      interrupt reset
 159  9     dma, int, trig ctrl     set dma, int
 160  a     pacer control           unused
 161  b     gain status             gain control
 162  cdef  8254
 163
 164*/
 165/*
 166    cio-das160x-1x.pdf
 167
 168    "das1601/12"
 169    "das1602/12"
 170    "das1602/16"
 171
 172  0     a/d bits 0-3            start 12 bit
 173  1     a/d bits 4-11           unused
 174  2     mux read                mux set
 175  3     di 4 bit                do 4 bit
 176  4     unused                  ao0_lsb
 177  5     unused                  ao0_msb
 178  6     unused                  ao1_lsb
 179  7     unused                  ao1_msb
 180  8     status eoc uni/bip      interrupt reset
 181  9     dma, int, trig ctrl     set dma, int
 182  a     pacer control           unused
 183  b     gain status             gain control
 184  cdef  8254
 185  400   8255
 186  404   unused                  conversion enable
 187  405   unused                  burst enable
 188  406   unused                  das1600 enable
 189  407   status
 190
 191*/
 192
 193/*  size in bytes of a sample from board */
 194static const int sample_size = 2;
 195
 196#define DAS16_TRIG              0
 197#define DAS16_AI_LSB            0
 198#define DAS16_AI_MSB            1
 199#define DAS16_MUX               2
 200#define DAS16_DIO               3
 201#define DAS16_AO_LSB(x) ((x) ? 6 : 4)
 202#define DAS16_AO_MSB(x) ((x) ? 7 : 5)
 203#define DAS16_STATUS            8
 204#define   BUSY                  (1<<7)
 205#define   UNIPOLAR                      (1<<6)
 206#define   DAS16_MUXBIT                  (1<<5)
 207#define   DAS16_INT                     (1<<4)
 208#define DAS16_CONTROL           9
 209#define   DAS16_INTE                    (1<<7)
 210#define   DAS16_IRQ(x)                  (((x) & 0x7) << 4)
 211#define   DMA_ENABLE                    (1<<2)
 212#define   PACING_MASK   0x3
 213#define   INT_PACER             0x03
 214#define   EXT_PACER                     0x02
 215#define   DAS16_SOFT            0x00
 216#define DAS16_PACER             0x0A
 217#define   DAS16_CTR0                    (1<<1)
 218#define   DAS16_TRIG0                   (1<<0)
 219#define   BURST_LEN_BITS(x)                     (((x) & 0xf) << 4)
 220#define DAS16_GAIN              0x0B
 221#define DAS16_CNTR0_DATA                0x0C
 222#define DAS16_CNTR1_DATA                0x0D
 223#define DAS16_CNTR2_DATA                0x0E
 224#define DAS16_CNTR_CONTROL      0x0F
 225#define   DAS16_TERM_CNT        0x00
 226#define   DAS16_ONE_SHOT        0x02
 227#define   DAS16_RATE_GEN        0x04
 228#define   DAS16_CNTR_LSB_MSB    0x30
 229#define   DAS16_CNTR0           0x00
 230#define   DAS16_CNTR1           0x40
 231#define   DAS16_CNTR2           0x80
 232
 233#define DAS1600_CONV            0x404
 234#define   DAS1600_CONV_DISABLE          0x40
 235#define DAS1600_BURST           0x405
 236#define   DAS1600_BURST_VAL             0x40
 237#define DAS1600_ENABLE          0x406
 238#define   DAS1600_ENABLE_VAL            0x40
 239#define DAS1600_STATUS_B        0x407
 240#define   DAS1600_BME           0x40
 241#define   DAS1600_ME            0x20
 242#define   DAS1600_CD                    0x10
 243#define   DAS1600_WS                    0x02
 244#define   DAS1600_CLK_10MHZ             0x01
 245
 246static const struct comedi_lrange range_das1x01_bip = { 4, {
 247                                                            BIP_RANGE(10),
 248                                                            BIP_RANGE(1),
 249                                                            BIP_RANGE(0.1),
 250                                                            BIP_RANGE(0.01),
 251                                                            }
 252};
 253
 254static const struct comedi_lrange range_das1x01_unip = { 4, {
 255                                                             UNI_RANGE(10),
 256                                                             UNI_RANGE(1),
 257                                                             UNI_RANGE(0.1),
 258                                                             UNI_RANGE(0.01),
 259                                                             }
 260};
 261
 262static const struct comedi_lrange range_das1x02_bip = { 4, {
 263                                                            BIP_RANGE(10),
 264                                                            BIP_RANGE(5),
 265                                                            BIP_RANGE(2.5),
 266                                                            BIP_RANGE(1.25),
 267                                                            }
 268};
 269
 270static const struct comedi_lrange range_das1x02_unip = { 4, {
 271                                                             UNI_RANGE(10),
 272                                                             UNI_RANGE(5),
 273                                                             UNI_RANGE(2.5),
 274                                                             UNI_RANGE(1.25),
 275                                                             }
 276};
 277
 278static const struct comedi_lrange range_das16jr = { 9, {
 279                                                /*  also used by 16/330 */
 280                                                        BIP_RANGE(10),
 281                                                        BIP_RANGE(5),
 282                                                        BIP_RANGE(2.5),
 283                                                        BIP_RANGE(1.25),
 284                                                        BIP_RANGE(0.625),
 285                                                        UNI_RANGE(10),
 286                                                        UNI_RANGE(5),
 287                                                        UNI_RANGE(2.5),
 288                                                        UNI_RANGE(1.25),
 289                                                        }
 290};
 291
 292static const struct comedi_lrange range_das16jr_16 = { 8, {
 293                                                           BIP_RANGE(10),
 294                                                           BIP_RANGE(5),
 295                                                           BIP_RANGE(2.5),
 296                                                           BIP_RANGE(1.25),
 297                                                           UNI_RANGE(10),
 298                                                           UNI_RANGE(5),
 299                                                           UNI_RANGE(2.5),
 300                                                           UNI_RANGE(1.25),
 301                                                           }
 302};
 303
 304static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
 305static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 306static const int das1600_gainlist[] = { 0, 1, 2, 3 };
 307
 308enum {
 309        das16_pg_none = 0,
 310        das16_pg_16jr,
 311        das16_pg_16jr_16,
 312        das16_pg_1601,
 313        das16_pg_1602,
 314};
 315static const int *const das16_gainlists[] = {
 316        NULL,
 317        das16jr_gainlist,
 318        das16jr_16_gainlist,
 319        das1600_gainlist,
 320        das1600_gainlist,
 321};
 322
 323static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
 324        &range_unknown,
 325        &range_das16jr,
 326        &range_das16jr_16,
 327        &range_das1x01_unip,
 328        &range_das1x02_unip,
 329};
 330
 331static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
 332        &range_unknown,
 333        &range_das16jr,
 334        &range_das16jr_16,
 335        &range_das1x01_bip,
 336        &range_das1x02_bip,
 337};
 338
 339struct munge_info {
 340        uint8_t byte;
 341        unsigned have_byte:1;
 342};
 343
 344struct das16_board {
 345        const char *name;
 346        void *ai;
 347        unsigned int ai_nbits;
 348        unsigned int ai_speed;  /*  max conversion speed in nanosec */
 349        unsigned int ai_pg;
 350        void *ao;
 351        unsigned int ao_nbits;
 352        void *di;
 353        void *do_;
 354
 355        unsigned int i8255_offset;
 356        unsigned int i8254_offset;
 357
 358        unsigned int size;
 359        unsigned int id;
 360};
 361
 362#define DAS16_TIMEOUT 1000
 363
 364/* Period for timer interrupt in jiffies.  It's a function
 365 * to deal with possibility of dynamic HZ patches  */
 366static inline int timer_period(void)
 367{
 368        return HZ / 20;
 369}
 370
 371struct das16_private_struct {
 372        unsigned int ai_unipolar;       /*  unipolar flag */
 373        unsigned int ai_singleended;    /*  single ended flag */
 374        unsigned int clockbase; /*  master clock speed in ns */
 375        volatile unsigned int control_state;    /*  dma, interrupt and trigger control bits */
 376        volatile unsigned long adc_byte_count;  /*  number of bytes remaining */
 377        /*  divisor dividing master clock to get conversion frequency */
 378        unsigned int divisor1;
 379        /*  divisor dividing master clock to get conversion frequency */
 380        unsigned int divisor2;
 381        unsigned int dma_chan;  /*  dma channel */
 382        uint16_t *dma_buffer[2];
 383        dma_addr_t dma_buffer_addr[2];
 384        unsigned int current_buffer;
 385        volatile unsigned int dma_transfer_size;        /*  target number of bytes to transfer per dma shot */
 386        /**
 387         * user-defined analog input and output ranges
 388         * defined from config options
 389         */
 390        struct comedi_lrange *user_ai_range_table;
 391        struct comedi_lrange *user_ao_range_table;
 392
 393        struct timer_list timer;        /*  for timed interrupt */
 394        volatile short timer_running;
 395        volatile short timer_mode;      /*  true if using timer mode */
 396};
 397
 398static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 399                          struct comedi_cmd *cmd)
 400{
 401        const struct das16_board *board = comedi_board(dev);
 402        struct das16_private_struct *devpriv = dev->private;
 403        int err = 0, tmp;
 404        int gain, start_chan, i;
 405        int mask;
 406
 407        /* Step 1 : check if triggers are trivially valid */
 408
 409        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
 410
 411        mask = TRIG_FOLLOW;
 412        /*  if board supports burst mode */
 413        if (board->size > 0x400)
 414                mask |= TRIG_TIMER | TRIG_EXT;
 415        err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
 416
 417        tmp = cmd->convert_src;
 418        mask = TRIG_TIMER | TRIG_EXT;
 419        /*  if board supports burst mode */
 420        if (board->size > 0x400)
 421                mask |= TRIG_NOW;
 422        err |= cfc_check_trigger_src(&cmd->convert_src, mask);
 423
 424        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 425        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 426
 427        if (err)
 428                return 1;
 429
 430        /* Step 2a : make sure trigger sources are unique */
 431
 432        err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
 433        err |= cfc_check_trigger_is_unique(cmd->convert_src);
 434        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 435
 436        /* Step 2b : and mutually compatible */
 437
 438        /*  make sure scan_begin_src and convert_src dont conflict */
 439        if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
 440                err |= -EINVAL;
 441        if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
 442                err |= -EINVAL;
 443
 444        if (err)
 445                return 2;
 446
 447        /* Step 3: check if arguments are trivially valid */
 448
 449        err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 450
 451        if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 452                err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 453
 454        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 455
 456        /* check against maximum frequency */
 457        if (cmd->scan_begin_src == TRIG_TIMER)
 458                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
 459                                        board->ai_speed * cmd->chanlist_len);
 460
 461        if (cmd->convert_src == TRIG_TIMER)
 462                err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
 463                                                 board->ai_speed);
 464
 465        if (cmd->stop_src == TRIG_NONE)
 466                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 467
 468        if (err)
 469                return 3;
 470
 471        /*  step 4: fix up arguments */
 472        if (cmd->scan_begin_src == TRIG_TIMER) {
 473                unsigned int tmp = cmd->scan_begin_arg;
 474                /*  set divisors, correct timing arguments */
 475                i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
 476                                               &(devpriv->divisor1),
 477                                               &(devpriv->divisor2),
 478                                               &(cmd->scan_begin_arg),
 479                                               cmd->flags & TRIG_ROUND_MASK);
 480                err += (tmp != cmd->scan_begin_arg);
 481        }
 482        if (cmd->convert_src == TRIG_TIMER) {
 483                unsigned int tmp = cmd->convert_arg;
 484                /*  set divisors, correct timing arguments */
 485                i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
 486                                               &(devpriv->divisor1),
 487                                               &(devpriv->divisor2),
 488                                               &(cmd->convert_arg),
 489                                               cmd->flags & TRIG_ROUND_MASK);
 490                err += (tmp != cmd->convert_arg);
 491        }
 492        if (err)
 493                return 4;
 494
 495        /*  check channel/gain list against card's limitations */
 496        if (cmd->chanlist) {
 497                gain = CR_RANGE(cmd->chanlist[0]);
 498                start_chan = CR_CHAN(cmd->chanlist[0]);
 499                for (i = 1; i < cmd->chanlist_len; i++) {
 500                        if (CR_CHAN(cmd->chanlist[i]) !=
 501                            (start_chan + i) % s->n_chan) {
 502                                comedi_error(dev,
 503                                                "entries in chanlist must be "
 504                                                "consecutive channels, "
 505                                                "counting upwards\n");
 506                                err++;
 507                        }
 508                        if (CR_RANGE(cmd->chanlist[i]) != gain) {
 509                                comedi_error(dev,
 510                                                "entries in chanlist must all "
 511                                                "have the same gain\n");
 512                                err++;
 513                        }
 514                }
 515        }
 516        if (err)
 517                return 5;
 518
 519        return 0;
 520}
 521
 522/* utility function that suggests a dma transfer size in bytes */
 523static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
 524                                                const struct comedi_cmd *cmd)
 525{
 526        struct das16_private_struct *devpriv = dev->private;
 527        unsigned int size;
 528        unsigned int freq;
 529
 530        /* if we are using timer interrupt, we don't care how long it
 531         * will take to complete transfer since it will be interrupted
 532         * by timer interrupt */
 533        if (devpriv->timer_mode)
 534                return DAS16_DMA_SIZE;
 535
 536        /* otherwise, we are relying on dma terminal count interrupt,
 537         * so pick a reasonable size */
 538        if (cmd->convert_src == TRIG_TIMER)
 539                freq = 1000000000 / cmd->convert_arg;
 540        else if (cmd->scan_begin_src == TRIG_TIMER)
 541                freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len;
 542        /*  return some default value */
 543        else
 544                freq = 0xffffffff;
 545
 546        if (cmd->flags & TRIG_WAKE_EOS) {
 547                size = sample_size * cmd->chanlist_len;
 548        } else {
 549                /*  make buffer fill in no more than 1/3 second */
 550                size = (freq / 3) * sample_size;
 551        }
 552
 553        /*  set a minimum and maximum size allowed */
 554        if (size > DAS16_DMA_SIZE)
 555                size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
 556        else if (size < sample_size)
 557                size = sample_size;
 558
 559        if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
 560                size = devpriv->adc_byte_count;
 561
 562        return size;
 563}
 564
 565static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 566                                    int rounding_flags)
 567{
 568        struct das16_private_struct *devpriv = dev->private;
 569
 570        i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
 571                                       &(devpriv->divisor2), &ns,
 572                                       rounding_flags & TRIG_ROUND_MASK);
 573
 574        /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
 575        i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
 576        i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
 577
 578        return ns;
 579}
 580
 581static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 582{
 583        const struct das16_board *board = comedi_board(dev);
 584        struct das16_private_struct *devpriv = dev->private;
 585        struct comedi_async *async = s->async;
 586        struct comedi_cmd *cmd = &async->cmd;
 587        unsigned int byte;
 588        unsigned long flags;
 589        int range;
 590
 591        if (devpriv->dma_chan == 0 || (dev->irq == 0
 592                                       && devpriv->timer_mode == 0)) {
 593                comedi_error(dev,
 594                                "irq (or use of 'timer mode') dma required to "
 595                                                        "execute comedi_cmd");
 596                return -1;
 597        }
 598        if (cmd->flags & TRIG_RT) {
 599                comedi_error(dev, "isa dma transfers cannot be performed with "
 600                                                        "TRIG_RT, aborting");
 601                return -1;
 602        }
 603
 604        devpriv->adc_byte_count =
 605            cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
 606
 607        /*  disable conversions for das1600 mode */
 608        if (board->size > 0x400)
 609                outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
 610
 611        /*  set scan limits */
 612        byte = CR_CHAN(cmd->chanlist[0]);
 613        byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
 614        outb(byte, dev->iobase + DAS16_MUX);
 615
 616        /* set gain (this is also burst rate register but according to
 617         * computer boards manual, burst rate does nothing, even on
 618         * keithley cards) */
 619        if (board->ai_pg != das16_pg_none) {
 620                range = CR_RANGE(cmd->chanlist[0]);
 621                outb((das16_gainlists[board->ai_pg])[range],
 622                     dev->iobase + DAS16_GAIN);
 623        }
 624
 625        /* set counter mode and counts */
 626        cmd->convert_arg =
 627            das16_set_pacer(dev, cmd->convert_arg,
 628                            cmd->flags & TRIG_ROUND_MASK);
 629        DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
 630
 631        /* enable counters */
 632        byte = 0;
 633        /* Enable burst mode if appropriate. */
 634        if (board->size > 0x400) {
 635                if (cmd->convert_src == TRIG_NOW) {
 636                        outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
 637                        /*  set burst length */
 638                        byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
 639                } else {
 640                        outb(0, dev->iobase + DAS1600_BURST);
 641                }
 642        }
 643        outb(byte, dev->iobase + DAS16_PACER);
 644
 645        /*  set up dma transfer */
 646        flags = claim_dma_lock();
 647        disable_dma(devpriv->dma_chan);
 648        /* clear flip-flop to make sure 2-byte registers for
 649         * count and address get set correctly */
 650        clear_dma_ff(devpriv->dma_chan);
 651        devpriv->current_buffer = 0;
 652        set_dma_addr(devpriv->dma_chan,
 653                     devpriv->dma_buffer_addr[devpriv->current_buffer]);
 654        /*  set appropriate size of transfer */
 655        devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd);
 656        set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
 657        enable_dma(devpriv->dma_chan);
 658        release_dma_lock(flags);
 659
 660        /*  set up interrupt */
 661        if (devpriv->timer_mode) {
 662                devpriv->timer_running = 1;
 663                devpriv->timer.expires = jiffies + timer_period();
 664                add_timer(&devpriv->timer);
 665                devpriv->control_state &= ~DAS16_INTE;
 666        } else {
 667                /* clear interrupt bit */
 668                outb(0x00, dev->iobase + DAS16_STATUS);
 669                /* enable interrupts */
 670                devpriv->control_state |= DAS16_INTE;
 671        }
 672        devpriv->control_state |= DMA_ENABLE;
 673        devpriv->control_state &= ~PACING_MASK;
 674        if (cmd->convert_src == TRIG_EXT)
 675                devpriv->control_state |= EXT_PACER;
 676        else
 677                devpriv->control_state |= INT_PACER;
 678        outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
 679
 680        /* Enable conversions if using das1600 mode */
 681        if (board->size > 0x400)
 682                outb(0, dev->iobase + DAS1600_CONV);
 683
 684
 685        return 0;
 686}
 687
 688static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 689{
 690        const struct das16_board *board = comedi_board(dev);
 691        struct das16_private_struct *devpriv = dev->private;
 692        unsigned long flags;
 693
 694        spin_lock_irqsave(&dev->spinlock, flags);
 695        /* disable interrupts, dma and pacer clocked conversions */
 696        devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
 697        outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
 698        if (devpriv->dma_chan)
 699                disable_dma(devpriv->dma_chan);
 700
 701        /*  disable SW timer */
 702        if (devpriv->timer_mode && devpriv->timer_running) {
 703                devpriv->timer_running = 0;
 704                del_timer(&devpriv->timer);
 705        }
 706
 707        /* disable burst mode */
 708        if (board->size > 0x400)
 709                outb(0, dev->iobase + DAS1600_BURST);
 710
 711
 712        spin_unlock_irqrestore(&dev->spinlock, flags);
 713
 714        return 0;
 715}
 716
 717static void das16_reset(struct comedi_device *dev)
 718{
 719        outb(0, dev->iobase + DAS16_STATUS);
 720        outb(0, dev->iobase + DAS16_CONTROL);
 721        outb(0, dev->iobase + DAS16_PACER);
 722        outb(0, dev->iobase + DAS16_CNTR_CONTROL);
 723}
 724
 725static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 726                          struct comedi_insn *insn, unsigned int *data)
 727{
 728        const struct das16_board *board = comedi_board(dev);
 729        struct das16_private_struct *devpriv = dev->private;
 730        int i, n;
 731        int range;
 732        int chan;
 733        int msb, lsb;
 734
 735        /*  disable interrupts and pacing */
 736        devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
 737        outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
 738
 739        /* set multiplexer */
 740        chan = CR_CHAN(insn->chanspec);
 741        chan |= CR_CHAN(insn->chanspec) << 4;
 742        outb(chan, dev->iobase + DAS16_MUX);
 743
 744        /* set gain */
 745        if (board->ai_pg != das16_pg_none) {
 746                range = CR_RANGE(insn->chanspec);
 747                outb((das16_gainlists[board->ai_pg])[range],
 748                     dev->iobase + DAS16_GAIN);
 749        }
 750
 751        for (n = 0; n < insn->n; n++) {
 752                /* trigger conversion */
 753                outb_p(0, dev->iobase + DAS16_TRIG);
 754
 755                for (i = 0; i < DAS16_TIMEOUT; i++) {
 756                        if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
 757                                break;
 758                }
 759                if (i == DAS16_TIMEOUT) {
 760                        printk("das16: timeout\n");
 761                        return -ETIME;
 762                }
 763                msb = inb(dev->iobase + DAS16_AI_MSB);
 764                lsb = inb(dev->iobase + DAS16_AI_LSB);
 765                if (board->ai_nbits == 12)
 766                        data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
 767                else
 768                        data[n] = lsb | (msb << 8);
 769
 770        }
 771
 772        return n;
 773}
 774
 775static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
 776                          struct comedi_insn *insn, unsigned int *data)
 777{
 778        unsigned int bits;
 779
 780        bits = inb(dev->iobase + DAS16_DIO) & 0xf;
 781        data[1] = bits;
 782        data[0] = 0;
 783
 784        return insn->n;
 785}
 786
 787static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
 788                          struct comedi_insn *insn, unsigned int *data)
 789{
 790        unsigned int wbits;
 791
 792        /*  only set bits that have been masked */
 793        data[0] &= 0xf;
 794        wbits = s->state;
 795        /*  zero bits that have been masked */
 796        wbits &= ~data[0];
 797        /*  set masked bits */
 798        wbits |= data[0] & data[1];
 799        s->state = wbits;
 800        data[1] = wbits;
 801
 802        outb(s->state, dev->iobase + DAS16_DIO);
 803
 804        return insn->n;
 805}
 806
 807static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
 808                          struct comedi_insn *insn, unsigned int *data)
 809{
 810        const struct das16_board *board = comedi_board(dev);
 811        int i;
 812        int lsb, msb;
 813        int chan;
 814
 815        chan = CR_CHAN(insn->chanspec);
 816
 817        for (i = 0; i < insn->n; i++) {
 818                if (board->ao_nbits == 12) {
 819                        lsb = (data[i] << 4) & 0xff;
 820                        msb = (data[i] >> 4) & 0xff;
 821                } else {
 822                        lsb = data[i] & 0xff;
 823                        msb = (data[i] >> 8) & 0xff;
 824                }
 825                outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
 826                outb(msb, dev->iobase + DAS16_AO_MSB(chan));
 827        }
 828
 829        return i;
 830}
 831
 832/* the pc104-das16jr (at least) has problems if the dma
 833        transfer is interrupted in the middle of transferring
 834        a 16 bit sample, so this function takes care to get
 835        an even transfer count after disabling dma
 836        channel.
 837*/
 838static int disable_dma_on_even(struct comedi_device *dev)
 839{
 840        struct das16_private_struct *devpriv = dev->private;
 841        int residue;
 842        int i;
 843        static const int disable_limit = 100;
 844        static const int enable_timeout = 100;
 845
 846        disable_dma(devpriv->dma_chan);
 847        residue = get_dma_residue(devpriv->dma_chan);
 848        for (i = 0; i < disable_limit && (residue % 2); ++i) {
 849                int j;
 850                enable_dma(devpriv->dma_chan);
 851                for (j = 0; j < enable_timeout; ++j) {
 852                        int new_residue;
 853                        udelay(2);
 854                        new_residue = get_dma_residue(devpriv->dma_chan);
 855                        if (new_residue != residue)
 856                                break;
 857                }
 858                disable_dma(devpriv->dma_chan);
 859                residue = get_dma_residue(devpriv->dma_chan);
 860        }
 861        if (i == disable_limit) {
 862                comedi_error(dev, "failed to get an even dma transfer, "
 863                                                        "could be trouble.");
 864        }
 865        return residue;
 866}
 867
 868static void das16_interrupt(struct comedi_device *dev)
 869{
 870        const struct das16_board *board = comedi_board(dev);
 871        struct das16_private_struct *devpriv = dev->private;
 872        unsigned long dma_flags, spin_flags;
 873        struct comedi_subdevice *s = dev->read_subdev;
 874        struct comedi_async *async;
 875        struct comedi_cmd *cmd;
 876        int num_bytes, residue;
 877        int buffer_index;
 878
 879        if (dev->attached == 0) {
 880                comedi_error(dev, "premature interrupt");
 881                return;
 882        }
 883        /*  initialize async here to make sure it is not NULL */
 884        async = s->async;
 885        cmd = &async->cmd;
 886
 887        if (devpriv->dma_chan == 0) {
 888                comedi_error(dev, "interrupt with no dma channel?");
 889                return;
 890        }
 891
 892        spin_lock_irqsave(&dev->spinlock, spin_flags);
 893        if ((devpriv->control_state & DMA_ENABLE) == 0) {
 894                spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 895                DEBUG_PRINT("interrupt while dma disabled?\n");
 896                return;
 897        }
 898
 899        dma_flags = claim_dma_lock();
 900        clear_dma_ff(devpriv->dma_chan);
 901        residue = disable_dma_on_even(dev);
 902
 903        /*  figure out how many points to read */
 904        if (residue > devpriv->dma_transfer_size) {
 905                comedi_error(dev, "residue > transfer size!\n");
 906                async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 907                num_bytes = 0;
 908        } else
 909                num_bytes = devpriv->dma_transfer_size - residue;
 910
 911        if (cmd->stop_src == TRIG_COUNT &&
 912                                        num_bytes >= devpriv->adc_byte_count) {
 913                num_bytes = devpriv->adc_byte_count;
 914                async->events |= COMEDI_CB_EOA;
 915        }
 916
 917        buffer_index = devpriv->current_buffer;
 918        devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
 919        devpriv->adc_byte_count -= num_bytes;
 920
 921        /*  figure out how many bytes for next transfer */
 922        if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
 923            devpriv->dma_transfer_size > devpriv->adc_byte_count)
 924                devpriv->dma_transfer_size = devpriv->adc_byte_count;
 925
 926        /*  re-enable  dma */
 927        if ((async->events & COMEDI_CB_EOA) == 0) {
 928                set_dma_addr(devpriv->dma_chan,
 929                             devpriv->dma_buffer_addr[devpriv->current_buffer]);
 930                set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
 931                enable_dma(devpriv->dma_chan);
 932                /* reenable conversions for das1600 mode, (stupid hardware) */
 933                if (board->size > 0x400 && devpriv->timer_mode == 0)
 934                        outb(0x00, dev->iobase + DAS1600_CONV);
 935
 936        }
 937        release_dma_lock(dma_flags);
 938
 939        spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 940
 941        cfc_write_array_to_buffer(s,
 942                                  devpriv->dma_buffer[buffer_index], num_bytes);
 943
 944        cfc_handle_events(dev, s);
 945}
 946
 947static irqreturn_t das16_dma_interrupt(int irq, void *d)
 948{
 949        int status;
 950        struct comedi_device *dev = d;
 951
 952        status = inb(dev->iobase + DAS16_STATUS);
 953
 954        if ((status & DAS16_INT) == 0) {
 955                DEBUG_PRINT("spurious interrupt\n");
 956                return IRQ_NONE;
 957        }
 958
 959        /* clear interrupt */
 960        outb(0x00, dev->iobase + DAS16_STATUS);
 961        das16_interrupt(dev);
 962        return IRQ_HANDLED;
 963}
 964
 965static void das16_timer_interrupt(unsigned long arg)
 966{
 967        struct comedi_device *dev = (struct comedi_device *)arg;
 968        struct das16_private_struct *devpriv = dev->private;
 969
 970        das16_interrupt(dev);
 971
 972        if (devpriv->timer_running)
 973                mod_timer(&devpriv->timer, jiffies + timer_period());
 974}
 975
 976static void reg_dump(struct comedi_device *dev)
 977{
 978        DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
 979        DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
 980        DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
 981        DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
 982        DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
 983        DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
 984        DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
 985        DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
 986                    inb(dev->iobase + DAS16_CNTR_CONTROL));
 987        DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
 988        DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
 989        DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
 990        DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
 991                    inb(dev->iobase + DAS1600_STATUS_B));
 992}
 993
 994static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 995{
 996        const struct das16_board *board = comedi_board(dev);
 997        struct das16_private_struct *devpriv = dev->private;
 998        int status;
 999        int diobits;
1000
1001        /* status is available on all boards */
1002
1003        status = inb(dev->iobase + DAS16_STATUS);
1004
1005        if ((status & UNIPOLAR))
1006                devpriv->ai_unipolar = 1;
1007        else
1008                devpriv->ai_unipolar = 0;
1009
1010
1011        if ((status & DAS16_MUXBIT))
1012                devpriv->ai_singleended = 1;
1013        else
1014                devpriv->ai_singleended = 0;
1015
1016
1017        /* diobits indicates boards */
1018
1019        diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
1020
1021        printk(KERN_INFO " id bits are 0x%02x\n", diobits);
1022        if (board->id != diobits) {
1023                printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
1024                       board->id);
1025        }
1026
1027        return 0;
1028}
1029
1030static int das1600_mode_detect(struct comedi_device *dev)
1031{
1032        struct das16_private_struct *devpriv = dev->private;
1033        int status = 0;
1034
1035        status = inb(dev->iobase + DAS1600_STATUS_B);
1036
1037        if (status & DAS1600_CLK_10MHZ) {
1038                devpriv->clockbase = 100;
1039                printk(KERN_INFO " 10MHz pacer clock\n");
1040        } else {
1041                devpriv->clockbase = 1000;
1042                printk(KERN_INFO " 1MHz pacer clock\n");
1043        }
1044
1045        reg_dump(dev);
1046
1047        return 0;
1048}
1049
1050static void das16_ai_munge(struct comedi_device *dev,
1051                           struct comedi_subdevice *s, void *array,
1052                           unsigned int num_bytes,
1053                           unsigned int start_chan_index)
1054{
1055        const struct das16_board *board = comedi_board(dev);
1056        unsigned int i, num_samples = num_bytes / sizeof(short);
1057        short *data = array;
1058
1059        for (i = 0; i < num_samples; i++) {
1060                data[i] = le16_to_cpu(data[i]);
1061                if (board->ai_nbits == 12)
1062                        data[i] = (data[i] >> 4) & 0xfff;
1063
1064        }
1065}
1066
1067/*
1068 *
1069 * Options list:
1070 *   0  I/O base
1071 *   1  IRQ
1072 *   2  DMA
1073 *   3  Clock speed (in MHz)
1074 */
1075static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1076{
1077        const struct das16_board *board = comedi_board(dev);
1078        struct das16_private_struct *devpriv;
1079        struct comedi_subdevice *s;
1080        int ret;
1081        unsigned int irq;
1082        unsigned long iobase;
1083        unsigned int dma_chan;
1084        int timer_mode;
1085        unsigned long flags;
1086        struct comedi_krange *user_ai_range, *user_ao_range;
1087
1088        iobase = it->options[0];
1089#if 0
1090        irq = it->options[1];
1091        timer_mode = it->options[8];
1092#endif
1093        /* always use time_mode since using irq can drop samples while
1094         * waiting for dma done interrupt (due to hardware limitations) */
1095        irq = 0;
1096        timer_mode = 1;
1097        if (timer_mode)
1098                irq = 0;
1099
1100        printk(KERN_INFO "comedi%d: das16:", dev->minor);
1101
1102        /*  check that clock setting is valid */
1103        if (it->options[3]) {
1104                if (it->options[3] != 0 &&
1105                    it->options[3] != 1 && it->options[3] != 10) {
1106                        printk
1107                            ("\n Invalid option.  Master clock must be set "
1108                                                        "to 1 or 10 (MHz)\n");
1109                        return -EINVAL;
1110                }
1111        }
1112
1113        devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1114        if (!devpriv)
1115                return -ENOMEM;
1116        dev->private = devpriv;
1117
1118        if (board->size < 0x400) {
1119                printk(" 0x%04lx-0x%04lx\n", iobase, iobase + board->size);
1120                if (!request_region(iobase, board->size, "das16")) {
1121                        printk(KERN_ERR " I/O port conflict\n");
1122                        return -EIO;
1123                }
1124        } else {
1125                printk(KERN_INFO " 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
1126                       iobase, iobase + 0x0f,
1127                       iobase + 0x400,
1128                       iobase + 0x400 + (board->size & 0x3ff));
1129                if (!request_region(iobase, 0x10, "das16")) {
1130                        printk(KERN_ERR " I/O port conflict:  0x%04lx-0x%04lx\n",
1131                               iobase, iobase + 0x0f);
1132                        return -EIO;
1133                }
1134                if (!request_region(iobase + 0x400, board->size & 0x3ff,
1135                                    "das16")) {
1136                        release_region(iobase, 0x10);
1137                        printk(KERN_ERR " I/O port conflict:  0x%04lx-0x%04lx\n",
1138                               iobase + 0x400,
1139                               iobase + 0x400 + (board->size & 0x3ff));
1140                        return -EIO;
1141                }
1142        }
1143
1144        dev->iobase = iobase;
1145
1146        /*  probe id bits to make sure they are consistent */
1147        if (das16_probe(dev, it)) {
1148                printk(KERN_ERR " id bits do not match selected board, aborting\n");
1149                return -EINVAL;
1150        }
1151        dev->board_name = board->name;
1152
1153        /*  get master clock speed */
1154        if (board->size < 0x400) {
1155                if (it->options[3])
1156                        devpriv->clockbase = 1000 / it->options[3];
1157                else
1158                        devpriv->clockbase = 1000;      /*  1 MHz default */
1159        } else {
1160                das1600_mode_detect(dev);
1161        }
1162
1163        /* now for the irq */
1164        if (irq > 1 && irq < 8) {
1165                ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev);
1166
1167                if (ret < 0)
1168                        return ret;
1169                dev->irq = irq;
1170                printk(KERN_INFO " ( irq = %u )", irq);
1171        } else if (irq == 0) {
1172                printk(" ( no irq )");
1173        } else {
1174                printk(" invalid irq\n");
1175                return -EINVAL;
1176        }
1177
1178        /*  initialize dma */
1179        dma_chan = it->options[2];
1180        if (dma_chan == 1 || dma_chan == 3) {
1181                /*  allocate dma buffers */
1182                int i;
1183                for (i = 0; i < 2; i++) {
1184                        devpriv->dma_buffer[i] = pci_alloc_consistent(
1185                                                NULL, DAS16_DMA_SIZE,
1186                                                &devpriv->dma_buffer_addr[i]);
1187
1188                        if (devpriv->dma_buffer[i] == NULL)
1189                                return -ENOMEM;
1190                }
1191                if (request_dma(dma_chan, "das16")) {
1192                        printk(KERN_ERR " failed to allocate dma channel %i\n",
1193                               dma_chan);
1194                        return -EINVAL;
1195                }
1196                devpriv->dma_chan = dma_chan;
1197                flags = claim_dma_lock();
1198                disable_dma(devpriv->dma_chan);
1199                set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1200                release_dma_lock(flags);
1201                printk(KERN_INFO " ( dma = %u)\n", dma_chan);
1202        } else if (dma_chan == 0) {
1203                printk(KERN_INFO " ( no dma )\n");
1204        } else {
1205                printk(KERN_ERR " invalid dma channel\n");
1206                return -EINVAL;
1207        }
1208
1209        /*  get any user-defined input range */
1210        if (board->ai_pg == das16_pg_none &&
1211            (it->options[4] || it->options[5])) {
1212                /*  allocate single-range range table */
1213                devpriv->user_ai_range_table =
1214                    kmalloc(sizeof(struct comedi_lrange) +
1215                            sizeof(struct comedi_krange), GFP_KERNEL);
1216                /*  initialize ai range */
1217                devpriv->user_ai_range_table->length = 1;
1218                user_ai_range = devpriv->user_ai_range_table->range;
1219                user_ai_range->min = it->options[4];
1220                user_ai_range->max = it->options[5];
1221                user_ai_range->flags = UNIT_volt;
1222        }
1223        /*  get any user-defined output range */
1224        if (it->options[6] || it->options[7]) {
1225                /*  allocate single-range range table */
1226                devpriv->user_ao_range_table =
1227                    kmalloc(sizeof(struct comedi_lrange) +
1228                            sizeof(struct comedi_krange), GFP_KERNEL);
1229                /*  initialize ao range */
1230                devpriv->user_ao_range_table->length = 1;
1231                user_ao_range = devpriv->user_ao_range_table->range;
1232                user_ao_range->min = it->options[6];
1233                user_ao_range->max = it->options[7];
1234                user_ao_range->flags = UNIT_volt;
1235        }
1236
1237        if (timer_mode) {
1238                init_timer(&(devpriv->timer));
1239                devpriv->timer.function = das16_timer_interrupt;
1240                devpriv->timer.data = (unsigned long)dev;
1241        }
1242        devpriv->timer_mode = timer_mode ? 1 : 0;
1243
1244        ret = comedi_alloc_subdevices(dev, 5);
1245        if (ret)
1246                return ret;
1247
1248        s = &dev->subdevices[0];
1249        dev->read_subdev = s;
1250        /* ai */
1251        if (board->ai) {
1252                s->type = COMEDI_SUBD_AI;
1253                s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1254                if (devpriv->ai_singleended) {
1255                        s->n_chan = 16;
1256                        s->len_chanlist = 16;
1257                        s->subdev_flags |= SDF_GROUND;
1258                } else {
1259                        s->n_chan = 8;
1260                        s->len_chanlist = 8;
1261                        s->subdev_flags |= SDF_DIFF;
1262                }
1263                s->maxdata = (1 << board->ai_nbits) - 1;
1264                if (devpriv->user_ai_range_table) { /*  user defined ai range */
1265                        s->range_table = devpriv->user_ai_range_table;
1266                } else if (devpriv->ai_unipolar) {
1267                        s->range_table = das16_ai_uni_lranges[board->ai_pg];
1268                } else {
1269                        s->range_table = das16_ai_bip_lranges[board->ai_pg];
1270                }
1271                s->insn_read = board->ai;
1272                s->do_cmdtest = das16_cmd_test;
1273                s->do_cmd = das16_cmd_exec;
1274                s->cancel = das16_cancel;
1275                s->munge = das16_ai_munge;
1276        } else {
1277                s->type = COMEDI_SUBD_UNUSED;
1278        }
1279
1280        s = &dev->subdevices[1];
1281        /* ao */
1282        if (board->ao) {
1283                s->type = COMEDI_SUBD_AO;
1284                s->subdev_flags = SDF_WRITABLE;
1285                s->n_chan = 2;
1286                s->maxdata = (1 << board->ao_nbits) - 1;
1287                /*  user defined ao range */
1288                if (devpriv->user_ao_range_table)
1289                        s->range_table = devpriv->user_ao_range_table;
1290                else
1291                        s->range_table = &range_unknown;
1292
1293                s->insn_write = board->ao;
1294        } else {
1295                s->type = COMEDI_SUBD_UNUSED;
1296        }
1297
1298        s = &dev->subdevices[2];
1299        /* di */
1300        if (board->di) {
1301                s->type = COMEDI_SUBD_DI;
1302                s->subdev_flags = SDF_READABLE;
1303                s->n_chan = 4;
1304                s->maxdata = 1;
1305                s->range_table = &range_digital;
1306                s->insn_bits = board->di;
1307        } else {
1308                s->type = COMEDI_SUBD_UNUSED;
1309        }
1310
1311        s = &dev->subdevices[3];
1312        /* do */
1313        if (board->do_) {
1314                s->type = COMEDI_SUBD_DO;
1315                s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1316                s->n_chan = 4;
1317                s->maxdata = 1;
1318                s->range_table = &range_digital;
1319                s->insn_bits = board->do_;
1320                /*  initialize digital output lines */
1321                outb(s->state, dev->iobase + DAS16_DIO);
1322        } else {
1323                s->type = COMEDI_SUBD_UNUSED;
1324        }
1325
1326        s = &dev->subdevices[4];
1327        /* 8255 */
1328        if (board->i8255_offset != 0) {
1329                subdev_8255_init(dev, s, NULL, (dev->iobase +
1330                                                board->i8255_offset));
1331        } else {
1332                s->type = COMEDI_SUBD_UNUSED;
1333        }
1334
1335        das16_reset(dev);
1336        /* set the interrupt level */
1337        devpriv->control_state = DAS16_IRQ(dev->irq);
1338        outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1339
1340        /*  turn on das1600 mode if available */
1341        if (board->size > 0x400) {
1342                outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1343                outb(0, dev->iobase + DAS1600_CONV);
1344                outb(0, dev->iobase + DAS1600_BURST);
1345        }
1346
1347        return 0;
1348}
1349
1350static void das16_detach(struct comedi_device *dev)
1351{
1352        const struct das16_board *board = comedi_board(dev);
1353        struct das16_private_struct *devpriv = dev->private;
1354
1355        das16_reset(dev);
1356        if (dev->subdevices)
1357                subdev_8255_cleanup(dev, &dev->subdevices[4]);
1358        if (devpriv) {
1359                int i;
1360                for (i = 0; i < 2; i++) {
1361                        if (devpriv->dma_buffer[i])
1362                                pci_free_consistent(NULL, DAS16_DMA_SIZE,
1363                                                    devpriv->dma_buffer[i],
1364                                                    devpriv->
1365                                                    dma_buffer_addr[i]);
1366                }
1367                if (devpriv->dma_chan)
1368                        free_dma(devpriv->dma_chan);
1369                kfree(devpriv->user_ai_range_table);
1370                kfree(devpriv->user_ao_range_table);
1371        }
1372        if (dev->irq)
1373                free_irq(dev->irq, dev);
1374        if (dev->iobase) {
1375                if (board->size < 0x400) {
1376                        release_region(dev->iobase, board->size);
1377                } else {
1378                        release_region(dev->iobase, 0x10);
1379                        release_region(dev->iobase + 0x400,
1380                                       board->size & 0x3ff);
1381                }
1382        }
1383}
1384
1385static const struct das16_board das16_boards[] = {
1386        {
1387                .name           = "das-16",
1388                .ai             = das16_ai_rinsn,
1389                .ai_nbits       = 12,
1390                .ai_speed       = 15000,
1391                .ai_pg          = das16_pg_none,
1392                .ao             = das16_ao_winsn,
1393                .ao_nbits       = 12,
1394                .di             = das16_di_rbits,
1395                .do_            = das16_do_wbits,
1396                .i8255_offset   = 0x10,
1397                .i8254_offset   = 0x0c,
1398                .size           = 0x14,
1399                .id             = 0x00,
1400        }, {
1401                .name           = "das-16g",
1402                .ai             = das16_ai_rinsn,
1403                .ai_nbits       = 12,
1404                .ai_speed       = 15000,
1405                .ai_pg          = das16_pg_none,
1406                .ao             = das16_ao_winsn,
1407                .ao_nbits       = 12,
1408                .di             = das16_di_rbits,
1409                .do_            = das16_do_wbits,
1410                .i8255_offset   = 0x10,
1411                .i8254_offset   = 0x0c,
1412                .size           = 0x14,
1413                .id             = 0x00,
1414        }, {
1415                .name           = "das-16f",
1416                .ai             = das16_ai_rinsn,
1417                .ai_nbits       = 12,
1418                .ai_speed       = 8500,
1419                .ai_pg          = das16_pg_none,
1420                .ao             = das16_ao_winsn,
1421                .ao_nbits       = 12,
1422                .di             = das16_di_rbits,
1423                .do_            = das16_do_wbits,
1424                .i8255_offset   = 0x10,
1425                .i8254_offset   = 0x0c,
1426                .size           = 0x14,
1427                .id             = 0x00,
1428        }, {
1429                .name           = "cio-das16",
1430                .ai             = das16_ai_rinsn,
1431                .ai_nbits       = 12,
1432                .ai_speed       = 20000,
1433                .ai_pg          = das16_pg_none,
1434                .ao             = das16_ao_winsn,
1435                .ao_nbits       = 12,
1436                .di             = das16_di_rbits,
1437                .do_            = das16_do_wbits,
1438                .i8255_offset   = 0x10,
1439                .i8254_offset   = 0x0c,
1440                .size           = 0x14,
1441                .id             = 0x80,
1442        }, {
1443                .name           = "cio-das16/f",
1444                .ai             = das16_ai_rinsn,
1445                .ai_nbits       = 12,
1446                .ai_speed       = 10000,
1447                .ai_pg          = das16_pg_none,
1448                .ao             = das16_ao_winsn,
1449                .ao_nbits       = 12,
1450                .di             = das16_di_rbits,
1451                .do_            = das16_do_wbits,
1452                .i8255_offset   = 0x10,
1453                .i8254_offset   = 0x0c,
1454                .size           = 0x14,
1455                .id             = 0x80,
1456        }, {
1457                .name           = "cio-das16/jr",
1458                .ai             = das16_ai_rinsn,
1459                .ai_nbits       = 12,
1460                .ai_speed       = 7692,
1461                .ai_pg          = das16_pg_16jr,
1462                .ao             = NULL,
1463                .di             = das16_di_rbits,
1464                .do_            = das16_do_wbits,
1465                .i8255_offset   = 0,
1466                .i8254_offset   = 0x0c,
1467                .size           = 0x10,
1468                .id             = 0x00,
1469        }, {
1470                .name           = "pc104-das16jr",
1471                .ai             = das16_ai_rinsn,
1472                .ai_nbits       = 12,
1473                .ai_speed       = 3300,
1474                .ai_pg          = das16_pg_16jr,
1475                .ao             = NULL,
1476                .di             = das16_di_rbits,
1477                .do_            = das16_do_wbits,
1478                .i8255_offset   = 0,
1479                .i8254_offset   = 0x0c,
1480                .size           = 0x10,
1481                .id             = 0x00,
1482        }, {
1483                .name           = "cio-das16jr/16",
1484                .ai             = das16_ai_rinsn,
1485                .ai_nbits       = 16,
1486                .ai_speed       = 10000,
1487                .ai_pg          = das16_pg_16jr_16,
1488                .ao             = NULL,
1489                .di             = das16_di_rbits,
1490                .do_            = das16_do_wbits,
1491                .i8255_offset   = 0,
1492                .i8254_offset   = 0x0c,
1493                .size           = 0x10,
1494                .id             = 0x00,
1495        }, {
1496                .name           = "pc104-das16jr/16",
1497                .ai             = das16_ai_rinsn,
1498                .ai_nbits       = 16,
1499                .ai_speed       = 10000,
1500                .ai_pg          = das16_pg_16jr_16,
1501                .ao             = NULL,
1502                .di             = das16_di_rbits,
1503                .do_            = das16_do_wbits,
1504                .i8255_offset   = 0,
1505                .i8254_offset   = 0x0c,
1506                .size           = 0x10,
1507                .id             = 0x00,
1508        }, {
1509                .name           = "das-1201",
1510                .ai             = das16_ai_rinsn,
1511                .ai_nbits       = 12,
1512                .ai_speed       = 20000,
1513                .ai_pg          = das16_pg_none,
1514                .ao             = NULL,
1515                .di             = das16_di_rbits,
1516                .do_            = das16_do_wbits,
1517                .i8255_offset   = 0x400,
1518                .i8254_offset   = 0x0c,
1519                .size           = 0x408,
1520                .id             = 0x20,
1521        }, {
1522                .name           = "das-1202",
1523                .ai             = das16_ai_rinsn,
1524                .ai_nbits       = 12,
1525                .ai_speed       = 10000,
1526                .ai_pg          = das16_pg_none,
1527                .ao             = NULL,
1528                .di             = das16_di_rbits,
1529                .do_            = das16_do_wbits,
1530                .i8255_offset   = 0x400,
1531                .i8254_offset   = 0x0c,
1532                .size           = 0x408,
1533                .id             = 0x20,
1534        }, {
1535                .name           = "das-1401",
1536                .ai             = das16_ai_rinsn,
1537                .ai_nbits       = 12,
1538                .ai_speed       = 10000,
1539                .ai_pg          = das16_pg_1601,
1540                .ao             = NULL,
1541                .di             = das16_di_rbits,
1542                .do_            = das16_do_wbits,
1543                .i8255_offset   = 0x0,
1544                .i8254_offset   = 0x0c,
1545                .size           = 0x408,
1546                .id             = 0xc0,
1547        }, {
1548                .name           = "das-1402",
1549                .ai             = das16_ai_rinsn,
1550                .ai_nbits       = 12,
1551                .ai_speed       = 10000,
1552                .ai_pg          = das16_pg_1602,
1553                .ao             = NULL,
1554                .di             = das16_di_rbits,
1555                .do_            = das16_do_wbits,
1556                .i8255_offset   = 0x0,
1557                .i8254_offset   = 0x0c,
1558                .size           = 0x408,
1559                .id             = 0xc0,
1560        }, {
1561                .name           = "das-1601",
1562                .ai             = das16_ai_rinsn,
1563                .ai_nbits       = 12,
1564                .ai_speed       = 10000,
1565                .ai_pg          = das16_pg_1601,
1566                .ao             = das16_ao_winsn,
1567                .ao_nbits       = 12,
1568                .di             = das16_di_rbits,
1569                .do_            = das16_do_wbits,
1570                .i8255_offset   = 0x400,
1571                .i8254_offset   = 0x0c,
1572                .size           = 0x408,
1573                .id             = 0xc0,
1574        }, {
1575                .name           = "das-1602",
1576                .ai             = das16_ai_rinsn,
1577                .ai_nbits       = 12,
1578                .ai_speed       = 10000,
1579                .ai_pg          = das16_pg_1602,
1580                .ao             = das16_ao_winsn,
1581                .ao_nbits       = 12,
1582                .di             = das16_di_rbits,
1583                .do_            = das16_do_wbits,
1584                .i8255_offset   = 0x400,
1585                .i8254_offset   = 0x0c,
1586                .size           = 0x408,
1587                .id             = 0xc0,
1588        }, {
1589                .name           = "cio-das1401/12",
1590                .ai             = das16_ai_rinsn,
1591                .ai_nbits       = 12,
1592                .ai_speed       = 6250,
1593                .ai_pg          = das16_pg_1601,
1594                .ao             = NULL,
1595                .di             = das16_di_rbits,
1596                .do_            = das16_do_wbits,
1597                .i8255_offset   = 0,
1598                .i8254_offset   = 0x0c,
1599                .size           = 0x408,
1600                .id             = 0xc0,
1601        }, {
1602                .name           = "cio-das1402/12",
1603                .ai             = das16_ai_rinsn,
1604                .ai_nbits       = 12,
1605                .ai_speed       = 6250,
1606                .ai_pg          = das16_pg_1602,
1607                .ao             = NULL,
1608                .di             = das16_di_rbits,
1609                .do_            = das16_do_wbits,
1610                .i8255_offset   = 0,
1611                .i8254_offset   = 0x0c,
1612                .size           = 0x408,
1613                .id             = 0xc0,
1614        }, {
1615                .name           = "cio-das1402/16",
1616                .ai             = das16_ai_rinsn,
1617                .ai_nbits       = 16,
1618                .ai_speed       = 10000,
1619                .ai_pg          = das16_pg_1602,
1620                .ao             = NULL,
1621                .di             = das16_di_rbits,
1622                .do_            = das16_do_wbits,
1623                .i8255_offset   = 0,
1624                .i8254_offset   = 0x0c,
1625                .size           = 0x408,
1626                .id             = 0xc0,
1627        }, {
1628                .name           = "cio-das1601/12",
1629                .ai             = das16_ai_rinsn,
1630                .ai_nbits       = 12,
1631                .ai_speed       = 6250,
1632                .ai_pg          = das16_pg_1601,
1633                .ao             = das16_ao_winsn,
1634                .ao_nbits       = 12,
1635                .di             = das16_di_rbits,
1636                .do_            = das16_do_wbits,
1637                .i8255_offset   = 0x400,
1638                .i8254_offset   = 0x0c,
1639                .size           = 0x408,
1640                .id             = 0xc0,
1641        }, {
1642                .name           = "cio-das1602/12",
1643                .ai             = das16_ai_rinsn,
1644                .ai_nbits       = 12,
1645                .ai_speed       = 10000,
1646                .ai_pg          = das16_pg_1602,
1647                .ao             = das16_ao_winsn,
1648                .ao_nbits       = 12,
1649                .di             = das16_di_rbits,
1650                .do_            = das16_do_wbits,
1651                .i8255_offset   = 0x400,
1652                .i8254_offset   = 0x0c,
1653                .size           = 0x408,
1654                .id             = 0xc0,
1655        }, {
1656                .name           = "cio-das1602/16",
1657                .ai             = das16_ai_rinsn,
1658                .ai_nbits       = 16,
1659                .ai_speed       = 10000,
1660                .ai_pg          = das16_pg_1602,
1661                .ao             = das16_ao_winsn,
1662                .ao_nbits       = 12,
1663                .di             = das16_di_rbits,
1664                .do_            = das16_do_wbits,
1665                .i8255_offset   = 0x400,
1666                .i8254_offset   = 0x0c,
1667                .size           = 0x408,
1668                .id             = 0xc0,
1669        }, {
1670                .name           = "cio-das16/330",
1671                .ai             = das16_ai_rinsn,
1672                .ai_nbits       = 12,
1673                .ai_speed       = 3030,
1674                .ai_pg          = das16_pg_16jr,
1675                .ao             = NULL,
1676                .di             = das16_di_rbits,
1677                .do_            = das16_do_wbits,
1678                .i8255_offset   = 0,
1679                .i8254_offset   = 0x0c,
1680                .size           = 0x14,
1681                .id             = 0xf0,
1682        },
1683};
1684
1685static struct comedi_driver das16_driver = {
1686        .driver_name    = "das16",
1687        .module         = THIS_MODULE,
1688        .attach         = das16_attach,
1689        .detach         = das16_detach,
1690        .board_name     = &das16_boards[0].name,
1691        .num_names      = ARRAY_SIZE(das16_boards),
1692        .offset         = sizeof(das16_boards[0]),
1693};
1694module_comedi_driver(das16_driver);
1695
1696MODULE_AUTHOR("Comedi http://www.comedi.org");
1697MODULE_DESCRIPTION("Comedi low-level driver");
1698MODULE_LICENSE("GPL");
1699