linux/drivers/staging/comedi/drivers/das1800.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/das1800.c
   3    Driver for Keitley das1700/das1800 series boards
   4    Copyright (C) 2000 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: das1800
  27Description: Keithley Metrabyte DAS1800 (& compatibles)
  28Author: Frank Mori Hess <fmhess@users.sourceforge.net>
  29Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
  30  DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
  31  DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
  32  DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
  33  DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
  34  DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
  35  DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
  36  DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
  37  DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
  38  DAS-1802AO (das-1802ao)
  39Status: works
  40
  41The waveform analog output on the 'ao' cards is not supported.
  42If you need it, send me (Frank Hess) an email.
  43
  44Configuration options:
  45  [0] - I/O port base address
  46  [1] - IRQ (optional, required for timed or externally triggered conversions)
  47  [2] - DMA0 (optional, requires irq)
  48  [3] - DMA1 (optional, requires irq and dma0)
  49*/
  50/*
  51
  52This driver supports the following Keithley boards:
  53
  54das-1701st
  55das-1701st-da
  56das-1701ao
  57das-1702st
  58das-1702st-da
  59das-1702hr
  60das-1702hr-da
  61das-1702ao
  62das-1801st
  63das-1801st-da
  64das-1801hc
  65das-1801ao
  66das-1802st
  67das-1802st-da
  68das-1802hr
  69das-1802hr-da
  70das-1802hc
  71das-1802ao
  72
  73Options:
  74        [0] - base io address
  75        [1] - irq (optional, required for timed or externally triggered conversions)
  76        [2] - dma0 (optional, requires irq)
  77        [3] - dma1 (optional, requires irq and dma0)
  78
  79irq can be omitted, although the cmd interface will not work without it.
  80
  81analog input cmd triggers supported:
  82        start_src:      TRIG_NOW | TRIG_EXT
  83        scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
  84        scan_end_src:   TRIG_COUNT
  85        convert_src:    TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
  86        stop_src:       TRIG_COUNT | TRIG_EXT | TRIG_NONE
  87
  88scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
  89'burst mode' which limits the valid conversion time to 64 microseconds
  90(convert_arg <= 64000).  This limitation does not apply if scan_begin_src
  91is TRIG_FOLLOW.
  92
  93NOTES:
  94Only the DAS-1801ST has been tested by me.
  95Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
  96
  97TODO:
  98        Make it automatically allocate irq and dma channels if they are not specified
  99        Add support for analog out on 'ao' cards
 100        read insn for analog out
 101*/
 102
 103#include <linux/interrupt.h>
 104#include <linux/slab.h>
 105#include "../comedidev.h"
 106
 107#include <linux/ioport.h>
 108#include <asm/dma.h>
 109
 110#include "8253.h"
 111#include "comedi_fc.h"
 112
 113/* misc. defines */
 114#define DAS1800_SIZE           16       /* uses 16 io addresses */
 115#define FIFO_SIZE              1024     /*  1024 sample fifo */
 116#define TIMER_BASE             200      /*  5 Mhz master clock */
 117#define UNIPOLAR               0x4      /*  bit that determines whether input range is uni/bipolar */
 118#define DMA_BUF_SIZE           0x1ff00  /*  size in bytes of dma buffers */
 119
 120/* Registers for the das1800 */
 121#define DAS1800_FIFO            0x0
 122#define DAS1800_QRAM            0x0
 123#define DAS1800_DAC             0x0
 124#define DAS1800_SELECT          0x2
 125#define   ADC                     0x0
 126#define   QRAM                    0x1
 127#define   DAC(a)                  (0x2 + a)
 128#define DAS1800_DIGITAL         0x3
 129#define DAS1800_CONTROL_A       0x4
 130#define   FFEN                    0x1
 131#define   CGEN                    0x4
 132#define   CGSL                    0x8
 133#define   TGEN                    0x10
 134#define   TGSL                    0x20
 135#define   ATEN                    0x80
 136#define DAS1800_CONTROL_B       0x5
 137#define   DMA_CH5                 0x1
 138#define   DMA_CH6                 0x2
 139#define   DMA_CH7                 0x3
 140#define   DMA_CH5_CH6             0x5
 141#define   DMA_CH6_CH7             0x6
 142#define   DMA_CH7_CH5             0x7
 143#define   DMA_ENABLED             0x3   /* mask used to determine if dma is enabled */
 144#define   DMA_DUAL                0x4
 145#define   IRQ3                    0x8
 146#define   IRQ5                    0x10
 147#define   IRQ7                    0x18
 148#define   IRQ10                   0x28
 149#define   IRQ11                   0x30
 150#define   IRQ15                   0x38
 151#define   FIMD                    0x40
 152#define DAS1800_CONTROL_C       0X6
 153#define   IPCLK                   0x1
 154#define   XPCLK                   0x3
 155#define   BMDE                    0x4
 156#define   CMEN                    0x8
 157#define   UQEN                    0x10
 158#define   SD                      0x40
 159#define   UB                      0x80
 160#define DAS1800_STATUS          0x7
 161/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
 162#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
 163#define   INT                     0x1
 164#define   DMATC                   0x2
 165#define   CT0TC                   0x8
 166#define   OVF                     0x10
 167#define   FHF                     0x20
 168#define   FNE                     0x40
 169#define   CVEN_MASK               0x40  /*  masks CVEN on write */
 170#define   CVEN                    0x80
 171#define DAS1800_BURST_LENGTH    0x8
 172#define DAS1800_BURST_RATE      0x9
 173#define DAS1800_QRAM_ADDRESS    0xa
 174#define DAS1800_COUNTER         0xc
 175
 176#define IOBASE2                   0x400 /* offset of additional ioports used on 'ao' cards */
 177
 178enum {
 179        das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
 180        das1702hr_da,
 181        das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
 182        das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
 183};
 184
 185static int das1800_attach(struct comedi_device *dev,
 186                          struct comedi_devconfig *it);
 187static int das1800_detach(struct comedi_device *dev);
 188static int das1800_probe(struct comedi_device *dev);
 189static int das1800_cancel(struct comedi_device *dev,
 190                          struct comedi_subdevice *s);
 191static irqreturn_t das1800_interrupt(int irq, void *d);
 192static int das1800_ai_poll(struct comedi_device *dev,
 193                           struct comedi_subdevice *s);
 194static void das1800_ai_handler(struct comedi_device *dev);
 195static void das1800_handle_dma(struct comedi_device *dev,
 196                               struct comedi_subdevice *s, unsigned int status);
 197static void das1800_flush_dma(struct comedi_device *dev,
 198                              struct comedi_subdevice *s);
 199static void das1800_flush_dma_channel(struct comedi_device *dev,
 200                                      struct comedi_subdevice *s,
 201                                      unsigned int channel, uint16_t * buffer);
 202static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 203                                          struct comedi_subdevice *s);
 204static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 205                                          struct comedi_subdevice *s);
 206static int das1800_ai_do_cmdtest(struct comedi_device *dev,
 207                                 struct comedi_subdevice *s,
 208                                 struct comedi_cmd *cmd);
 209static int das1800_ai_do_cmd(struct comedi_device *dev,
 210                             struct comedi_subdevice *s);
 211static int das1800_ai_rinsn(struct comedi_device *dev,
 212                            struct comedi_subdevice *s,
 213                            struct comedi_insn *insn, unsigned int *data);
 214static int das1800_ao_winsn(struct comedi_device *dev,
 215                            struct comedi_subdevice *s,
 216                            struct comedi_insn *insn, unsigned int *data);
 217static int das1800_di_rbits(struct comedi_device *dev,
 218                            struct comedi_subdevice *s,
 219                            struct comedi_insn *insn, unsigned int *data);
 220static int das1800_do_wbits(struct comedi_device *dev,
 221                            struct comedi_subdevice *s,
 222                            struct comedi_insn *insn, unsigned int *data);
 223
 224static int das1800_set_frequency(struct comedi_device *dev);
 225static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
 226static unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
 227
 228/* analog input ranges */
 229static const struct comedi_lrange range_ai_das1801 = {
 230        8,
 231        {
 232         RANGE(-5, 5),
 233         RANGE(-1, 1),
 234         RANGE(-0.1, 0.1),
 235         RANGE(-0.02, 0.02),
 236         RANGE(0, 5),
 237         RANGE(0, 1),
 238         RANGE(0, 0.1),
 239         RANGE(0, 0.02),
 240         }
 241};
 242
 243static const struct comedi_lrange range_ai_das1802 = {
 244        8,
 245        {
 246         RANGE(-10, 10),
 247         RANGE(-5, 5),
 248         RANGE(-2.5, 2.5),
 249         RANGE(-1.25, 1.25),
 250         RANGE(0, 10),
 251         RANGE(0, 5),
 252         RANGE(0, 2.5),
 253         RANGE(0, 1.25),
 254         }
 255};
 256
 257struct das1800_board {
 258        const char *name;
 259        int ai_speed;           /* max conversion period in nanoseconds */
 260        int resolution;         /* bits of ai resolution */
 261        int qram_len;           /* length of card's channel / gain queue */
 262        int common;             /* supports AREF_COMMON flag */
 263        int do_n_chan;          /* number of digital output channels */
 264        int ao_ability;         /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
 265        int ao_n_chan;          /* number of analog out channels */
 266        const struct comedi_lrange *range_ai;   /* available input ranges */
 267};
 268
 269/* Warning: the maximum conversion speeds listed below are
 270 * not always achievable depending on board setup (see
 271 * user manual.)
 272 */
 273static const struct das1800_board das1800_boards[] = {
 274        {
 275         .name = "das-1701st",
 276         .ai_speed = 6250,
 277         .resolution = 12,
 278         .qram_len = 256,
 279         .common = 1,
 280         .do_n_chan = 4,
 281         .ao_ability = 0,
 282         .ao_n_chan = 0,
 283         .range_ai = &range_ai_das1801,
 284         },
 285        {
 286         .name = "das-1701st-da",
 287         .ai_speed = 6250,
 288         .resolution = 12,
 289         .qram_len = 256,
 290         .common = 1,
 291         .do_n_chan = 4,
 292         .ao_ability = 1,
 293         .ao_n_chan = 4,
 294         .range_ai = &range_ai_das1801,
 295         },
 296        {
 297         .name = "das-1702st",
 298         .ai_speed = 6250,
 299         .resolution = 12,
 300         .qram_len = 256,
 301         .common = 1,
 302         .do_n_chan = 4,
 303         .ao_ability = 0,
 304         .ao_n_chan = 0,
 305         .range_ai = &range_ai_das1802,
 306         },
 307        {
 308         .name = "das-1702st-da",
 309         .ai_speed = 6250,
 310         .resolution = 12,
 311         .qram_len = 256,
 312         .common = 1,
 313         .do_n_chan = 4,
 314         .ao_ability = 1,
 315         .ao_n_chan = 4,
 316         .range_ai = &range_ai_das1802,
 317         },
 318        {
 319         .name = "das-1702hr",
 320         .ai_speed = 20000,
 321         .resolution = 16,
 322         .qram_len = 256,
 323         .common = 1,
 324         .do_n_chan = 4,
 325         .ao_ability = 0,
 326         .ao_n_chan = 0,
 327         .range_ai = &range_ai_das1802,
 328         },
 329        {
 330         .name = "das-1702hr-da",
 331         .ai_speed = 20000,
 332         .resolution = 16,
 333         .qram_len = 256,
 334         .common = 1,
 335         .do_n_chan = 4,
 336         .ao_ability = 1,
 337         .ao_n_chan = 2,
 338         .range_ai = &range_ai_das1802,
 339         },
 340        {
 341         .name = "das-1701ao",
 342         .ai_speed = 6250,
 343         .resolution = 12,
 344         .qram_len = 256,
 345         .common = 1,
 346         .do_n_chan = 4,
 347         .ao_ability = 2,
 348         .ao_n_chan = 2,
 349         .range_ai = &range_ai_das1801,
 350         },
 351        {
 352         .name = "das-1702ao",
 353         .ai_speed = 6250,
 354         .resolution = 12,
 355         .qram_len = 256,
 356         .common = 1,
 357         .do_n_chan = 4,
 358         .ao_ability = 2,
 359         .ao_n_chan = 2,
 360         .range_ai = &range_ai_das1802,
 361         },
 362        {
 363         .name = "das-1801st",
 364         .ai_speed = 3000,
 365         .resolution = 12,
 366         .qram_len = 256,
 367         .common = 1,
 368         .do_n_chan = 4,
 369         .ao_ability = 0,
 370         .ao_n_chan = 0,
 371         .range_ai = &range_ai_das1801,
 372         },
 373        {
 374         .name = "das-1801st-da",
 375         .ai_speed = 3000,
 376         .resolution = 12,
 377         .qram_len = 256,
 378         .common = 1,
 379         .do_n_chan = 4,
 380         .ao_ability = 0,
 381         .ao_n_chan = 4,
 382         .range_ai = &range_ai_das1801,
 383         },
 384        {
 385         .name = "das-1802st",
 386         .ai_speed = 3000,
 387         .resolution = 12,
 388         .qram_len = 256,
 389         .common = 1,
 390         .do_n_chan = 4,
 391         .ao_ability = 0,
 392         .ao_n_chan = 0,
 393         .range_ai = &range_ai_das1802,
 394         },
 395        {
 396         .name = "das-1802st-da",
 397         .ai_speed = 3000,
 398         .resolution = 12,
 399         .qram_len = 256,
 400         .common = 1,
 401         .do_n_chan = 4,
 402         .ao_ability = 1,
 403         .ao_n_chan = 4,
 404         .range_ai = &range_ai_das1802,
 405         },
 406        {
 407         .name = "das-1802hr",
 408         .ai_speed = 10000,
 409         .resolution = 16,
 410         .qram_len = 256,
 411         .common = 1,
 412         .do_n_chan = 4,
 413         .ao_ability = 0,
 414         .ao_n_chan = 0,
 415         .range_ai = &range_ai_das1802,
 416         },
 417        {
 418         .name = "das-1802hr-da",
 419         .ai_speed = 10000,
 420         .resolution = 16,
 421         .qram_len = 256,
 422         .common = 1,
 423         .do_n_chan = 4,
 424         .ao_ability = 1,
 425         .ao_n_chan = 2,
 426         .range_ai = &range_ai_das1802,
 427         },
 428        {
 429         .name = "das-1801hc",
 430         .ai_speed = 3000,
 431         .resolution = 12,
 432         .qram_len = 64,
 433         .common = 0,
 434         .do_n_chan = 8,
 435         .ao_ability = 1,
 436         .ao_n_chan = 2,
 437         .range_ai = &range_ai_das1801,
 438         },
 439        {
 440         .name = "das-1802hc",
 441         .ai_speed = 3000,
 442         .resolution = 12,
 443         .qram_len = 64,
 444         .common = 0,
 445         .do_n_chan = 8,
 446         .ao_ability = 1,
 447         .ao_n_chan = 2,
 448         .range_ai = &range_ai_das1802,
 449         },
 450        {
 451         .name = "das-1801ao",
 452         .ai_speed = 3000,
 453         .resolution = 12,
 454         .qram_len = 256,
 455         .common = 1,
 456         .do_n_chan = 4,
 457         .ao_ability = 2,
 458         .ao_n_chan = 2,
 459         .range_ai = &range_ai_das1801,
 460         },
 461        {
 462         .name = "das-1802ao",
 463         .ai_speed = 3000,
 464         .resolution = 12,
 465         .qram_len = 256,
 466         .common = 1,
 467         .do_n_chan = 4,
 468         .ao_ability = 2,
 469         .ao_n_chan = 2,
 470         .range_ai = &range_ai_das1802,
 471         },
 472};
 473
 474/*
 475 * Useful for shorthand access to the particular board structure
 476 */
 477#define thisboard ((const struct das1800_board *)dev->board_ptr)
 478
 479struct das1800_private {
 480        volatile unsigned int count;    /* number of data points left to be taken */
 481        unsigned int divisor1;  /* value to load into board's counter 1 for timed conversions */
 482        unsigned int divisor2;  /* value to load into board's counter 2 for timed conversions */
 483        int do_bits;            /* digital output bits */
 484        int irq_dma_bits;       /* bits for control register b */
 485        /* dma bits for control register b, stored so that dma can be
 486         * turned on and off */
 487        int dma_bits;
 488        unsigned int dma0;      /* dma channels used */
 489        unsigned int dma1;
 490        volatile unsigned int dma_current;      /* dma channel currently in use */
 491        uint16_t *ai_buf0;      /* pointers to dma buffers */
 492        uint16_t *ai_buf1;
 493        uint16_t *dma_current_buf;      /* pointer to dma buffer currently being used */
 494        unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */
 495        unsigned long iobase2;  /* secondary io address used for analog out on 'ao' boards */
 496        short ao_update_bits;   /* remembers the last write to the 'update' dac */
 497};
 498
 499#define devpriv ((struct das1800_private *)dev->private)
 500
 501/* analog out range for boards with basic analog out */
 502static const struct comedi_lrange range_ao_1 = {
 503        1,
 504        {
 505         RANGE(-10, 10),
 506         }
 507};
 508
 509/* analog out range for 'ao' boards */
 510/*
 511static const struct comedi_lrange range_ao_2 = {
 512        2,
 513        {
 514                RANGE(-10, 10),
 515                RANGE(-5, 5),
 516        }
 517};
 518*/
 519
 520static struct comedi_driver driver_das1800 = {
 521        .driver_name = "das1800",
 522        .module = THIS_MODULE,
 523        .attach = das1800_attach,
 524        .detach = das1800_detach,
 525        .num_names = ARRAY_SIZE(das1800_boards),
 526        .board_name = &das1800_boards[0].name,
 527        .offset = sizeof(struct das1800_board),
 528};
 529
 530/*
 531 * A convenient macro that defines init_module() and cleanup_module(),
 532 * as necessary.
 533 */
 534static int __init driver_das1800_init_module(void)
 535{
 536        return comedi_driver_register(&driver_das1800);
 537}
 538
 539static void __exit driver_das1800_cleanup_module(void)
 540{
 541        comedi_driver_unregister(&driver_das1800);
 542}
 543
 544module_init(driver_das1800_init_module);
 545module_exit(driver_das1800_cleanup_module);
 546
 547static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
 548                            unsigned int dma1)
 549{
 550        unsigned long flags;
 551
 552        /*  need an irq to do dma */
 553        if (dev->irq && dma0) {
 554                /* encode dma0 and dma1 into 2 digit hexadecimal for switch */
 555                switch ((dma0 & 0x7) | (dma1 << 4)) {
 556                case 0x5:       /*  dma0 == 5 */
 557                        devpriv->dma_bits |= DMA_CH5;
 558                        break;
 559                case 0x6:       /*  dma0 == 6 */
 560                        devpriv->dma_bits |= DMA_CH6;
 561                        break;
 562                case 0x7:       /*  dma0 == 7 */
 563                        devpriv->dma_bits |= DMA_CH7;
 564                        break;
 565                case 0x65:      /*  dma0 == 5, dma1 == 6 */
 566                        devpriv->dma_bits |= DMA_CH5_CH6;
 567                        break;
 568                case 0x76:      /*  dma0 == 6, dma1 == 7 */
 569                        devpriv->dma_bits |= DMA_CH6_CH7;
 570                        break;
 571                case 0x57:      /*  dma0 == 7, dma1 == 5 */
 572                        devpriv->dma_bits |= DMA_CH7_CH5;
 573                        break;
 574                default:
 575                        printk(" only supports dma channels 5 through 7\n"
 576                               " Dual dma only allows the following combinations:\n"
 577                               " dma 5,6 / 6,7 / or 7,5\n");
 578                        return -EINVAL;
 579                        break;
 580                }
 581                if (request_dma(dma0, driver_das1800.driver_name)) {
 582                        printk(" failed to allocate dma channel %i\n", dma0);
 583                        return -EINVAL;
 584                }
 585                devpriv->dma0 = dma0;
 586                devpriv->dma_current = dma0;
 587                if (dma1) {
 588                        if (request_dma(dma1, driver_das1800.driver_name)) {
 589                                printk(" failed to allocate dma channel %i\n",
 590                                       dma1);
 591                                return -EINVAL;
 592                        }
 593                        devpriv->dma1 = dma1;
 594                }
 595                devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
 596                if (devpriv->ai_buf0 == NULL)
 597                        return -ENOMEM;
 598                devpriv->dma_current_buf = devpriv->ai_buf0;
 599                if (dma1) {
 600                        devpriv->ai_buf1 =
 601                            kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
 602                        if (devpriv->ai_buf1 == NULL)
 603                                return -ENOMEM;
 604                }
 605                flags = claim_dma_lock();
 606                disable_dma(devpriv->dma0);
 607                set_dma_mode(devpriv->dma0, DMA_MODE_READ);
 608                if (dma1) {
 609                        disable_dma(devpriv->dma1);
 610                        set_dma_mode(devpriv->dma1, DMA_MODE_READ);
 611                }
 612                release_dma_lock(flags);
 613        }
 614        return 0;
 615}
 616
 617static int das1800_attach(struct comedi_device *dev,
 618                          struct comedi_devconfig *it)
 619{
 620        struct comedi_subdevice *s;
 621        unsigned long iobase = it->options[0];
 622        unsigned int irq = it->options[1];
 623        unsigned int dma0 = it->options[2];
 624        unsigned int dma1 = it->options[3];
 625        unsigned long iobase2;
 626        int board;
 627        int retval;
 628
 629        /* allocate and initialize dev->private */
 630        if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
 631                return -ENOMEM;
 632
 633        printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
 634               iobase);
 635        if (irq) {
 636                printk(", irq %u", irq);
 637                if (dma0) {
 638                        printk(", dma %u", dma0);
 639                        if (dma1)
 640                                printk(" and %u", dma1);
 641                }
 642        }
 643        printk("\n");
 644
 645        if (iobase == 0) {
 646                printk(" io base address required\n");
 647                return -EINVAL;
 648        }
 649
 650        /* check if io addresses are available */
 651        if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
 652                printk
 653                    (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
 654                     iobase, iobase + DAS1800_SIZE - 1);
 655                return -EIO;
 656        }
 657        dev->iobase = iobase;
 658
 659        board = das1800_probe(dev);
 660        if (board < 0) {
 661                printk(" unable to determine board type\n");
 662                return -ENODEV;
 663        }
 664
 665        dev->board_ptr = das1800_boards + board;
 666        dev->board_name = thisboard->name;
 667
 668        /*  if it is an 'ao' board with fancy analog out then we need extra io ports */
 669        if (thisboard->ao_ability == 2) {
 670                iobase2 = iobase + IOBASE2;
 671                if (!request_region(iobase2, DAS1800_SIZE,
 672                                    driver_das1800.driver_name)) {
 673                        printk
 674                            (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
 675                             iobase2, iobase2 + DAS1800_SIZE - 1);
 676                        return -EIO;
 677                }
 678                devpriv->iobase2 = iobase2;
 679        }
 680
 681        /* grab our IRQ */
 682        if (irq) {
 683                if (request_irq(irq, das1800_interrupt, 0,
 684                                driver_das1800.driver_name, dev)) {
 685                        printk(" unable to allocate irq %u\n", irq);
 686                        return -EINVAL;
 687                }
 688        }
 689        dev->irq = irq;
 690
 691        /*  set bits that tell card which irq to use */
 692        switch (irq) {
 693        case 0:
 694                break;
 695        case 3:
 696                devpriv->irq_dma_bits |= 0x8;
 697                break;
 698        case 5:
 699                devpriv->irq_dma_bits |= 0x10;
 700                break;
 701        case 7:
 702                devpriv->irq_dma_bits |= 0x18;
 703                break;
 704        case 10:
 705                devpriv->irq_dma_bits |= 0x28;
 706                break;
 707        case 11:
 708                devpriv->irq_dma_bits |= 0x30;
 709                break;
 710        case 15:
 711                devpriv->irq_dma_bits |= 0x38;
 712                break;
 713        default:
 714                printk(" irq out of range\n");
 715                return -EINVAL;
 716                break;
 717        }
 718
 719        retval = das1800_init_dma(dev, dma0, dma1);
 720        if (retval < 0)
 721                return retval;
 722
 723        if (devpriv->ai_buf0 == NULL) {
 724                devpriv->ai_buf0 =
 725                    kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
 726                if (devpriv->ai_buf0 == NULL)
 727                        return -ENOMEM;
 728        }
 729
 730        if (alloc_subdevices(dev, 4) < 0)
 731                return -ENOMEM;
 732
 733        /* analog input subdevice */
 734        s = dev->subdevices + 0;
 735        dev->read_subdev = s;
 736        s->type = COMEDI_SUBD_AI;
 737        s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
 738        if (thisboard->common)
 739                s->subdev_flags |= SDF_COMMON;
 740        s->n_chan = thisboard->qram_len;
 741        s->len_chanlist = thisboard->qram_len;
 742        s->maxdata = (1 << thisboard->resolution) - 1;
 743        s->range_table = thisboard->range_ai;
 744        s->do_cmd = das1800_ai_do_cmd;
 745        s->do_cmdtest = das1800_ai_do_cmdtest;
 746        s->insn_read = das1800_ai_rinsn;
 747        s->poll = das1800_ai_poll;
 748        s->cancel = das1800_cancel;
 749
 750        /* analog out */
 751        s = dev->subdevices + 1;
 752        if (thisboard->ao_ability == 1) {
 753                s->type = COMEDI_SUBD_AO;
 754                s->subdev_flags = SDF_WRITABLE;
 755                s->n_chan = thisboard->ao_n_chan;
 756                s->maxdata = (1 << thisboard->resolution) - 1;
 757                s->range_table = &range_ao_1;
 758                s->insn_write = das1800_ao_winsn;
 759        } else {
 760                s->type = COMEDI_SUBD_UNUSED;
 761        }
 762
 763        /* di */
 764        s = dev->subdevices + 2;
 765        s->type = COMEDI_SUBD_DI;
 766        s->subdev_flags = SDF_READABLE;
 767        s->n_chan = 4;
 768        s->maxdata = 1;
 769        s->range_table = &range_digital;
 770        s->insn_bits = das1800_di_rbits;
 771
 772        /* do */
 773        s = dev->subdevices + 3;
 774        s->type = COMEDI_SUBD_DO;
 775        s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
 776        s->n_chan = thisboard->do_n_chan;
 777        s->maxdata = 1;
 778        s->range_table = &range_digital;
 779        s->insn_bits = das1800_do_wbits;
 780
 781        das1800_cancel(dev, dev->read_subdev);
 782
 783        /*  initialize digital out channels */
 784        outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
 785
 786        /*  initialize analog out channels */
 787        if (thisboard->ao_ability == 1) {
 788                /*  select 'update' dac channel for baseAddress + 0x0 */
 789                outb(DAC(thisboard->ao_n_chan - 1),
 790                     dev->iobase + DAS1800_SELECT);
 791                outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
 792        }
 793
 794        return 0;
 795};
 796
 797static int das1800_detach(struct comedi_device *dev)
 798{
 799        /* only free stuff if it has been allocated by _attach */
 800        if (dev->iobase)
 801                release_region(dev->iobase, DAS1800_SIZE);
 802        if (dev->irq)
 803                free_irq(dev->irq, dev);
 804        if (dev->private) {
 805                if (devpriv->iobase2)
 806                        release_region(devpriv->iobase2, DAS1800_SIZE);
 807                if (devpriv->dma0)
 808                        free_dma(devpriv->dma0);
 809                if (devpriv->dma1)
 810                        free_dma(devpriv->dma1);
 811                kfree(devpriv->ai_buf0);
 812                kfree(devpriv->ai_buf1);
 813        }
 814
 815        printk("comedi%d: %s: remove\n", dev->minor,
 816               driver_das1800.driver_name);
 817
 818        return 0;
 819};
 820
 821/* probes and checks das-1800 series board type
 822 */
 823static int das1800_probe(struct comedi_device *dev)
 824{
 825        int id;
 826        int board;
 827
 828        id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;   /* get id bits */
 829        board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
 830
 831        switch (id) {
 832        case 0x3:
 833                if (board == das1801st_da || board == das1802st_da ||
 834                    board == das1701st_da || board == das1702st_da) {
 835                        printk(" Board model: %s\n",
 836                               das1800_boards[board].name);
 837                        return board;
 838                }
 839                printk
 840                    (" Board model (probed, not recommended): das-1800st-da series\n");
 841                return das1801st;
 842                break;
 843        case 0x4:
 844                if (board == das1802hr_da || board == das1702hr_da) {
 845                        printk(" Board model: %s\n",
 846                               das1800_boards[board].name);
 847                        return board;
 848                }
 849                printk
 850                    (" Board model (probed, not recommended): das-1802hr-da\n");
 851                return das1802hr;
 852                break;
 853        case 0x5:
 854                if (board == das1801ao || board == das1802ao ||
 855                    board == das1701ao || board == das1702ao) {
 856                        printk(" Board model: %s\n",
 857                               das1800_boards[board].name);
 858                        return board;
 859                }
 860                printk
 861                    (" Board model (probed, not recommended): das-1800ao series\n");
 862                return das1801ao;
 863                break;
 864        case 0x6:
 865                if (board == das1802hr || board == das1702hr) {
 866                        printk(" Board model: %s\n",
 867                               das1800_boards[board].name);
 868                        return board;
 869                }
 870                printk(" Board model (probed, not recommended): das-1802hr\n");
 871                return das1802hr;
 872                break;
 873        case 0x7:
 874                if (board == das1801st || board == das1802st ||
 875                    board == das1701st || board == das1702st) {
 876                        printk(" Board model: %s\n",
 877                               das1800_boards[board].name);
 878                        return board;
 879                }
 880                printk
 881                    (" Board model (probed, not recommended): das-1800st series\n");
 882                return das1801st;
 883                break;
 884        case 0x8:
 885                if (board == das1801hc || board == das1802hc) {
 886                        printk(" Board model: %s\n",
 887                               das1800_boards[board].name);
 888                        return board;
 889                }
 890                printk
 891                    (" Board model (probed, not recommended): das-1800hc series\n");
 892                return das1801hc;
 893                break;
 894        default:
 895                printk
 896                    (" Board model: probe returned 0x%x (unknown, please report)\n",
 897                     id);
 898                return board;
 899                break;
 900        }
 901        return -1;
 902}
 903
 904static int das1800_ai_poll(struct comedi_device *dev,
 905                           struct comedi_subdevice *s)
 906{
 907        unsigned long flags;
 908
 909        /*  prevent race with interrupt handler */
 910        spin_lock_irqsave(&dev->spinlock, flags);
 911        das1800_ai_handler(dev);
 912        spin_unlock_irqrestore(&dev->spinlock, flags);
 913
 914        return s->async->buf_write_count - s->async->buf_read_count;
 915}
 916
 917static irqreturn_t das1800_interrupt(int irq, void *d)
 918{
 919        struct comedi_device *dev = d;
 920        unsigned int status;
 921
 922        if (dev->attached == 0) {
 923                comedi_error(dev, "premature interrupt");
 924                return IRQ_HANDLED;
 925        }
 926
 927        /* Prevent race with das1800_ai_poll() on multi processor systems.
 928         * Also protects indirect addressing in das1800_ai_handler */
 929        spin_lock(&dev->spinlock);
 930        status = inb(dev->iobase + DAS1800_STATUS);
 931
 932        /* if interrupt was not caused by das-1800 */
 933        if (!(status & INT)) {
 934                spin_unlock(&dev->spinlock);
 935                return IRQ_NONE;
 936        }
 937        /* clear the interrupt status bit INT */
 938        outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
 939        /*  handle interrupt */
 940        das1800_ai_handler(dev);
 941
 942        spin_unlock(&dev->spinlock);
 943        return IRQ_HANDLED;
 944}
 945
 946/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
 947static void das1800_ai_handler(struct comedi_device *dev)
 948{
 949        struct comedi_subdevice *s = dev->subdevices + 0;       /* analog input subdevice */
 950        struct comedi_async *async = s->async;
 951        struct comedi_cmd *cmd = &async->cmd;
 952        unsigned int status = inb(dev->iobase + DAS1800_STATUS);
 953
 954        async->events = 0;
 955        /*  select adc for base address + 0 */
 956        outb(ADC, dev->iobase + DAS1800_SELECT);
 957        /*  dma buffer full */
 958        if (devpriv->irq_dma_bits & DMA_ENABLED) {
 959                /*  look for data from dma transfer even if dma terminal count hasn't happened yet */
 960                das1800_handle_dma(dev, s, status);
 961        } else if (status & FHF) {      /*  if fifo half full */
 962                das1800_handle_fifo_half_full(dev, s);
 963        } else if (status & FNE) {      /*  if fifo not empty */
 964                das1800_handle_fifo_not_empty(dev, s);
 965        }
 966
 967        async->events |= COMEDI_CB_BLOCK;
 968        /* if the card's fifo has overflowed */
 969        if (status & OVF) {
 970                /*  clear OVF interrupt bit */
 971                outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
 972                comedi_error(dev, "DAS1800 FIFO overflow");
 973                das1800_cancel(dev, s);
 974                async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
 975                comedi_event(dev, s);
 976                return;
 977        }
 978        /*  stop taking data if appropriate */
 979        /* stop_src TRIG_EXT */
 980        if (status & CT0TC) {
 981                /*  clear CT0TC interrupt bit */
 982                outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
 983                /*  make sure we get all remaining data from board before quitting */
 984                if (devpriv->irq_dma_bits & DMA_ENABLED)
 985                        das1800_flush_dma(dev, s);
 986                else
 987                        das1800_handle_fifo_not_empty(dev, s);
 988                das1800_cancel(dev, s); /* disable hardware conversions */
 989                async->events |= COMEDI_CB_EOA;
 990        } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {        /*  stop_src TRIG_COUNT */
 991                das1800_cancel(dev, s); /* disable hardware conversions */
 992                async->events |= COMEDI_CB_EOA;
 993        }
 994
 995        comedi_event(dev, s);
 996
 997        return;
 998}
 999
