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