linux/drivers/staging/comedi/drivers/ni_at_a2150.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/ni_at_a2150.c
   3    Driver for National Instruments AT-A2150 boards
   4    Copyright (C) 2001, 2002 Frank Mori Hess <fmhess@users.sourceforge.net>
   5
   6    COMEDI - Linux Control and Measurement Device Interface
   7    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   8
   9    This program is free software; you can redistribute it and/or modify
  10    it under the terms of the GNU General Public License as published by
  11    the Free Software Foundation; either version 2 of the License, or
  12    (at your option) any later version.
  13
  14    This program is distributed in the hope that it will be useful,
  15    but WITHOUT ANY WARRANTY; without even the implied warranty of
  16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  17    GNU General Public License for more details.
  18
  19    You should have received a copy of the GNU General Public License
  20    along with this program; if not, write to the Free Software
  21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  22
  23************************************************************************
  24*/
  25/*
  26Driver: ni_at_a2150
  27Description: National Instruments AT-A2150
  28Author: Frank Mori Hess
  29Status: works
  30Devices: [National Instruments] AT-A2150C (at_a2150c), AT-2150S (at_a2150s)
  31
  32If you want to ac couple the board's inputs, use AREF_OTHER.
  33
  34Configuration options:
  35  [0] - I/O port base address
  36  [1] - IRQ (optional, required for timed conversions)
  37  [2] - DMA (optional, required for timed conversions)
  38
  39*/
  40/*
  41Yet another driver for obsolete hardware brought to you by Frank Hess.
  42Testing and debugging help provided by Dave Andruczyk.
  43
  44This driver supports the boards:
  45
  46AT-A2150C
  47AT-A2150S
  48
  49The only difference is their master clock frequencies.
  50
  51Options:
  52        [0] - base io address
  53        [1] - irq
  54        [2] - dma channel
  55
  56References (from ftp://ftp.natinst.com/support/manuals):
  57
  58           320360.pdf  AT-A2150 User Manual
  59
  60TODO:
  61
  62analog level triggering
  63TRIG_WAKE_EOS
  64
  65*/
  66
  67#include <linux/interrupt.h>
  68#include <linux/slab.h>
  69#include "../comedidev.h"
  70
  71#include <linux/ioport.h>
  72#include <linux/io.h>
  73#include <asm/dma.h>
  74
  75#include "8253.h"
  76#include "comedi_fc.h"
  77
  78#define A2150_SIZE           28
  79#define A2150_DMA_BUFFER_SIZE   0xff00  /*  size in bytes of dma buffer */
  80
  81/* #define A2150_DEBUG     enable debugging code */
  82#undef A2150_DEBUG              /*  disable debugging code */
  83
  84/* Registers and bits */
  85#define CONFIG_REG              0x0
  86#define   CHANNEL_BITS(x)               ((x) & 0x7)
  87#define   CHANNEL_MASK          0x7
  88#define   CLOCK_SELECT_BITS(x)          (((x) & 0x3) << 3)
  89#define   CLOCK_DIVISOR_BITS(x)         (((x) & 0x3) << 5)
  90#define   CLOCK_MASK            (0xf << 3)
  91#define   ENABLE0_BIT           0x80    /*  enable (don't internally ground) channels 0 and 1 */
  92#define   ENABLE1_BIT           0x100   /*  enable (don't internally ground) channels 2 and 3 */
  93#define   AC0_BIT               0x200   /*  ac couple channels 0,1 */
  94#define   AC1_BIT               0x400   /*  ac couple channels 2,3 */
  95#define   APD_BIT               0x800   /*  analog power down */
  96#define   DPD_BIT               0x1000  /*  digital power down */
  97#define TRIGGER_REG             0x2     /*  trigger config register */
  98#define   POST_TRIGGER_BITS             0x2
  99#define   DELAY_TRIGGER_BITS            0x3
 100#define   HW_TRIG_EN            0x10    /*  enable hardware trigger */
 101#define FIFO_START_REG          0x6     /*  software start aquistion trigger */
 102#define FIFO_RESET_REG          0x8     /*  clears fifo + fifo flags */
 103#define FIFO_DATA_REG           0xa     /*  read data */
 104#define DMA_TC_CLEAR_REG                0xe     /*  clear dma terminal count interrupt */
 105#define STATUS_REG              0x12    /*  read only */
 106#define   FNE_BIT               0x1     /*  fifo not empty */
 107#define   OVFL_BIT              0x8     /*  fifo overflow */
 108#define   EDAQ_BIT              0x10    /*  end of acquisition interrupt */
 109#define   DCAL_BIT              0x20    /*  offset calibration in progress */
 110#define   INTR_BIT              0x40    /*  interrupt has occurred */
 111#define   DMA_TC_BIT            0x80    /*  dma terminal count interrupt has occurred */
 112#define   ID_BITS(x)    (((x) >> 8) & 0x3)
 113#define IRQ_DMA_CNTRL_REG               0x12    /*  write only */
 114#define   DMA_CHAN_BITS(x)              ((x) & 0x7)     /*  sets dma channel */
 115#define   DMA_EN_BIT            0x8     /*  enables dma */
 116#define   IRQ_LVL_BITS(x)               (((x) & 0xf) << 4)      /*  sets irq level */
 117#define   FIFO_INTR_EN_BIT              0x100   /*  enable fifo interrupts */
 118#define   FIFO_INTR_FHF_BIT             0x200   /*  interrupt fifo half full */
 119#define   DMA_INTR_EN_BIT               0x800   /*  enable interrupt on dma terminal count */
 120#define   DMA_DEM_EN_BIT        0x1000  /*  enables demand mode dma */
 121#define I8253_BASE_REG          0x14
 122#define I8253_MODE_REG          0x17
 123#define   HW_COUNT_DISABLE              0x30    /*  disable hardware counting of conversions */
 124
 125struct a2150_board {
 126        const char *name;
 127        int clock[4];           /*  master clock periods, in nanoseconds */
 128        int num_clocks;         /*  number of available master clock speeds */
 129        int ai_speed;           /*  maximum conversion rate in nanoseconds */
 130};
 131
 132/* analog input range */
 133static const struct comedi_lrange range_a2150 = {
 134        1,
 135        {
 136         RANGE(-2.828, 2.828),
 137         }
 138};
 139
 140/* enum must match board indices */
 141enum { a2150_c, a2150_s };
 142static const struct a2150_board a2150_boards[] = {
 143        {
 144         .name = "at-a2150c",
 145         .clock = {31250, 22676, 20833, 19531},
 146         .num_clocks = 4,
 147         .ai_speed = 19531,
 148         },
 149        {
 150         .name = "at-a2150s",
 151         .clock = {62500, 50000, 41667, 0},
 152         .num_clocks = 3,
 153         .ai_speed = 41667,
 154         },
 155};
 156
 157/*
 158 * Useful for shorthand access to the particular board structure
 159 */
 160#define thisboard ((const struct a2150_board *)dev->board_ptr)
 161
 162struct a2150_private {
 163
 164        volatile unsigned int count;    /* number of data points left to be taken */
 165        unsigned int dma;       /*  dma channel */
 166        s16 *dma_buffer;        /*  dma buffer */
 167        unsigned int dma_transfer_size; /*  size in bytes of dma transfers */
 168        int irq_dma_bits;       /*  irq/dma register bits */
 169        int config_bits;        /*  config register bits */
 170};
 171
 172#define devpriv ((struct a2150_private *)dev->private)
 173
 174static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
 175
 176static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
 177                            int flags);
 178static int a2150_set_chanlist(struct comedi_device *dev,
 179                              unsigned int start_channel,
 180                              unsigned int num_channels);
 181#ifdef A2150_DEBUG
 182
 183static void ni_dump_regs(struct comedi_device *dev)
 184{
 185        printk("config bits 0x%x\n", devpriv->config_bits);
 186        printk("irq dma bits 0x%x\n", devpriv->irq_dma_bits);
 187        printk("status bits 0x%x\n", inw(dev->iobase + STATUS_REG));
 188}
 189
 190#endif
 191
 192/* interrupt service routine */
 193static irqreturn_t a2150_interrupt(int irq, void *d)
 194{
 195        int i;
 196        int status;
 197        unsigned long flags;
 198        struct comedi_device *dev = d;
 199        struct comedi_subdevice *s = dev->read_subdev;
 200        struct comedi_async *async;
 201        struct comedi_cmd *cmd;
 202        unsigned int max_points, num_points, residue, leftover;
 203        short dpnt;
 204        static const int sample_size = sizeof(devpriv->dma_buffer[0]);
 205
 206        if (dev->attached == 0) {
 207                comedi_error(dev, "premature interrupt");
 208                return IRQ_HANDLED;
 209        }
 210        /*  initialize async here to make sure s is not NULL */
 211        async = s->async;
 212        async->events = 0;
 213        cmd = &async->cmd;
 214
 215        status = inw(dev->iobase + STATUS_REG);
 216
 217        if ((status & INTR_BIT) == 0) {
 218                comedi_error(dev, "spurious interrupt");
 219                return IRQ_NONE;
 220        }
 221
 222        if (status & OVFL_BIT) {
 223                comedi_error(dev, "fifo overflow");
 224                a2150_cancel(dev, s);
 225                async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 226        }
 227
 228        if ((status & DMA_TC_BIT) == 0) {
 229                comedi_error(dev, "caught non-dma interrupt?  Aborting.");
 230                a2150_cancel(dev, s);
 231                async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 232                comedi_event(dev, s);
 233                return IRQ_HANDLED;
 234        }
 235
 236        flags = claim_dma_lock();
 237        disable_dma(devpriv->dma);
 238        /* clear flip-flop to make sure 2-byte registers for
 239         * count and address get set correctly */
 240        clear_dma_ff(devpriv->dma);
 241
 242        /*  figure out how many points to read */
 243        max_points = devpriv->dma_transfer_size / sample_size;
 244        /* residue is the number of points left to be done on the dma
 245         * transfer.  It should always be zero at this point unless
 246         * the stop_src is set to external triggering.
 247         */
 248        residue = get_dma_residue(devpriv->dma) / sample_size;
 249        num_points = max_points - residue;
 250        if (devpriv->count < num_points && cmd->stop_src == TRIG_COUNT)
 251                num_points = devpriv->count;
 252
 253        /*  figure out how many points will be stored next time */
 254        leftover = 0;
 255        if (cmd->stop_src == TRIG_NONE) {
 256                leftover = devpriv->dma_transfer_size / sample_size;
 257        } else if (devpriv->count > max_points) {
 258                leftover = devpriv->count - max_points;
 259                if (leftover > max_points)
 260                        leftover = max_points;
 261        }
 262        /* there should only be a residue if collection was stopped by having
 263         * the stop_src set to an external trigger, in which case there
 264         * will be no more data
 265         */
 266        if (residue)
 267                leftover = 0;
 268
 269        for (i = 0; i < num_points; i++) {
 270                /* write data point to comedi buffer */
 271                dpnt = devpriv->dma_buffer[i];
 272                /*  convert from 2's complement to unsigned coding */
 273                dpnt ^= 0x8000;
 274                cfc_write_to_buffer(s, dpnt);
 275                if (cmd->stop_src == TRIG_COUNT) {
 276                        if (--devpriv->count == 0) {    /* end of acquisition */
 277                                a2150_cancel(dev, s);
 278                                async->events |= COMEDI_CB_EOA;
 279                                break;
 280                        }
 281                }
 282        }
 283        /*  re-enable  dma */
 284        if (leftover) {
 285                set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
 286                set_dma_count(devpriv->dma, leftover * sample_size);
 287                enable_dma(devpriv->dma);
 288        }
 289        release_dma_lock(flags);
 290
 291        async->events |= COMEDI_CB_BLOCK;
 292
 293        comedi_event(dev, s);
 294
 295        /* clear interrupt */
 296        outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
 297
 298        return IRQ_HANDLED;
 299}
 300
 301static int a2150_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 302{
 303        /*  disable dma on card */
 304        devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
 305        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 306
 307        /*  disable computer's dma */
 308        disable_dma(devpriv->dma);
 309
 310        /*  clear fifo and reset triggering circuitry */
 311        outw(0, dev->iobase + FIFO_RESET_REG);
 312
 313        return 0;
 314}
 315
 316static int a2150_ai_cmdtest(struct comedi_device *dev,
 317                            struct comedi_subdevice *s, struct comedi_cmd *cmd)
 318{
 319        int err = 0;
 320        int tmp;
 321        int startChan;
 322        int i;
 323
 324        /* Step 1 : check if triggers are trivially valid */
 325
 326        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 327        err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
 328        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 329        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 330        err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 331
 332        if (err)
 333                return 1;
 334
 335        /* Step 2a : make sure trigger sources are unique */
 336
 337        err |= cfc_check_trigger_is_unique(cmd->start_src);
 338        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 339
 340        /* Step 2b : and mutually compatible */
 341
 342        if (err)
 343                return 2;
 344
 345        /* step 3: make sure arguments are trivially compatible */
 346
 347        if (cmd->start_arg != 0) {
 348                cmd->start_arg = 0;
 349                err++;
 350        }
 351        if (cmd->convert_src == TRIG_TIMER) {
 352                if (cmd->convert_arg < thisboard->ai_speed) {
 353                        cmd->convert_arg = thisboard->ai_speed;
 354                        err++;
 355                }
 356        }
 357        if (!cmd->chanlist_len) {
 358                cmd->chanlist_len = 1;
 359                err++;
 360        }
 361        if (cmd->scan_end_arg != cmd->chanlist_len) {
 362                cmd->scan_end_arg = cmd->chanlist_len;
 363                err++;
 364        }
 365        if (cmd->stop_src == TRIG_COUNT) {
 366                if (!cmd->stop_arg) {
 367                        cmd->stop_arg = 1;
 368                        err++;
 369                }
 370        } else {                /* TRIG_NONE */
 371                if (cmd->stop_arg != 0) {
 372                        cmd->stop_arg = 0;
 373                        err++;
 374                }
 375        }
 376
 377        if (err)
 378                return 3;
 379
 380        /* step 4: fix up any arguments */
 381
 382        if (cmd->scan_begin_src == TRIG_TIMER) {
 383                tmp = cmd->scan_begin_arg;
 384                a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
 385                if (tmp != cmd->scan_begin_arg)
 386                        err++;
 387        }
 388
 389        if (err)
 390                return 4;
 391
 392        /*  check channel/gain list against card's limitations */
 393        if (cmd->chanlist) {
 394                startChan = CR_CHAN(cmd->chanlist[0]);
 395                for (i = 1; i < cmd->chanlist_len; i++) {
 396                        if (CR_CHAN(cmd->chanlist[i]) != (startChan + i)) {
 397                                comedi_error(dev,
 398                                             "entries in chanlist must be consecutive channels, counting upwards\n");
 399                                err++;
 400                        }
 401                }
 402                if (cmd->chanlist_len == 2 && CR_CHAN(cmd->chanlist[0]) == 1) {
 403                        comedi_error(dev,
 404                                     "length 2 chanlist must be channels 0,1 or channels 2,3");
 405                        err++;
 406                }
 407                if (cmd->chanlist_len == 3) {
 408                        comedi_error(dev,
 409                                     "chanlist must have 1,2 or 4 channels");
 410                        err++;
 411                }
 412                if (CR_AREF(cmd->chanlist[0]) != CR_AREF(cmd->chanlist[1]) ||
 413                    CR_AREF(cmd->chanlist[2]) != CR_AREF(cmd->chanlist[3])) {
 414                        comedi_error(dev,
 415                                     "channels 0/1 and 2/3 must have the same analog reference");
 416                        err++;
 417                }
 418        }
 419
 420        if (err)
 421                return 5;
 422
 423        return 0;
 424}
 425
 426static int a2150_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 427{
 428        struct comedi_async *async = s->async;
 429        struct comedi_cmd *cmd = &async->cmd;
 430        unsigned long lock_flags;
 431        unsigned int old_config_bits = devpriv->config_bits;
 432        unsigned int trigger_bits;
 433
 434        if (!dev->irq || !devpriv->dma) {
 435                comedi_error(dev,
 436                             " irq and dma required, cannot do hardware conversions");
 437                return -1;
 438        }
 439        if (cmd->flags & TRIG_RT) {
 440                comedi_error(dev,
 441                             " dma incompatible with hard real-time interrupt (TRIG_RT), aborting");
 442                return -1;
 443        }
 444        /*  clear fifo and reset triggering circuitry */
 445        outw(0, dev->iobase + FIFO_RESET_REG);
 446
 447        /* setup chanlist */
 448        if (a2150_set_chanlist(dev, CR_CHAN(cmd->chanlist[0]),
 449                               cmd->chanlist_len) < 0)
 450                return -1;
 451
 452        /*  setup ac/dc coupling */
 453        if (CR_AREF(cmd->chanlist[0]) == AREF_OTHER)
 454                devpriv->config_bits |= AC0_BIT;
 455        else
 456                devpriv->config_bits &= ~AC0_BIT;
 457        if (CR_AREF(cmd->chanlist[2]) == AREF_OTHER)
 458                devpriv->config_bits |= AC1_BIT;
 459        else
 460                devpriv->config_bits &= ~AC1_BIT;
 461
 462        /*  setup timing */
 463        a2150_get_timing(dev, &cmd->scan_begin_arg, cmd->flags);
 464
 465        /*  send timing, channel, config bits */
 466        outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
 467
 468        /*  initialize number of samples remaining */
 469        devpriv->count = cmd->stop_arg * cmd->chanlist_len;
 470
 471        /*  enable computer's dma */
 472        lock_flags = claim_dma_lock();
 473        disable_dma(devpriv->dma);
 474        /* clear flip-flop to make sure 2-byte registers for
 475         * count and address get set correctly */
 476        clear_dma_ff(devpriv->dma);
 477        set_dma_addr(devpriv->dma, virt_to_bus(devpriv->dma_buffer));
 478        /*  set size of transfer to fill in 1/3 second */
 479#define ONE_THIRD_SECOND 333333333
 480        devpriv->dma_transfer_size =
 481            sizeof(devpriv->dma_buffer[0]) * cmd->chanlist_len *
 482            ONE_THIRD_SECOND / cmd->scan_begin_arg;
 483        if (devpriv->dma_transfer_size > A2150_DMA_BUFFER_SIZE)
 484                devpriv->dma_transfer_size = A2150_DMA_BUFFER_SIZE;
 485        if (devpriv->dma_transfer_size < sizeof(devpriv->dma_buffer[0]))
 486                devpriv->dma_transfer_size = sizeof(devpriv->dma_buffer[0]);
 487        devpriv->dma_transfer_size -=
 488            devpriv->dma_transfer_size % sizeof(devpriv->dma_buffer[0]);
 489        set_dma_count(devpriv->dma, devpriv->dma_transfer_size);
 490        enable_dma(devpriv->dma);
 491        release_dma_lock(lock_flags);
 492
 493        /* clear dma interrupt before enabling it, to try and get rid of that
 494         * one spurious interrupt that has been happening */
 495        outw(0x00, dev->iobase + DMA_TC_CLEAR_REG);
 496
 497        /*  enable dma on card */
 498        devpriv->irq_dma_bits |= DMA_INTR_EN_BIT | DMA_EN_BIT;
 499        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 500
 501        /*  may need to wait 72 sampling periods if timing was changed */
 502        i8254_load(dev->iobase + I8253_BASE_REG, 0, 2, 72, 0);
 503
 504        /*  setup start triggering */
 505        trigger_bits = 0;
 506        /*  decide if we need to wait 72 periods for valid data */
 507        if (cmd->start_src == TRIG_NOW &&
 508            (old_config_bits & CLOCK_MASK) !=
 509            (devpriv->config_bits & CLOCK_MASK)) {
 510                /*  set trigger source to delay trigger */
 511                trigger_bits |= DELAY_TRIGGER_BITS;
 512        } else {
 513                /*  otherwise no delay */
 514                trigger_bits |= POST_TRIGGER_BITS;
 515        }
 516        /*  enable external hardware trigger */
 517        if (cmd->start_src == TRIG_EXT) {
 518                trigger_bits |= HW_TRIG_EN;
 519        } else if (cmd->start_src == TRIG_OTHER) {
 520                /*  XXX add support for level/slope start trigger using TRIG_OTHER */
 521                comedi_error(dev, "you shouldn't see this?");
 522        }
 523        /*  send trigger config bits */
 524        outw(trigger_bits, dev->iobase + TRIGGER_REG);
 525
 526        /*  start acquisition for soft trigger */
 527        if (cmd->start_src == TRIG_NOW)
 528                outw(0, dev->iobase + FIFO_START_REG);
 529#ifdef A2150_DEBUG
 530        ni_dump_regs(dev);
 531#endif
 532
 533        return 0;
 534}
 535
 536static int a2150_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
 537                          struct comedi_insn *insn, unsigned int *data)
 538{
 539        unsigned int i, n;
 540        static const int timeout = 100000;
 541        static const int filter_delay = 36;
 542
 543        /*  clear fifo and reset triggering circuitry */
 544        outw(0, dev->iobase + FIFO_RESET_REG);
 545
 546        /* setup chanlist */
 547        if (a2150_set_chanlist(dev, CR_CHAN(insn->chanspec), 1) < 0)
 548                return -1;
 549
 550        /*  set dc coupling */
 551        devpriv->config_bits &= ~AC0_BIT;
 552        devpriv->config_bits &= ~AC1_BIT;
 553
 554        /*  send timing, channel, config bits */
 555        outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
 556
 557        /*  disable dma on card */
 558        devpriv->irq_dma_bits &= ~DMA_INTR_EN_BIT & ~DMA_EN_BIT;
 559        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 560
 561        /*  setup start triggering */
 562        outw(0, dev->iobase + TRIGGER_REG);
 563
 564        /*  start acquisition for soft trigger */
 565        outw(0, dev->iobase + FIFO_START_REG);
 566
 567        /*
 568         * there is a 35.6 sample delay for data to get through the
 569         * antialias filter
 570         */
 571        for (n = 0; n < filter_delay; n++) {
 572                for (i = 0; i < timeout; i++) {
 573                        if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
 574                                break;
 575                        udelay(1);
 576                }
 577                if (i == timeout) {
 578                        comedi_error(dev, "timeout");
 579                        return -ETIME;
 580                }
 581                inw(dev->iobase + FIFO_DATA_REG);
 582        }
 583
 584        /*  read data */
 585        for (n = 0; n < insn->n; n++) {
 586                for (i = 0; i < timeout; i++) {
 587                        if (inw(dev->iobase + STATUS_REG) & FNE_BIT)
 588                                break;
 589                        udelay(1);
 590                }
 591                if (i == timeout) {
 592                        comedi_error(dev, "timeout");
 593                        return -ETIME;
 594                }
 595#ifdef A2150_DEBUG
 596                ni_dump_regs(dev);
 597#endif
 598                data[n] = inw(dev->iobase + FIFO_DATA_REG);
 599#ifdef A2150_DEBUG
 600                printk(" data is %i\n", data[n]);
 601#endif
 602                data[n] ^= 0x8000;
 603        }
 604
 605        /*  clear fifo and reset triggering circuitry */
 606        outw(0, dev->iobase + FIFO_RESET_REG);
 607
 608        return n;
 609}
 610
 611/*
 612 * sets bits in devpriv->clock_bits to nearest approximation of requested
 613 * period, adjusts requested period to actual timing.
 614 */
 615static int a2150_get_timing(struct comedi_device *dev, unsigned int *period,
 616                            int flags)
 617{
 618        int lub, glb, temp;
 619        int lub_divisor_shift, lub_index, glb_divisor_shift, glb_index;
 620        int i, j;
 621
 622        /*  initialize greatest lower and least upper bounds */
 623        lub_divisor_shift = 3;
 624        lub_index = 0;
 625        lub = thisboard->clock[lub_index] * (1 << lub_divisor_shift);
 626        glb_divisor_shift = 0;
 627        glb_index = thisboard->num_clocks - 1;
 628        glb = thisboard->clock[glb_index] * (1 << glb_divisor_shift);
 629
 630        /*  make sure period is in available range */
 631        if (*period < glb)
 632                *period = glb;
 633        if (*period > lub)
 634                *period = lub;
 635
 636        /*  we can multiply period by 1, 2, 4, or 8, using (1 << i) */
 637        for (i = 0; i < 4; i++) {
 638                /*  there are a maximum of 4 master clocks */
 639                for (j = 0; j < thisboard->num_clocks; j++) {
 640                        /*  temp is the period in nanosec we are evaluating */
 641                        temp = thisboard->clock[j] * (1 << i);
 642                        /*  if it is the best match yet */
 643                        if (temp < lub && temp >= *period) {
 644                                lub_divisor_shift = i;
 645                                lub_index = j;
 646                                lub = temp;
 647                        }
 648                        if (temp > glb && temp <= *period) {
 649                                glb_divisor_shift = i;
 650                                glb_index = j;
 651                                glb = temp;
 652                        }
 653                }
 654        }
 655        flags &= TRIG_ROUND_MASK;
 656        switch (flags) {
 657        case TRIG_ROUND_NEAREST:
 658        default:
 659                /*  if least upper bound is better approximation */
 660                if (lub - *period < *period - glb)
 661                        *period = lub;
 662                else
 663                        *period = glb;
 664                break;
 665        case TRIG_ROUND_UP:
 666                *period = lub;
 667                break;
 668        case TRIG_ROUND_DOWN:
 669                *period = glb;
 670                break;
 671        }
 672
 673        /*  set clock bits for config register appropriately */
 674        devpriv->config_bits &= ~CLOCK_MASK;
 675        if (*period == lub) {
 676                devpriv->config_bits |=
 677                    CLOCK_SELECT_BITS(lub_index) |
 678                    CLOCK_DIVISOR_BITS(lub_divisor_shift);
 679        } else {
 680                devpriv->config_bits |=
 681                    CLOCK_SELECT_BITS(glb_index) |
 682                    CLOCK_DIVISOR_BITS(glb_divisor_shift);
 683        }
 684
 685        return 0;
 686}
 687
 688static int a2150_set_chanlist(struct comedi_device *dev,
 689                              unsigned int start_channel,
 690                              unsigned int num_channels)
 691{
 692        if (start_channel + num_channels > 4)
 693                return -1;
 694
 695        devpriv->config_bits &= ~CHANNEL_MASK;
 696
 697        switch (num_channels) {
 698        case 1:
 699                devpriv->config_bits |= CHANNEL_BITS(0x4 | start_channel);
 700                break;
 701        case 2:
 702                if (start_channel == 0) {
 703                        devpriv->config_bits |= CHANNEL_BITS(0x2);
 704                } else if (start_channel == 2) {
 705                        devpriv->config_bits |= CHANNEL_BITS(0x3);
 706                } else {
 707                        return -1;
 708                }
 709                break;
 710        case 4:
 711                devpriv->config_bits |= CHANNEL_BITS(0x1);
 712                break;
 713        default:
 714                return -1;
 715                break;
 716        }
 717
 718        return 0;
 719}
 720
 721/* probes board type, returns offset */
 722static int a2150_probe(struct comedi_device *dev)
 723{
 724        int status = inw(dev->iobase + STATUS_REG);
 725        return ID_BITS(status);
 726}
 727
 728static int a2150_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 729{
 730        struct comedi_subdevice *s;
 731        unsigned long iobase = it->options[0];
 732        unsigned int irq = it->options[1];
 733        unsigned int dma = it->options[2];
 734        static const int timeout = 2000;
 735        int i;
 736        int ret;
 737
 738        printk("comedi%d: %s: io 0x%lx", dev->minor, dev->driver->driver_name,
 739               iobase);
 740        if (irq) {
 741                printk(", irq %u", irq);
 742        } else {
 743                printk(", no irq");
 744        }
 745        if (dma) {
 746                printk(", dma %u", dma);
 747        } else {
 748                printk(", no dma");
 749        }
 750        printk("\n");
 751
 752        /* allocate and initialize dev->private */
 753        if (alloc_private(dev, sizeof(struct a2150_private)) < 0)
 754                return -ENOMEM;
 755
 756        if (iobase == 0) {
 757                printk(" io base address required\n");
 758                return -EINVAL;
 759        }
 760
 761        /* check if io addresses are available */
 762        if (!request_region(iobase, A2150_SIZE, dev->driver->driver_name)) {
 763                printk(" I/O port conflict\n");
 764                return -EIO;
 765        }
 766        dev->iobase = iobase;
 767
 768        /* grab our IRQ */
 769        if (irq) {
 770                /*  check that irq is supported */
 771                if (irq < 3 || irq == 8 || irq == 13 || irq > 15) {
 772                        printk(" invalid irq line %u\n", irq);
 773                        return -EINVAL;
 774                }
 775                if (request_irq(irq, a2150_interrupt, 0,
 776                                dev->driver->driver_name, dev)) {
 777                        printk("unable to allocate irq %u\n", irq);
 778                        return -EINVAL;
 779                }
 780                devpriv->irq_dma_bits |= IRQ_LVL_BITS(irq);
 781                dev->irq = irq;
 782        }
 783        /*  initialize dma */
 784        if (dma) {
 785                if (dma == 4 || dma > 7) {
 786                        printk(" invalid dma channel %u\n", dma);
 787                        return -EINVAL;
 788                }
 789                if (request_dma(dma, dev->driver->driver_name)) {
 790                        printk(" failed to allocate dma channel %u\n", dma);
 791                        return -EINVAL;
 792                }
 793                devpriv->dma = dma;
 794                devpriv->dma_buffer =
 795                    kmalloc(A2150_DMA_BUFFER_SIZE, GFP_KERNEL | GFP_DMA);
 796                if (devpriv->dma_buffer == NULL)
 797                        return -ENOMEM;
 798
 799                disable_dma(dma);
 800                set_dma_mode(dma, DMA_MODE_READ);
 801
 802                devpriv->irq_dma_bits |= DMA_CHAN_BITS(dma);
 803        }
 804
 805        dev->board_ptr = a2150_boards + a2150_probe(dev);
 806        dev->board_name = thisboard->name;
 807
 808        ret = comedi_alloc_subdevices(dev, 1);
 809        if (ret)
 810                return ret;
 811
 812        /* analog input subdevice */
 813        s = &dev->subdevices[0];
 814        dev->read_subdev = s;
 815        s->type = COMEDI_SUBD_AI;
 816        s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_OTHER | SDF_CMD_READ;
 817        s->n_chan = 4;
 818        s->len_chanlist = 4;
 819        s->maxdata = 0xffff;
 820        s->range_table = &range_a2150;
 821        s->do_cmd = a2150_ai_cmd;
 822        s->do_cmdtest = a2150_ai_cmdtest;
 823        s->insn_read = a2150_ai_rinsn;
 824        s->cancel = a2150_cancel;
 825
 826        /* need to do this for software counting of completed conversions, to
 827         * prevent hardware count from stopping acquisition */
 828        outw(HW_COUNT_DISABLE, dev->iobase + I8253_MODE_REG);
 829
 830        /*  set card's irq and dma levels */
 831        outw(devpriv->irq_dma_bits, dev->iobase + IRQ_DMA_CNTRL_REG);
 832
 833        /*  reset and sync adc clock circuitry */
 834        outw_p(DPD_BIT | APD_BIT, dev->iobase + CONFIG_REG);
 835        outw_p(DPD_BIT, dev->iobase + CONFIG_REG);
 836        /*  initialize configuration register */
 837        devpriv->config_bits = 0;
 838        outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
 839        /*  wait until offset calibration is done, then enable analog inputs */
 840        for (i = 0; i < timeout; i++) {
 841                if ((DCAL_BIT & inw(dev->iobase + STATUS_REG)) == 0)
 842                        break;
 843                udelay(1000);
 844        }
 845        if (i == timeout) {
 846                printk
 847                    (" timed out waiting for offset calibration to complete\n");
 848                return -ETIME;
 849        }
 850        devpriv->config_bits |= ENABLE0_BIT | ENABLE1_BIT;
 851        outw(devpriv->config_bits, dev->iobase + CONFIG_REG);
 852
 853        return 0;
 854};
 855
 856static void a2150_detach(struct comedi_device *dev)
 857{
 858        if (dev->iobase) {
 859                outw(APD_BIT | DPD_BIT, dev->iobase + CONFIG_REG);
 860                release_region(dev->iobase, A2150_SIZE);
 861        }
 862        if (dev->irq)
 863                free_irq(dev->irq, dev);
 864        if (devpriv) {
 865                if (devpriv->dma)
 866                        free_dma(devpriv->dma);
 867                kfree(devpriv->dma_buffer);
 868        }
 869};
 870
 871static struct comedi_driver ni_at_a2150_driver = {
 872        .driver_name    = "ni_at_a2150",
 873        .module         = THIS_MODULE,
 874        .attach         = a2150_attach,
 875        .detach         = a2150_detach,
 876};
 877module_comedi_driver(ni_at_a2150_driver);
 878
 879MODULE_AUTHOR("Comedi http://www.comedi.org");
 880MODULE_DESCRIPTION("Comedi low-level driver");
 881MODULE_LICENSE("GPL");
 882