1000static void das1800_handle_dma(struct comedi_device *dev,
1001                               struct comedi_subdevice *s, unsigned int status)
1002{
1003        unsigned long flags;
1004        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1005
1006        flags = claim_dma_lock();
1007        das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1008                                  devpriv->dma_current_buf);
1009        /*  re-enable  dma channel */
1010        set_dma_addr(devpriv->dma_current,
1011                     virt_to_bus(devpriv->dma_current_buf));
1012        set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
1013        enable_dma(devpriv->dma_current);
1014        release_dma_lock(flags);
1015
1016        if (status & DMATC) {
1017                /*  clear DMATC interrupt bit */
1018                outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
1019                /*  switch dma channels for next time, if appropriate */
1020                if (dual_dma) {
1021                        /*  read data from the other channel next time */
1022                        if (devpriv->dma_current == devpriv->dma0) {
1023                                devpriv->dma_current = devpriv->dma1;
1024                                devpriv->dma_current_buf = devpriv->ai_buf1;
1025                        } else {
1026                                devpriv->dma_current = devpriv->dma0;
1027                                devpriv->dma_current_buf = devpriv->ai_buf0;
1028                        }
1029                }
1030        }
1031
1032        return;
1033}
1034
1035static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
1036                                            uint16_t sample)
1037{
1038        sample += 1 << (thisboard->resolution - 1);
1039        return sample;
1040}
1041
1042static void munge_data(struct comedi_device *dev, uint16_t * array,
1043                       unsigned int num_elements)
1044{
1045        unsigned int i;
1046        int unipolar;
1047
1048        /* see if card is using a unipolar or bipolar range so we can munge data correctly */
1049        unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1050
1051        /* convert to unsigned type if we are in a bipolar mode */
1052        if (!unipolar) {
1053                for (i = 0; i < num_elements; i++) {
1054                        array[i] = munge_bipolar_sample(dev, array[i]);
1055                }
1056        }
1057}
1058
1059/* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1060 * Assumes dma lock is held */
1061static void das1800_flush_dma_channel(struct comedi_device *dev,
1062                                      struct comedi_subdevice *s,
1063                                      unsigned int channel, uint16_t * buffer)
1064{
1065        unsigned int num_bytes, num_samples;
1066        struct comedi_cmd *cmd = &s->async->cmd;
1067
1068        disable_dma(channel);
1069
1070        /* clear flip-flop to make sure 2-byte registers
1071         * get set correctly */
1072        clear_dma_ff(channel);
1073
1074        /*  figure out how many points to read */
1075        num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1076        num_samples = num_bytes / sizeof(short);
1077
1078        /* if we only need some of the points */
1079        if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1080                num_samples = devpriv->count;
1081
1082        munge_data(dev, buffer, num_samples);
1083        cfc_write_array_to_buffer(s, buffer, num_bytes);
1084        if (s->async->cmd.stop_src == TRIG_COUNT)
1085                devpriv->count -= num_samples;
1086
1087        return;
1088}
1089
1090/* flushes remaining data from board when external trigger has stopped aquisition
1091 * and we are using dma transfers */
1092static void das1800_flush_dma(struct comedi_device *dev,
1093                              struct comedi_subdevice *s)
1094{
1095        unsigned long flags;
1096        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1097
1098        flags = claim_dma_lock();
1099        das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1100                                  devpriv->dma_current_buf);
1101
1102        if (dual_dma) {
1103                /*  switch to other channel and flush it */
1104                if (devpriv->dma_current == devpriv->dma0) {
1105                        devpriv->dma_current = devpriv->dma1;
1106                        devpriv->dma_current_buf = devpriv->ai_buf1;
1107                } else {
1108                        devpriv->dma_current = devpriv->dma0;
1109                        devpriv->dma_current_buf = devpriv->ai_buf0;
1110                }
1111                das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1112                                          devpriv->dma_current_buf);
1113        }
1114
1115        release_dma_lock(flags);
1116
1117        /*  get any remaining samples in fifo */
1118        das1800_handle_fifo_not_empty(dev, s);
1119
1120        return;
1121}
1122
1123static void das1800_handle_fifo_half_full(struct comedi_device *dev,
1124                                          struct comedi_subdevice *s)
1125{
1126        int numPoints = 0;      /* number of points to read */
1127        struct comedi_cmd *cmd = &s->async->cmd;
1128
1129        numPoints = FIFO_SIZE / 2;
1130        /* if we only need some of the points */
1131        if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1132                numPoints = devpriv->count;
1133        insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1134        munge_data(dev, devpriv->ai_buf0, numPoints);
1135        cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1136                                  numPoints * sizeof(devpriv->ai_buf0[0]));
1137        if (cmd->stop_src == TRIG_COUNT)
1138                devpriv->count -= numPoints;
1139        return;
1140}
1141
1142static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
1143                                          struct comedi_subdevice *s)
1144{
1145        short dpnt;
1146        int unipolar;
1147        struct comedi_cmd *cmd = &s->async->cmd;
1148
1149        unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1150
1151        while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1152                if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1153                        break;
1154                dpnt = inw(dev->iobase + DAS1800_FIFO);
1155                /* convert to unsigned type if we are in a bipolar mode */
1156                if (!unipolar) ;
1157                dpnt = munge_bipolar_sample(dev, dpnt);
1158                cfc_write_to_buffer(s, dpnt);
1159                if (cmd->stop_src == TRIG_COUNT)
1160                        devpriv->count--;
1161        }
1162
1163        return;
1164}
1165
1166static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1167{
1168        outb(0x0, dev->iobase + DAS1800_STATUS);        /* disable conversions */
1169        outb(0x0, dev->iobase + DAS1800_CONTROL_B);     /* disable interrupts and dma */
1170        outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* disable and clear fifo and stop triggering */
1171        if (devpriv->dma0)
1172                disable_dma(devpriv->dma0);
1173        if (devpriv->dma1)
1174                disable_dma(devpriv->dma1);
1175        return 0;
1176}
1177
1178/* test analog input cmd */
1179static int das1800_ai_do_cmdtest(struct comedi_device *dev,
1180                                 struct comedi_subdevice *s,
1181                                 struct comedi_cmd *cmd)
1182{
1183        int err = 0;
1184        int tmp;
1185        unsigned int tmp_arg;
1186        int i;
1187        int unipolar;
1188
1189        /* step 1: make sure trigger sources are trivially valid */
1190
1191        tmp = cmd->start_src;
1192        cmd->start_src &= TRIG_NOW | TRIG_EXT;
1193        if (!cmd->start_src || tmp != cmd->start_src)
1194                err++;
1195
1196        tmp = cmd->scan_begin_src;
1197        cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1198        if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1199                err++;
1200
1201        tmp = cmd->convert_src;
1202        cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1203        if (!cmd->convert_src || tmp != cmd->convert_src)
1204                err++;
1205
1206        tmp = cmd->scan_end_src;
1207        cmd->scan_end_src &= TRIG_COUNT;
1208        if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1209                err++;
1210
1211        tmp = cmd->stop_src;
1212        cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1213        if (!cmd->stop_src || tmp != cmd->stop_src)
1214                err++;
1215
1216        if (err)
1217                return 1;
1218
1219        /* step 2: make sure trigger sources are unique and mutually compatible */
1220
1221        /*  uniqueness check */
1222        if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1223                err++;
1224        if (cmd->scan_begin_src != TRIG_FOLLOW &&
1225            cmd->scan_begin_src != TRIG_TIMER &&
1226            cmd->scan_begin_src != TRIG_EXT)
1227                err++;
1228        if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1229                err++;
1230        if (cmd->stop_src != TRIG_COUNT &&
1231            cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1232                err++;
1233        /* compatibility check */
1234        if (cmd->scan_begin_src != TRIG_FOLLOW &&
1235            cmd->convert_src != TRIG_TIMER)
1236                err++;
1237
1238        if (err)
1239                return 2;
1240
1241        /* step 3: make sure arguments are trivially compatible */
1242
1243        if (cmd->start_arg != 0) {
1244                cmd->start_arg = 0;
1245                err++;
1246        }
1247        if (cmd->convert_src == TRIG_TIMER) {
1248                if (cmd->convert_arg < thisboard->ai_speed) {
1249                        cmd->convert_arg = thisboard->ai_speed;
1250                        err++;
1251                }
1252        }
1253        if (!cmd->chanlist_len) {
1254                cmd->chanlist_len = 1;
1255                err++;
1256        }
1257        if (cmd->scan_end_arg != cmd->chanlist_len) {
1258                cmd->scan_end_arg = cmd->chanlist_len;
1259                err++;
1260        }
1261
1262        switch (cmd->stop_src) {
1263        case TRIG_COUNT:
1264                if (!cmd->stop_arg) {
1265                        cmd->stop_arg = 1;
1266                        err++;
1267                }
1268                break;
1269        case TRIG_NONE:
1270                if (cmd->stop_arg != 0) {
1271                        cmd->stop_arg = 0;
1272                        err++;
1273                }
1274                break;
1275        default:
1276                break;
1277        }
1278
1279        if (err)
1280                return 3;
1281
1282        /* step 4: fix up any arguments */
1283
1284        if (cmd->convert_src == TRIG_TIMER) {
1285                /*  if we are not in burst mode */
1286                if (cmd->scan_begin_src == TRIG_FOLLOW) {
1287                        tmp_arg = cmd->convert_arg;
1288                        /* calculate counter values that give desired timing */
1289                        i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1290                                                       &(devpriv->divisor1),
1291                                                       &(devpriv->divisor2),
1292                                                       &(cmd->convert_arg),
1293                                                       cmd->
1294                                                       flags & TRIG_ROUND_MASK);
1295                        if (tmp_arg != cmd->convert_arg)
1296                                err++;
1297                }
1298                /*  if we are in burst mode */
1299                else {
1300                        /*  check that convert_arg is compatible */
1301                        tmp_arg = cmd->convert_arg;
1302                        cmd->convert_arg =
1303                            burst_convert_arg(cmd->convert_arg,
1304                                              cmd->flags & TRIG_ROUND_MASK);
1305                        if (tmp_arg != cmd->convert_arg)
1306                                err++;
1307
1308                        if (cmd->scan_begin_src == TRIG_TIMER) {
1309                                /*  if scans are timed faster than conversion rate allows */
1310                                if (cmd->convert_arg * cmd->chanlist_len >
1311                                    cmd->scan_begin_arg) {
1312                                        cmd->scan_begin_arg =
1313                                            cmd->convert_arg *
1314                                            cmd->chanlist_len;
1315                                        err++;
1316                                }
1317                                tmp_arg = cmd->scan_begin_arg;
1318                                /* calculate counter values that give desired timing */
1319                                i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1320                                                               &(devpriv->
1321                                                                 divisor1),
1322                                                               &(devpriv->
1323                                                                 divisor2),
1324                                                               &(cmd->
1325                                                                 scan_begin_arg),
1326                                                               cmd->
1327                                                               flags &
1328                                                               TRIG_ROUND_MASK);
1329                                if (tmp_arg != cmd->scan_begin_arg)
1330                                        err++;
1331                        }
1332                }
1333        }
1334
1335        if (err)
1336                return 4;
1337
1338        /*  make sure user is not trying to mix unipolar and bipolar ranges */
1339        if (cmd->chanlist) {
1340                unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1341                for (i = 1; i < cmd->chanlist_len; i++) {
1342                        if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1343                                comedi_error(dev,
1344                                             "unipolar and bipolar ranges cannot be mixed in the chanlist");
1345                                err++;
1346                                break;
1347                        }
1348                }
1349        }
1350
1351        if (err)
1352                return 5;
1353
1354        return 0;
1355}
1356
1357/* analog input cmd interface */
1358
1359/* first, some utility functions used in the main ai_do_cmd() */
1360
1361/* returns appropriate bits for control register a, depending on command */
1362static int control_a_bits(struct comedi_cmd cmd)
1363{
1364        int control_a;
1365
1366        control_a = FFEN;       /* enable fifo */
1367        if (cmd.stop_src == TRIG_EXT) {
1368                control_a |= ATEN;
1369        }
1370        switch (cmd.start_src) {
1371        case TRIG_EXT:
1372                control_a |= TGEN | CGSL;
1373                break;
1374        case TRIG_NOW:
1375                control_a |= CGEN;
1376                break;
1377        default:
1378                break;
1379        }
1380
1381        return control_a;
1382}
1383
1384/* returns appropriate bits for control register c, depending on command */
1385static int control_c_bits(struct comedi_cmd cmd)
1386{
1387        int control_c;
1388        int aref;
1389
1390        /* set clock source to internal or external, select analog reference,
1391         * select unipolar / bipolar
1392         */
1393        aref = CR_AREF(cmd.chanlist[0]);
1394        control_c = UQEN;       /* enable upper qram addresses */
1395        if (aref != AREF_DIFF)
1396                control_c |= SD;
1397        if (aref == AREF_COMMON)
1398                control_c |= CMEN;
1399        /* if a unipolar range was selected */
1400        if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1401                control_c |= UB;
1402        switch (cmd.scan_begin_src) {
1403        case TRIG_FOLLOW:       /*  not in burst mode */
1404                switch (cmd.convert_src) {
1405                case TRIG_TIMER:
1406                        /* trig on cascaded counters */
1407                        control_c |= IPCLK;
1408                        break;
1409                case TRIG_EXT:
1410                        /* trig on falling edge of external trigger */
1411                        control_c |= XPCLK;
1412                        break;
1413                default:
1414                        break;
1415                }
1416                break;
1417        case TRIG_TIMER:
1418                /*  burst mode with internal pacer clock */
1419                control_c |= BMDE | IPCLK;
1420                break;
1421        case TRIG_EXT:
1422                /*  burst mode with external trigger */
1423                control_c |= BMDE | XPCLK;
1424                break;
1425        default:
1426                break;
1427        }
1428
1429        return control_c;
1430}
1431
1432/* sets up counters */
1433static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
1434{
1435        /*  setup cascaded counters for conversion/scan frequency */
1436        switch (cmd.scan_begin_src) {
1437        case TRIG_FOLLOW:       /*  not in burst mode */
1438                if (cmd.convert_src == TRIG_TIMER) {
1439                        /* set conversion frequency */
1440                        i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1441                                                       &(devpriv->divisor1),
1442                                                       &(devpriv->divisor2),
1443                                                       &(cmd.convert_arg),
1444                                                       cmd.
1445                                                       flags & TRIG_ROUND_MASK);
1446                        if (das1800_set_frequency(dev) < 0) {
1447                                return -1;
1448                        }
1449                }
1450                break;
1451        case TRIG_TIMER:        /*  in burst mode */
1452                /* set scan frequency */
1453                i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1454                                               &(devpriv->divisor2),
1455                                               &(cmd.scan_begin_arg),
1456                                               cmd.flags & TRIG_ROUND_MASK);
1457                if (das1800_set_frequency(dev) < 0) {
1458                        return -1;
1459                }
1460                break;
1461        default:
1462                break;
1463        }
1464
1465        /*  setup counter 0 for 'about triggering' */
1466        if (cmd.stop_src == TRIG_EXT) {
1467                /*  load counter 0 in mode 0 */
1468                i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1469        }
1470
1471        return 0;
1472}
1473
1474/* sets up dma */
1475static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
1476{
1477        unsigned long lock_flags;
1478        const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1479
1480        if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1481                return;
1482
1483        /* determine a reasonable dma transfer size */
1484        devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1485        lock_flags = claim_dma_lock();
1486        disable_dma(devpriv->dma0);
1487        /* clear flip-flop to make sure 2-byte registers for
1488         * count and address get set correctly */
1489        clear_dma_ff(devpriv->dma0);
1490        set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1491        /*  set appropriate size of transfer */
1492        set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1493        devpriv->dma_current = devpriv->dma0;
1494        devpriv->dma_current_buf = devpriv->ai_buf0;
1495        enable_dma(devpriv->dma0);
1496        /*  set up dual dma if appropriate */
1497        if (dual_dma) {
1498                disable_dma(devpriv->dma1);
1499                /* clear flip-flop to make sure 2-byte registers for
1500                 * count and address get set correctly */
1501                clear_dma_ff(devpriv->dma1);
1502                set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1503                /*  set appropriate size of transfer */
1504                set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1505                enable_dma(devpriv->dma1);
1506        }
1507        release_dma_lock(lock_flags);
1508
1509        return;
1510}
1511
1512/* programs channel/gain list into card */
1513static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
1514{
1515        int i, n, chan_range;
1516        unsigned long irq_flags;
1517        const int range_mask = 0x3;     /* masks unipolar/bipolar bit off range */
1518        const int range_bitshift = 8;
1519
1520        n = cmd.chanlist_len;
1521        /*  spinlock protects indirect addressing */
1522        spin_lock_irqsave(&dev->spinlock, irq_flags);
1523        outb(QRAM, dev->iobase + DAS1800_SELECT);       /* select QRAM for baseAddress + 0x0 */
1524        outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);        /*set QRAM address start */
1525        /* make channel / gain list */
1526        for (i = 0; i < n; i++) {
1527                chan_range =
1528                    CR_CHAN(cmd.
1529                            chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) &
1530                                             range_mask) << range_bitshift);
1531                outw(chan_range, dev->iobase + DAS1800_QRAM);
1532        }
1533        outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);        /*finish write to QRAM */
1534        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1535
1536        return;
1537}
1538
1539/* analog input do_cmd */
1540static int das1800_ai_do_cmd(struct comedi_device *dev,
1541                             struct comedi_subdevice *s)
1542{
1543        int ret;
1544        int control_a, control_c;
1545        struct comedi_async *async = s->async;
1546        struct comedi_cmd cmd = async->cmd;
1547
1548        if (!dev->irq) {
1549                comedi_error(dev,
1550                             "no irq assigned for das-1800, cannot do hardware conversions");
1551                return -1;
1552        }
1553
1554        /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1555         * (because dma in handler is unsafe at hard real-time priority) */
1556        if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1557                devpriv->irq_dma_bits &= ~DMA_ENABLED;
1558        } else {
1559                devpriv->irq_dma_bits |= devpriv->dma_bits;
1560        }
1561        /*  interrupt on end of conversion for TRIG_WAKE_EOS */
1562        if (cmd.flags & TRIG_WAKE_EOS) {
1563                /*  interrupt fifo not empty */
1564                devpriv->irq_dma_bits &= ~FIMD;
1565        } else {
1566                /*  interrupt fifo half full */
1567                devpriv->irq_dma_bits |= FIMD;
1568        }
1569        /*  determine how many conversions we need */
1570        if (cmd.stop_src == TRIG_COUNT) {
1571                devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1572        }
1573
1574        das1800_cancel(dev, s);
1575
1576        /*  determine proper bits for control registers */
1577        control_a = control_a_bits(cmd);
1578        control_c = control_c_bits(cmd);
1579
1580        /* setup card and start */
1581        program_chanlist(dev, cmd);
1582        ret = setup_counters(dev, cmd);
1583        if (ret < 0) {
1584                comedi_error(dev, "Error setting up counters");
1585                return ret;
1586        }
1587        setup_dma(dev, cmd);
1588        outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1589        /*  set conversion rate and length for burst mode */
1590        if (control_c & BMDE) {
1591                /*  program conversion period with number of microseconds minus 1 */
1592                outb(cmd.convert_arg / 1000 - 1,
1593                     dev->iobase + DAS1800_BURST_RATE);
1594                outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1595        }
1596        outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);   /*  enable irq/dma */
1597        outb(control_a, dev->iobase + DAS1800_CONTROL_A);       /* enable fifo and triggering */
1598        outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
1599
1600        return 0;
1601}
1602
1603/* read analog input */
1604static int das1800_ai_rinsn(struct comedi_device *dev,
1605                            struct comedi_subdevice *s,
1606                            struct comedi_insn *insn, unsigned int *data)
1607{
1608        int i, n;
1609        int chan, range, aref, chan_range;
1610        int timeout = 1000;
1611        short dpnt;
1612        int conv_flags = 0;
1613        unsigned long irq_flags;
1614
1615        /* set up analog reference and unipolar / bipolar mode */
1616        aref = CR_AREF(insn->chanspec);
1617        conv_flags |= UQEN;
1618        if (aref != AREF_DIFF)
1619                conv_flags |= SD;
1620        if (aref == AREF_COMMON)
1621                conv_flags |= CMEN;
1622        /* if a unipolar range was selected */
1623        if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1624                conv_flags |= UB;
1625
1626        outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);      /* software conversion enabled */
1627        outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
1628        outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* reset fifo */
1629        outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1630
1631        chan = CR_CHAN(insn->chanspec);
1632        /* mask of unipolar/bipolar bit from range */
1633        range = CR_RANGE(insn->chanspec) & 0x3;
1634        chan_range = chan | (range << 8);
1635        spin_lock_irqsave(&dev->spinlock, irq_flags);
1636        outb(QRAM, dev->iobase + DAS1800_SELECT);       /* select QRAM for baseAddress + 0x0 */
1637        outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);  /* set QRAM address start */
1638        outw(chan_range, dev->iobase + DAS1800_QRAM);
1639        outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);  /*finish write to QRAM */
1640        outb(ADC, dev->iobase + DAS1800_SELECT);        /* select ADC for baseAddress + 0x0 */
1641
1642        for (n = 0; n < insn->n; n++) {
1643                /* trigger conversion */
1644                outb(0, dev->iobase + DAS1800_FIFO);
1645                for (i = 0; i < timeout; i++) {
1646                        if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1647                                break;
1648                }
1649                if (i == timeout) {
1650                        comedi_error(dev, "timeout");
1651                        n = -ETIME;
1652                        goto exit;
1653                }
1654                dpnt = inw(dev->iobase + DAS1800_FIFO);
1655                /* shift data to offset binary for bipolar ranges */
1656                if ((conv_flags & UB) == 0)
1657                        dpnt += 1 << (thisboard->resolution - 1);
1658                data[n] = dpnt;
1659        }
1660exit:
1661        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1662
1663        return n;
1664}
1665
1666/* writes to an analog output channel */
1667static int das1800_ao_winsn(struct comedi_device *dev,
1668                            struct comedi_subdevice *s,
1669                            struct comedi_insn *insn, unsigned int *data)
1670{
1671        int chan = CR_CHAN(insn->chanspec);
1672/* int range = CR_RANGE(insn->chanspec); */
1673        int update_chan = thisboard->ao_n_chan - 1;
1674        short output;
1675        unsigned long irq_flags;
1676
1677        /*   card expects two's complement data */
1678        output = data[0] - (1 << (thisboard->resolution - 1));
1679        /*  if the write is to the 'update' channel, we need to remember its value */
1680        if (chan == update_chan)
1681                devpriv->ao_update_bits = output;
1682        /*  write to channel */
1683        spin_lock_irqsave(&dev->spinlock, irq_flags);
1684        outb(DAC(chan), dev->iobase + DAS1800_SELECT);  /* select dac channel for baseAddress + 0x0 */
1685        outw(output, dev->iobase + DAS1800_DAC);
1686        /*  now we need to write to 'update' channel to update all dac channels */
1687        if (chan != update_chan) {
1688                outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);   /* select 'update' channel for baseAddress + 0x0 */
1689                outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1690        }
1691        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1692
1693        return 1;
1694}
1695
1696/* reads from digital input channels */
1697static int das1800_di_rbits(struct comedi_device *dev,
1698                            struct comedi_subdevice *s,
1699                            struct comedi_insn *insn, unsigned int *data)
1700{
1701
1702        data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1703        data[0] = 0;
1704
1705        return 2;
1706}
1707
1708/* writes to digital output channels */
1709static int das1800_do_wbits(struct comedi_device *dev,
1710                            struct comedi_subdevice *s,
1711                            struct comedi_insn *insn, unsigned int *data)
1712{
1713        unsigned int wbits;
1714
1715        /*  only set bits that have been masked */
1716        data[0] &= (1 << s->n_chan) - 1;
1717        wbits = devpriv->do_bits;
1718        wbits &= ~data[0];
1719        wbits |= data[0] & data[1];
1720        devpriv->do_bits = wbits;
1721
1722        outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1723
1724        data[1] = devpriv->do_bits;
1725
1726        return 2;
1727}
1728
1729/* loads counters with divisor1, divisor2 from private structure */
1730static int das1800_set_frequency(struct comedi_device *dev)
1731{
1732        int err = 0;
1733
1734        /*  counter 1, mode 2 */
1735        if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1736                       2))
1737                err++;
1738        /*  counter 2, mode 2 */
1739        if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1740                       2))
1741                err++;
1742        if (err)
1743                return -1;
1744
1745        return 0;
1746}
1747
1748/* converts requested conversion timing to timing compatible with
1749 * hardware, used only when card is in 'burst mode'
1750 */
1751static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1752{
1753        unsigned int micro_sec;
1754
1755        /*  in burst mode, the maximum conversion time is 64 microseconds */
1756        if (convert_arg > 64000)
1757                convert_arg = 64000;
1758
1759        /*  the conversion time must be an integral number of microseconds */
1760        switch (round_mode) {
1761        case TRIG_ROUND_NEAREST:
1762        default:
1763                micro_sec = (convert_arg + 500) / 1000;
1764                break;
1765        case TRIG_ROUND_DOWN:
1766                micro_sec = convert_arg / 1000;
1767                break;
1768        case TRIG_ROUND_UP:
1769                micro_sec = (convert_arg - 1) / 1000 + 1;
1770                break;
1771        }
1772
1773        /*  return number of nanoseconds */
1774        return micro_sec * 1000;
1775}
1776
1777/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1778static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
1779{
1780        unsigned int size = DMA_BUF_SIZE;
1781        static const int sample_size = 2;       /*  size in bytes of one sample from board */
1782        unsigned int fill_time = 300000000;     /*  target time in nanoseconds for filling dma buffer */
1783        unsigned int max_size;  /*  maximum size we will allow for a transfer */
1784
1785        /*  make dma buffer fill in 0.3 seconds for timed modes */
1786        switch (cmd->scan_begin_src) {
1787        case TRIG_FOLLOW:       /*  not in burst mode */
1788                if (cmd->convert_src == TRIG_TIMER)
1789                        size = (fill_time / cmd->convert_arg) * sample_size;
1790                break;
1791        case TRIG_TIMER:
1792                size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1793                    sample_size;
1794                break;
1795        default:
1796                size = DMA_BUF_SIZE;
1797                break;
1798        }
1799
1800        /*  set a minimum and maximum size allowed */
1801        max_size = DMA_BUF_SIZE;
1802        /*  if we are taking limited number of conversions, limit transfer size to that */
1803        if (cmd->stop_src == TRIG_COUNT &&
1804            cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1805                max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1806
1807        if (size > max_size)
1808                size = max_size;
1809        if (size < sample_size)
1810                size = sample_size;
1811
1812        return size;
1813}
1814
1815MODULE_AUTHOR("Comedi http://www.comedi.org");
1816MODULE_DESCRIPTION("Comedi low-level driver");
1817MODULE_LICENSE("GPL");
1818