root/drivers/staging/comedi/drivers/das1800.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. das1800_ai_munge
  2. das1800_handle_fifo_half_full
  3. das1800_handle_fifo_not_empty
  4. das1800_flush_dma_channel
  5. das1800_flush_dma
  6. das1800_handle_dma
  7. das1800_ai_cancel
  8. das1800_ai_handler
  9. das1800_ai_poll
  10. das1800_interrupt
  11. das1800_ai_fixup_paced_timing
  12. das1800_ai_fixup_burst_timing
  13. das1800_ai_check_chanlist
  14. das1800_ai_cmdtest
  15. das1800_ai_chanspec_bits
  16. das1800_ai_transfer_size
  17. das1800_ai_setup_dma
  18. das1800_ai_set_chanlist
  19. das1800_ai_cmd
  20. das1800_ai_eoc
  21. das1800_ai_insn_read
  22. das1800_ao_insn_write
  23. das1800_di_insn_bits
  24. das1800_do_insn_bits
  25. das1800_init_dma
  26. das1800_free_dma
  27. das1800_probe
  28. das1800_attach
  29. das1800_detach

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Comedi driver for Keithley DAS-1700/DAS-1800 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 
  10 /*
  11  * Driver: das1800
  12  * Description: Keithley Metrabyte DAS1800 (& compatibles)
  13  * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
  14  * Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
  15  *   DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
  16  *   DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
  17  *   DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
  18  *   DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
  19  *   DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
  20  *   DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
  21  *   DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
  22  *   DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
  23  *   DAS-1802AO (das-1802ao)
  24  * Status: works
  25  *
  26  * Configuration options:
  27  *   [0] - I/O port base address
  28  *   [1] - IRQ (optional, required for analog input cmd support)
  29  *   [2] - DMA0 (optional, requires irq)
  30  *   [3] - DMA1 (optional, requires irq and dma0)
  31  *
  32  * analog input cmd triggers supported:
  33  *
  34  *   start_src          TRIG_NOW        command starts immediately
  35  *                      TRIG_EXT        command starts on external pin TGIN
  36  *
  37  *   scan_begin_src     TRIG_FOLLOW     paced/external scans start immediately
  38  *                      TRIG_TIMER      burst scans start periodically
  39  *                      TRIG_EXT        burst scans start on external pin XPCLK
  40  *
  41  *   scan_end_src       TRIG_COUNT      scan ends after last channel
  42  *
  43  *   convert_src        TRIG_TIMER      paced/burst conversions are timed
  44  *                      TRIG_EXT        conversions on external pin XPCLK
  45  *                                      (requires scan_begin_src == TRIG_FOLLOW)
  46  *
  47  *   stop_src           TRIG_COUNT      command stops after stop_arg scans
  48  *                      TRIG_EXT        command stops on external pin TGIN
  49  *                      TRIG_NONE       command runs until canceled
  50  *
  51  * If TRIG_EXT is used for both the start_src and stop_src, the first TGIN
  52  * trigger starts the command, and the second trigger will stop it. If only
  53  * one is TRIG_EXT, the first trigger will either stop or start the command.
  54  * The external pin TGIN is normally set for negative edge triggering. It
  55  * can be set to positive edge with the CR_INVERT flag. If TRIG_EXT is used
  56  * for both the start_src and stop_src they must have the same polarity.
  57  *
  58  * Minimum conversion speed is limited to 64 microseconds (convert_arg <= 64000)
  59  * for 'burst' scans. This limitation does not apply for 'paced' scans. The
  60  * maximum conversion speed is limited by the board (convert_arg >= ai_speed).
  61  * Maximum conversion speeds are not always achievable depending on the
  62  * board setup (see user manual).
  63  *
  64  * NOTES:
  65  * Only the DAS-1801ST has been tested by me.
  66  * Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
  67  *
  68  * The waveform analog output on the 'ao' cards is not supported.
  69  * If you need it, send me (Frank Hess) an email.
  70  */
  71 
  72 #include <linux/module.h>
  73 #include <linux/interrupt.h>
  74 #include <linux/slab.h>
  75 #include <linux/io.h>
  76 
  77 #include "../comedidev.h"
  78 
  79 #include "comedi_isadma.h"
  80 #include "comedi_8254.h"
  81 
  82 /* misc. defines */
  83 #define DAS1800_SIZE           16       /* uses 16 io addresses */
  84 #define FIFO_SIZE              1024     /*  1024 sample fifo */
  85 #define DMA_BUF_SIZE           0x1ff00  /*  size in bytes of dma buffers */
  86 
  87 /* Registers for the das1800 */
  88 #define DAS1800_FIFO            0x0
  89 #define DAS1800_QRAM            0x0
  90 #define DAS1800_DAC             0x0
  91 #define DAS1800_SELECT          0x2
  92 #define   ADC                     0x0
  93 #define   QRAM                    0x1
  94 #define   DAC(a)                  (0x2 + a)
  95 #define DAS1800_DIGITAL         0x3
  96 #define DAS1800_CONTROL_A       0x4
  97 #define   FFEN                    0x1
  98 #define   CGEN                    0x4
  99 #define   CGSL                    0x8
 100 #define   TGEN                    0x10
 101 #define   TGSL                    0x20
 102 #define   TGPL                    0x40
 103 #define   ATEN                    0x80
 104 #define DAS1800_CONTROL_B       0x5
 105 #define   DMA_CH5                 0x1
 106 #define   DMA_CH6                 0x2
 107 #define   DMA_CH7                 0x3
 108 #define   DMA_CH5_CH6             0x5
 109 #define   DMA_CH6_CH7             0x6
 110 #define   DMA_CH7_CH5             0x7
 111 #define   DMA_ENABLED             0x3
 112 #define   DMA_DUAL                0x4
 113 #define   IRQ3                    0x8
 114 #define   IRQ5                    0x10
 115 #define   IRQ7                    0x18
 116 #define   IRQ10                   0x28
 117 #define   IRQ11                   0x30
 118 #define   IRQ15                   0x38
 119 #define   FIMD                    0x40
 120 #define DAS1800_CONTROL_C       0X6
 121 #define   IPCLK                   0x1
 122 #define   XPCLK                   0x3
 123 #define   BMDE                    0x4
 124 #define   CMEN                    0x8
 125 #define   UQEN                    0x10
 126 #define   SD                      0x40
 127 #define   UB                      0x80
 128 #define DAS1800_STATUS          0x7
 129 #define   INT                     0x1
 130 #define   DMATC                   0x2
 131 #define   CT0TC                   0x8
 132 #define   OVF                     0x10
 133 #define   FHF                     0x20
 134 #define   FNE                     0x40
 135 #define   CVEN                    0x80
 136 #define   CVEN_MASK               0x40
 137 #define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
 138 #define DAS1800_BURST_LENGTH    0x8
 139 #define DAS1800_BURST_RATE      0x9
 140 #define DAS1800_QRAM_ADDRESS    0xa
 141 #define DAS1800_COUNTER         0xc
 142 
 143 #define IOBASE2                   0x400
 144 
 145 static const struct comedi_lrange das1801_ai_range = {
 146         8, {
 147                 BIP_RANGE(5),           /* bipolar gain = 1 */
 148                 BIP_RANGE(1),           /* bipolar gain = 10 */
 149                 BIP_RANGE(0.1),         /* bipolar gain = 50 */
 150                 BIP_RANGE(0.02),        /* bipolar gain = 250 */
 151                 UNI_RANGE(5),           /* unipolar gain = 1 */
 152                 UNI_RANGE(1),           /* unipolar gain = 10 */
 153                 UNI_RANGE(0.1),         /* unipolar gain = 50 */
 154                 UNI_RANGE(0.02)         /* unipolar gain = 250 */
 155         }
 156 };
 157 
 158 static const struct comedi_lrange das1802_ai_range = {
 159         8, {
 160                 BIP_RANGE(10),          /* bipolar gain = 1 */
 161                 BIP_RANGE(5),           /* bipolar gain = 2 */
 162                 BIP_RANGE(2.5),         /* bipolar gain = 4 */
 163                 BIP_RANGE(1.25),        /* bipolar gain = 8 */
 164                 UNI_RANGE(10),          /* unipolar gain = 1 */
 165                 UNI_RANGE(5),           /* unipolar gain = 2 */
 166                 UNI_RANGE(2.5),         /* unipolar gain = 4 */
 167                 UNI_RANGE(1.25)         /* unipolar gain = 8 */
 168         }
 169 };
 170 
 171 /*
 172  * The waveform analog outputs on the 'ao' boards are not currently
 173  * supported. They have a comedi_lrange of:
 174  * { 2, { BIP_RANGE(10), BIP_RANGE(5) } }
 175  */
 176 
 177 enum das1800_boardid {
 178         BOARD_DAS1701ST,
 179         BOARD_DAS1701ST_DA,
 180         BOARD_DAS1702ST,
 181         BOARD_DAS1702ST_DA,
 182         BOARD_DAS1702HR,
 183         BOARD_DAS1702HR_DA,
 184         BOARD_DAS1701AO,
 185         BOARD_DAS1702AO,
 186         BOARD_DAS1801ST,
 187         BOARD_DAS1801ST_DA,
 188         BOARD_DAS1802ST,
 189         BOARD_DAS1802ST_DA,
 190         BOARD_DAS1802HR,
 191         BOARD_DAS1802HR_DA,
 192         BOARD_DAS1801HC,
 193         BOARD_DAS1802HC,
 194         BOARD_DAS1801AO,
 195         BOARD_DAS1802AO
 196 };
 197 
 198 /* board probe id values (hi byte of the digital input register) */
 199 #define DAS1800_ID_ST_DA                0x3
 200 #define DAS1800_ID_HR_DA                0x4
 201 #define DAS1800_ID_AO                   0x5
 202 #define DAS1800_ID_HR                   0x6
 203 #define DAS1800_ID_ST                   0x7
 204 #define DAS1800_ID_HC                   0x8
 205 
 206 struct das1800_board {
 207         const char *name;
 208         unsigned char id;
 209         unsigned int ai_speed;
 210         unsigned int is_01_series:1;
 211 };
 212 
 213 static const struct das1800_board das1800_boards[] = {
 214         [BOARD_DAS1701ST] = {
 215                 .name           = "das-1701st",
 216                 .id             = DAS1800_ID_ST,
 217                 .ai_speed       = 6250,
 218                 .is_01_series   = 1,
 219         },
 220         [BOARD_DAS1701ST_DA] = {
 221                 .name           = "das-1701st-da",
 222                 .id             = DAS1800_ID_ST_DA,
 223                 .ai_speed       = 6250,
 224                 .is_01_series   = 1,
 225         },
 226         [BOARD_DAS1702ST] = {
 227                 .name           = "das-1702st",
 228                 .id             = DAS1800_ID_ST,
 229                 .ai_speed       = 6250,
 230         },
 231         [BOARD_DAS1702ST_DA] = {
 232                 .name           = "das-1702st-da",
 233                 .id             = DAS1800_ID_ST_DA,
 234                 .ai_speed       = 6250,
 235         },
 236         [BOARD_DAS1702HR] = {
 237                 .name           = "das-1702hr",
 238                 .id             = DAS1800_ID_HR,
 239                 .ai_speed       = 20000,
 240         },
 241         [BOARD_DAS1702HR_DA] = {
 242                 .name           = "das-1702hr-da",
 243                 .id             = DAS1800_ID_HR_DA,
 244                 .ai_speed       = 20000,
 245         },
 246         [BOARD_DAS1701AO] = {
 247                 .name           = "das-1701ao",
 248                 .id             = DAS1800_ID_AO,
 249                 .ai_speed       = 6250,
 250                 .is_01_series   = 1,
 251         },
 252         [BOARD_DAS1702AO] = {
 253                 .name           = "das-1702ao",
 254                 .id             = DAS1800_ID_AO,
 255                 .ai_speed       = 6250,
 256         },
 257         [BOARD_DAS1801ST] = {
 258                 .name           = "das-1801st",
 259                 .id             = DAS1800_ID_ST,
 260                 .ai_speed       = 3000,
 261                 .is_01_series   = 1,
 262         },
 263         [BOARD_DAS1801ST_DA] = {
 264                 .name           = "das-1801st-da",
 265                 .id             = DAS1800_ID_ST_DA,
 266                 .ai_speed       = 3000,
 267                 .is_01_series   = 1,
 268         },
 269         [BOARD_DAS1802ST] = {
 270                 .name           = "das-1802st",
 271                 .id             = DAS1800_ID_ST,
 272                 .ai_speed       = 3000,
 273         },
 274         [BOARD_DAS1802ST_DA] = {
 275                 .name           = "das-1802st-da",
 276                 .id             = DAS1800_ID_ST_DA,
 277                 .ai_speed       = 3000,
 278         },
 279         [BOARD_DAS1802HR] = {
 280                 .name           = "das-1802hr",
 281                 .id             = DAS1800_ID_HR,
 282                 .ai_speed       = 10000,
 283         },
 284         [BOARD_DAS1802HR_DA] = {
 285                 .name           = "das-1802hr-da",
 286                 .id             = DAS1800_ID_HR_DA,
 287                 .ai_speed       = 10000,
 288         },
 289         [BOARD_DAS1801HC] = {
 290                 .name           = "das-1801hc",
 291                 .id             = DAS1800_ID_HC,
 292                 .ai_speed       = 3000,
 293                 .is_01_series   = 1,
 294         },
 295         [BOARD_DAS1802HC] = {
 296                 .name           = "das-1802hc",
 297                 .id             = DAS1800_ID_HC,
 298                 .ai_speed       = 3000,
 299         },
 300         [BOARD_DAS1801AO] = {
 301                 .name           = "das-1801ao",
 302                 .id             = DAS1800_ID_AO,
 303                 .ai_speed       = 3000,
 304                 .is_01_series   = 1,
 305         },
 306         [BOARD_DAS1802AO] = {
 307                 .name           = "das-1802ao",
 308                 .id             = DAS1800_ID_AO,
 309                 .ai_speed       = 3000,
 310         },
 311 };
 312 
 313 struct das1800_private {
 314         struct comedi_isadma *dma;
 315         int irq_dma_bits;
 316         int dma_bits;
 317         unsigned short *fifo_buf;
 318         unsigned long iobase2;
 319         bool ai_is_unipolar;
 320 };
 321 
 322 static void das1800_ai_munge(struct comedi_device *dev,
 323                              struct comedi_subdevice *s,
 324                              void *data, unsigned int num_bytes,
 325                              unsigned int start_chan_index)
 326 {
 327         struct das1800_private *devpriv = dev->private;
 328         unsigned short *array = data;
 329         unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
 330         unsigned int i;
 331 
 332         if (devpriv->ai_is_unipolar)
 333                 return;
 334 
 335         for (i = 0; i < num_samples; i++)
 336                 array[i] = comedi_offset_munge(s, array[i]);
 337 }
 338 
 339 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
 340                                           struct comedi_subdevice *s)
 341 {
 342         struct das1800_private *devpriv = dev->private;
 343         unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
 344 
 345         insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
 346         comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
 347 }
 348 
 349 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
 350                                           struct comedi_subdevice *s)
 351 {
 352         struct comedi_cmd *cmd = &s->async->cmd;
 353         unsigned short dpnt;
 354 
 355         while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
 356                 dpnt = inw(dev->iobase + DAS1800_FIFO);
 357                 comedi_buf_write_samples(s, &dpnt, 1);
 358 
 359                 if (cmd->stop_src == TRIG_COUNT &&
 360                     s->async->scans_done >= cmd->stop_arg)
 361                         break;
 362         }
 363 }
 364 
 365 static void das1800_flush_dma_channel(struct comedi_device *dev,
 366                                       struct comedi_subdevice *s,
 367                                       struct comedi_isadma_desc *desc)
 368 {
 369         unsigned int residue = comedi_isadma_disable(desc->chan);
 370         unsigned int nbytes = desc->size - residue;
 371         unsigned int nsamples;
 372 
 373         /*  figure out how many points to read */
 374         nsamples = comedi_bytes_to_samples(s, nbytes);
 375         nsamples = comedi_nsamples_left(s, nsamples);
 376 
 377         comedi_buf_write_samples(s, desc->virt_addr, nsamples);
 378 }
 379 
 380 static void das1800_flush_dma(struct comedi_device *dev,
 381                               struct comedi_subdevice *s)
 382 {
 383         struct das1800_private *devpriv = dev->private;
 384         struct comedi_isadma *dma = devpriv->dma;
 385         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 386         const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 387 
 388         das1800_flush_dma_channel(dev, s, desc);
 389 
 390         if (dual_dma) {
 391                 /*  switch to other channel and flush it */
 392                 dma->cur_dma = 1 - dma->cur_dma;
 393                 desc = &dma->desc[dma->cur_dma];
 394                 das1800_flush_dma_channel(dev, s, desc);
 395         }
 396 
 397         /*  get any remaining samples in fifo */
 398         das1800_handle_fifo_not_empty(dev, s);
 399 }
 400 
 401 static void das1800_handle_dma(struct comedi_device *dev,
 402                                struct comedi_subdevice *s, unsigned int status)
 403 {
 404         struct das1800_private *devpriv = dev->private;
 405         struct comedi_isadma *dma = devpriv->dma;
 406         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 407         const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
 408 
 409         das1800_flush_dma_channel(dev, s, desc);
 410 
 411         /* re-enable dma channel */
 412         comedi_isadma_program(desc);
 413 
 414         if (status & DMATC) {
 415                 /*  clear DMATC interrupt bit */
 416                 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
 417                 /*  switch dma channels for next time, if appropriate */
 418                 if (dual_dma)
 419                         dma->cur_dma = 1 - dma->cur_dma;
 420         }
 421 }
 422 
 423 static int das1800_ai_cancel(struct comedi_device *dev,
 424                              struct comedi_subdevice *s)
 425 {
 426         struct das1800_private *devpriv = dev->private;
 427         struct comedi_isadma *dma = devpriv->dma;
 428         struct comedi_isadma_desc *desc;
 429         int i;
 430 
 431         /* disable and stop conversions */
 432         outb(0x0, dev->iobase + DAS1800_STATUS);
 433         outb(0x0, dev->iobase + DAS1800_CONTROL_B);
 434         outb(0x0, dev->iobase + DAS1800_CONTROL_A);
 435 
 436         if (dma) {
 437                 for (i = 0; i < 2; i++) {
 438                         desc = &dma->desc[i];
 439                         if (desc->chan)
 440                                 comedi_isadma_disable(desc->chan);
 441                 }
 442         }
 443 
 444         return 0;
 445 }
 446 
 447 static void das1800_ai_handler(struct comedi_device *dev)
 448 {
 449         struct das1800_private *devpriv = dev->private;
 450         struct comedi_subdevice *s = dev->read_subdev;
 451         struct comedi_async *async = s->async;
 452         struct comedi_cmd *cmd = &async->cmd;
 453         unsigned int status = inb(dev->iobase + DAS1800_STATUS);
 454 
 455         /* select adc register (spinlock is already held) */
 456         outb(ADC, dev->iobase + DAS1800_SELECT);
 457 
 458         /* get samples with dma, fifo, or polled as necessary */
 459         if (devpriv->irq_dma_bits & DMA_ENABLED)
 460                 das1800_handle_dma(dev, s, status);
 461         else if (status & FHF)
 462                 das1800_handle_fifo_half_full(dev, s);
 463         else if (status & FNE)
 464                 das1800_handle_fifo_not_empty(dev, s);
 465 
 466         /* if the card's fifo has overflowed */
 467         if (status & OVF) {
 468                 /*  clear OVF interrupt bit */
 469                 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
 470                 dev_err(dev->class_dev, "FIFO overflow\n");
 471                 async->events |= COMEDI_CB_ERROR;
 472                 comedi_handle_events(dev, s);
 473                 return;
 474         }
 475         /*  stop taking data if appropriate */
 476         /* stop_src TRIG_EXT */
 477         if (status & CT0TC) {
 478                 /*  clear CT0TC interrupt bit */
 479                 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
 480                 /* get all remaining samples before quitting */
 481                 if (devpriv->irq_dma_bits & DMA_ENABLED)
 482                         das1800_flush_dma(dev, s);
 483                 else
 484                         das1800_handle_fifo_not_empty(dev, s);
 485                 async->events |= COMEDI_CB_EOA;
 486         } else if (cmd->stop_src == TRIG_COUNT &&
 487                    async->scans_done >= cmd->stop_arg) {
 488                 async->events |= COMEDI_CB_EOA;
 489         }
 490 
 491         comedi_handle_events(dev, s);
 492 }
 493 
 494 static int das1800_ai_poll(struct comedi_device *dev,
 495                            struct comedi_subdevice *s)
 496 {
 497         unsigned long flags;
 498 
 499         /*
 500          * Protects the indirect addressing selected by DAS1800_SELECT
 501          * in das1800_ai_handler() also prevents race with das1800_interrupt().
 502          */
 503         spin_lock_irqsave(&dev->spinlock, flags);
 504 
 505         das1800_ai_handler(dev);
 506 
 507         spin_unlock_irqrestore(&dev->spinlock, flags);
 508 
 509         return comedi_buf_n_bytes_ready(s);
 510 }
 511 
 512 static irqreturn_t das1800_interrupt(int irq, void *d)
 513 {
 514         struct comedi_device *dev = d;
 515         unsigned int status;
 516 
 517         if (!dev->attached) {
 518                 dev_err(dev->class_dev, "premature interrupt\n");
 519                 return IRQ_HANDLED;
 520         }
 521 
 522         /*
 523          * Protects the indirect addressing selected by DAS1800_SELECT
 524          * in das1800_ai_handler() also prevents race with das1800_ai_poll().
 525          */
 526         spin_lock(&dev->spinlock);
 527 
 528         status = inb(dev->iobase + DAS1800_STATUS);
 529 
 530         /* if interrupt was not caused by das-1800 */
 531         if (!(status & INT)) {
 532                 spin_unlock(&dev->spinlock);
 533                 return IRQ_NONE;
 534         }
 535         /* clear the interrupt status bit INT */
 536         outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
 537         /*  handle interrupt */
 538         das1800_ai_handler(dev);
 539 
 540         spin_unlock(&dev->spinlock);
 541         return IRQ_HANDLED;
 542 }
 543 
 544 static int das1800_ai_fixup_paced_timing(struct comedi_device *dev,
 545                                          struct comedi_cmd *cmd)
 546 {
 547         unsigned int arg = cmd->convert_arg;
 548 
 549         /*
 550          * Paced mode:
 551          *      scan_begin_src is TRIG_FOLLOW
 552          *      convert_src is TRIG_TIMER
 553          *
 554          * The convert_arg sets the pacer sample acquisition time.
 555          * The max acquisition speed is limited to the boards
 556          * 'ai_speed' (this was already verified). The min speed is
 557          * limited by the cascaded 8254 timer.
 558          */
 559         comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 560         return comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 561 }
 562 
 563 static int das1800_ai_fixup_burst_timing(struct comedi_device *dev,
 564                                          struct comedi_cmd *cmd)
 565 {
 566         unsigned int arg = cmd->convert_arg;
 567         int err = 0;
 568 
 569         /*
 570          * Burst mode:
 571          *      scan_begin_src is TRIG_TIMER or TRIG_EXT
 572          *      convert_src is TRIG_TIMER
 573          *
 574          * The convert_arg sets burst sample acquisition time.
 575          * The max acquisition speed is limited to the boards
 576          * 'ai_speed' (this was already verified). The min speed is
 577          * limiited to 64 microseconds,
 578          */
 579         err |= comedi_check_trigger_arg_max(&arg, 64000);
 580 
 581         /* round to microseconds then verify */
 582         switch (cmd->flags & CMDF_ROUND_MASK) {
 583         case CMDF_ROUND_NEAREST:
 584         default:
 585                 arg = DIV_ROUND_CLOSEST(arg, 1000);
 586                 break;
 587         case CMDF_ROUND_DOWN:
 588                 arg = arg / 1000;
 589                 break;
 590         case CMDF_ROUND_UP:
 591                 arg = DIV_ROUND_UP(arg, 1000);
 592                 break;
 593         }
 594         err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg * 1000);
 595 
 596         /*
 597          * The pacer can be used to set the scan sample rate. The max scan
 598          * speed is limited by the conversion speed and the number of channels
 599          * to convert. The min speed is limited by the cascaded 8254 timer.
 600          */
 601         if (cmd->scan_begin_src == TRIG_TIMER) {
 602                 arg = cmd->convert_arg * cmd->chanlist_len;
 603                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 604 
 605                 arg = cmd->scan_begin_arg;
 606                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 607                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 608         }
 609 
 610         return err;
 611 }
 612 
 613 static int das1800_ai_check_chanlist(struct comedi_device *dev,
 614                                      struct comedi_subdevice *s,
 615                                      struct comedi_cmd *cmd)
 616 {
 617         unsigned int range = CR_RANGE(cmd->chanlist[0]);
 618         bool unipolar0 = comedi_range_is_unipolar(s, range);
 619         int i;
 620 
 621         for (i = 1; i < cmd->chanlist_len; i++) {
 622                 range = CR_RANGE(cmd->chanlist[i]);
 623 
 624                 if (unipolar0 != comedi_range_is_unipolar(s, range)) {
 625                         dev_dbg(dev->class_dev,
 626                                 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
 627                         return -EINVAL;
 628                 }
 629         }
 630 
 631         return 0;
 632 }
 633 
 634 static int das1800_ai_cmdtest(struct comedi_device *dev,
 635                               struct comedi_subdevice *s,
 636                               struct comedi_cmd *cmd)
 637 {
 638         const struct das1800_board *board = dev->board_ptr;
 639         int err = 0;
 640 
 641         /* Step 1 : check if triggers are trivially valid */
 642 
 643         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
 644         err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 645                                         TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
 646         err |= comedi_check_trigger_src(&cmd->convert_src,
 647                                         TRIG_TIMER | TRIG_EXT);
 648         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 649         err |= comedi_check_trigger_src(&cmd->stop_src,
 650                                         TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 651 
 652         if (err)
 653                 return 1;
 654 
 655         /* Step 2a : make sure trigger sources are unique */
 656 
 657         err |= comedi_check_trigger_is_unique(cmd->start_src);
 658         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 659         err |= comedi_check_trigger_is_unique(cmd->convert_src);
 660         err |= comedi_check_trigger_is_unique(cmd->stop_src);
 661 
 662         /* Step 2b : and mutually compatible */
 663 
 664         /* burst scans must use timed conversions */
 665         if (cmd->scan_begin_src != TRIG_FOLLOW &&
 666             cmd->convert_src != TRIG_TIMER)
 667                 err |= -EINVAL;
 668 
 669         /* the external pin TGIN must use the same polarity */
 670         if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
 671                 err |= comedi_check_trigger_arg_is(&cmd->start_arg,
 672                                                    cmd->stop_arg);
 673 
 674         if (err)
 675                 return 2;
 676 
 677         /* Step 3: check if arguments are trivially valid */
 678 
 679         if (cmd->start_arg == TRIG_NOW)
 680                 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 681 
 682         if (cmd->convert_src == TRIG_TIMER) {
 683                 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 684                                                     board->ai_speed);
 685         }
 686 
 687         err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
 688         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 689                                            cmd->chanlist_len);
 690 
 691         switch (cmd->stop_src) {
 692         case TRIG_COUNT:
 693                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 694                 break;
 695         case TRIG_NONE:
 696                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 697                 break;
 698         default:
 699                 break;
 700         }
 701 
 702         if (err)
 703                 return 3;
 704 
 705         /* Step 4: fix up any arguments */
 706 
 707         if (cmd->convert_src == TRIG_TIMER) {
 708                 if (cmd->scan_begin_src == TRIG_FOLLOW)
 709                         err |= das1800_ai_fixup_paced_timing(dev, cmd);
 710                 else /* TRIG_TIMER or TRIG_EXT */
 711                         err |= das1800_ai_fixup_burst_timing(dev, cmd);
 712         }
 713 
 714         if (err)
 715                 return 4;
 716 
 717         /* Step 5: check channel list if it exists */
 718         if (cmd->chanlist && cmd->chanlist_len > 0)
 719                 err |= das1800_ai_check_chanlist(dev, s, cmd);
 720 
 721         if (err)
 722                 return 5;
 723 
 724         return 0;
 725 }
 726 
 727 static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s,
 728                                               unsigned int chanspec)
 729 {
 730         unsigned int range = CR_RANGE(chanspec);
 731         unsigned int aref = CR_AREF(chanspec);
 732         unsigned char bits;
 733 
 734         bits = UQEN;
 735         if (aref != AREF_DIFF)
 736                 bits |= SD;
 737         if (aref == AREF_COMMON)
 738                 bits |= CMEN;
 739         if (comedi_range_is_unipolar(s, range))
 740                 bits |= UB;
 741 
 742         return bits;
 743 }
 744 
 745 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
 746                                              struct comedi_subdevice *s,
 747                                              unsigned int maxbytes,
 748                                              unsigned int ns)
 749 {
 750         struct comedi_cmd *cmd = &s->async->cmd;
 751         unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
 752         unsigned int samples;
 753 
 754         samples = max_samples;
 755 
 756         /* for timed modes, make dma buffer fill in 'ns' time */
 757         switch (cmd->scan_begin_src) {
 758         case TRIG_FOLLOW:       /* not in burst mode */
 759                 if (cmd->convert_src == TRIG_TIMER)
 760                         samples = ns / cmd->convert_arg;
 761                 break;
 762         case TRIG_TIMER:
 763                 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
 764                 break;
 765         }
 766 
 767         /* limit samples to what is remaining in the command */
 768         samples = comedi_nsamples_left(s, samples);
 769 
 770         if (samples > max_samples)
 771                 samples = max_samples;
 772         if (samples < 1)
 773                 samples = 1;
 774 
 775         return comedi_samples_to_bytes(s, samples);
 776 }
 777 
 778 static void das1800_ai_setup_dma(struct comedi_device *dev,
 779                                  struct comedi_subdevice *s)
 780 {
 781         struct das1800_private *devpriv = dev->private;
 782         struct comedi_isadma *dma = devpriv->dma;
 783         struct comedi_isadma_desc *desc;
 784         unsigned int bytes;
 785 
 786         if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
 787                 return;
 788 
 789         dma->cur_dma = 0;
 790         desc = &dma->desc[0];
 791 
 792         /* determine a dma transfer size to fill buffer in 0.3 sec */
 793         bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
 794 
 795         desc->size = bytes;
 796         comedi_isadma_program(desc);
 797 
 798         /* set up dual dma if appropriate */
 799         if (devpriv->irq_dma_bits & DMA_DUAL) {
 800                 desc = &dma->desc[1];
 801                 desc->size = bytes;
 802                 comedi_isadma_program(desc);
 803         }
 804 }
 805 
 806 static void das1800_ai_set_chanlist(struct comedi_device *dev,
 807                                     unsigned int *chanlist, unsigned int len)
 808 {
 809         unsigned long flags;
 810         unsigned int i;
 811 
 812         /* protects the indirect addressing selected by DAS1800_SELECT */
 813         spin_lock_irqsave(&dev->spinlock, flags);
 814 
 815         /* select QRAM register and set start address */
 816         outb(QRAM, dev->iobase + DAS1800_SELECT);
 817         outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
 818 
 819         /* make channel / gain list */
 820         for (i = 0; i < len; i++) {
 821                 unsigned int chan = CR_CHAN(chanlist[i]);
 822                 unsigned int range = CR_RANGE(chanlist[i]);
 823                 unsigned short val;
 824 
 825                 val = chan | ((range & 0x3) << 8);
 826                 outw(val, dev->iobase + DAS1800_QRAM);
 827         }
 828 
 829         /* finish write to QRAM */
 830         outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
 831 
 832         spin_unlock_irqrestore(&dev->spinlock, flags);
 833 }
 834 
 835 static int das1800_ai_cmd(struct comedi_device *dev,
 836                           struct comedi_subdevice *s)
 837 {
 838         struct das1800_private *devpriv = dev->private;
 839         int control_a, control_c;
 840         struct comedi_async *async = s->async;
 841         const struct comedi_cmd *cmd = &async->cmd;
 842         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 843 
 844         /*
 845          * Disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY (because dma in
 846          * handler is unsafe at hard real-time priority).
 847          */
 848         if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
 849                 devpriv->irq_dma_bits &= ~DMA_ENABLED;
 850         else
 851                 devpriv->irq_dma_bits |= devpriv->dma_bits;
 852         /*  interrupt on end of conversion for CMDF_WAKE_EOS */
 853         if (cmd->flags & CMDF_WAKE_EOS) {
 854                 /*  interrupt fifo not empty */
 855                 devpriv->irq_dma_bits &= ~FIMD;
 856         } else {
 857                 /*  interrupt fifo half full */
 858                 devpriv->irq_dma_bits |= FIMD;
 859         }
 860 
 861         das1800_ai_cancel(dev, s);
 862 
 863         devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0);
 864 
 865         control_a = FFEN;
 866         if (cmd->stop_src == TRIG_EXT)
 867                 control_a |= ATEN;
 868         if (cmd->start_src == TRIG_EXT)
 869                 control_a |= TGEN | CGSL;
 870         else /* TRIG_NOW */
 871                 control_a |= CGEN;
 872         if (control_a & (ATEN | TGEN)) {
 873                 if ((cmd->start_arg & CR_INVERT) || (cmd->stop_arg & CR_INVERT))
 874                         control_a |= TGPL;
 875         }
 876 
 877         control_c = das1800_ai_chanspec_bits(s, cmd->chanlist[0]);
 878         /* set clock source to internal or external */
 879         if (cmd->scan_begin_src == TRIG_FOLLOW) {
 880                 /* not in burst mode */
 881                 if (cmd->convert_src == TRIG_TIMER) {
 882                         /* trig on cascaded counters */
 883                         control_c |= IPCLK;
 884                 } else { /* TRIG_EXT */
 885                         /* trig on falling edge of external trigger */
 886                         control_c |= XPCLK;
 887                 }
 888         } else if (cmd->scan_begin_src == TRIG_TIMER) {
 889                 /* burst mode with internal pacer clock */
 890                 control_c |= BMDE | IPCLK;
 891         } else { /* TRIG_EXT */
 892                 /* burst mode with external trigger */
 893                 control_c |= BMDE | XPCLK;
 894         }
 895 
 896         das1800_ai_set_chanlist(dev, cmd->chanlist, cmd->chanlist_len);
 897 
 898         /* setup cascaded counters for conversion/scan frequency */
 899         if ((cmd->scan_begin_src == TRIG_FOLLOW ||
 900              cmd->scan_begin_src == TRIG_TIMER) &&
 901             cmd->convert_src == TRIG_TIMER) {
 902                 comedi_8254_update_divisors(dev->pacer);
 903                 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 904         }
 905 
 906         /* setup counter 0 for 'about triggering' */
 907         if (cmd->stop_src == TRIG_EXT)
 908                 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
 909 
 910         das1800_ai_setup_dma(dev, s);
 911         outb(control_c, dev->iobase + DAS1800_CONTROL_C);
 912         /*  set conversion rate and length for burst mode */
 913         if (control_c & BMDE) {
 914                 outb(cmd->convert_arg / 1000 - 1,       /* microseconds - 1 */
 915                      dev->iobase + DAS1800_BURST_RATE);
 916                 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
 917         }
 918 
 919         /* enable and start conversions */
 920         outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);
 921         outb(control_a, dev->iobase + DAS1800_CONTROL_A);
 922         outb(CVEN, dev->iobase + DAS1800_STATUS);
 923 
 924         return 0;
 925 }
 926 
 927 static int das1800_ai_eoc(struct comedi_device *dev,
 928                           struct comedi_subdevice *s,
 929                           struct comedi_insn *insn,
 930                           unsigned long context)
 931 {
 932         unsigned char status;
 933 
 934         status = inb(dev->iobase + DAS1800_STATUS);
 935         if (status & FNE)
 936                 return 0;
 937         return -EBUSY;
 938 }
 939 
 940 static int das1800_ai_insn_read(struct comedi_device *dev,
 941                                 struct comedi_subdevice *s,
 942                                 struct comedi_insn *insn,
 943                                 unsigned int *data)
 944 {
 945         unsigned int range = CR_RANGE(insn->chanspec);
 946         bool is_unipolar = comedi_range_is_unipolar(s, range);
 947         int ret = 0;
 948         int n;
 949         unsigned short dpnt;
 950         unsigned long flags;
 951 
 952         outb(das1800_ai_chanspec_bits(s, insn->chanspec),
 953              dev->iobase + DAS1800_CONTROL_C);          /* software pacer */
 954         outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
 955         outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* reset fifo */
 956         outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
 957 
 958         das1800_ai_set_chanlist(dev, &insn->chanspec, 1);
 959 
 960         /* protects the indirect addressing selected by DAS1800_SELECT */
 961         spin_lock_irqsave(&dev->spinlock, flags);
 962 
 963         /* select ai fifo register */
 964         outb(ADC, dev->iobase + DAS1800_SELECT);
 965 
 966         for (n = 0; n < insn->n; n++) {
 967                 /* trigger conversion */
 968                 outb(0, dev->iobase + DAS1800_FIFO);
 969 
 970                 ret = comedi_timeout(dev, s, insn, das1800_ai_eoc, 0);
 971                 if (ret)
 972                         break;
 973 
 974                 dpnt = inw(dev->iobase + DAS1800_FIFO);
 975                 if (!is_unipolar)
 976                         dpnt = comedi_offset_munge(s, dpnt);
 977                 data[n] = dpnt;
 978         }
 979         spin_unlock_irqrestore(&dev->spinlock, flags);
 980 
 981         return ret ? ret : insn->n;
 982 }
 983 
 984 static int das1800_ao_insn_write(struct comedi_device *dev,
 985                                  struct comedi_subdevice *s,
 986                                  struct comedi_insn *insn,
 987                                  unsigned int *data)
 988 {
 989         unsigned int chan = CR_CHAN(insn->chanspec);
 990         unsigned int update_chan = s->n_chan - 1;
 991         unsigned long flags;
 992         int i;
 993 
 994         /* protects the indirect addressing selected by DAS1800_SELECT */
 995         spin_lock_irqsave(&dev->spinlock, flags);
 996 
 997         for (i = 0; i < insn->n; i++) {
 998                 unsigned int val = data[i];
 999 
1000                 s->readback[chan] = val;
1001 
1002                 val = comedi_offset_munge(s, val);
1003 
1004                 /* load this channel (and update if it's the last channel) */
1005                 outb(DAC(chan), dev->iobase + DAS1800_SELECT);
1006                 outw(val, dev->iobase + DAS1800_DAC);
1007 
1008                 /* update all channels */
1009                 if (chan != update_chan) {
1010                         val = comedi_offset_munge(s, s->readback[update_chan]);
1011 
1012                         outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);
1013                         outw(val, dev->iobase + DAS1800_DAC);
1014                 }
1015         }
1016         spin_unlock_irqrestore(&dev->spinlock, flags);
1017 
1018         return insn->n;
1019 }
1020 
1021 static int das1800_di_insn_bits(struct comedi_device *dev,
1022                                 struct comedi_subdevice *s,
1023                                 struct comedi_insn *insn,
1024                                 unsigned int *data)
1025 {
1026         data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1027         data[0] = 0;
1028 
1029         return insn->n;
1030 }
1031 
1032 static int das1800_do_insn_bits(struct comedi_device *dev,
1033                                 struct comedi_subdevice *s,
1034                                 struct comedi_insn *insn,
1035                                 unsigned int *data)
1036 {
1037         if (comedi_dio_update_state(s, data))
1038                 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1039 
1040         data[1] = s->state;
1041 
1042         return insn->n;
1043 }
1044 
1045 static void das1800_init_dma(struct comedi_device *dev,
1046                              struct comedi_devconfig *it)
1047 {
1048         struct das1800_private *devpriv = dev->private;
1049         unsigned int *dma_chan;
1050 
1051         /*
1052          * it->options[2] is DMA channel 0
1053          * it->options[3] is DMA channel 1
1054          *
1055          * Encode the DMA channels into 2 digit hexadecimal for switch.
1056          */
1057         dma_chan = &it->options[2];
1058 
1059         switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1060         case 0x5:       /*  dma0 == 5 */
1061                 devpriv->dma_bits = DMA_CH5;
1062                 break;
1063         case 0x6:       /*  dma0 == 6 */
1064                 devpriv->dma_bits = DMA_CH6;
1065                 break;
1066         case 0x7:       /*  dma0 == 7 */
1067                 devpriv->dma_bits = DMA_CH7;
1068                 break;
1069         case 0x65:      /*  dma0 == 5, dma1 == 6 */
1070                 devpriv->dma_bits = DMA_CH5_CH6;
1071                 break;
1072         case 0x76:      /*  dma0 == 6, dma1 == 7 */
1073                 devpriv->dma_bits = DMA_CH6_CH7;
1074                 break;
1075         case 0x57:      /*  dma0 == 7, dma1 == 5 */
1076                 devpriv->dma_bits = DMA_CH7_CH5;
1077                 break;
1078         default:
1079                 return;
1080         }
1081 
1082         /* DMA can use 1 or 2 buffers, each with a separate channel */
1083         devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1084                                            dma_chan[0], dma_chan[1],
1085                                            DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1086         if (!devpriv->dma)
1087                 devpriv->dma_bits = 0;
1088 }
1089 
1090 static void das1800_free_dma(struct comedi_device *dev)
1091 {
1092         struct das1800_private *devpriv = dev->private;
1093 
1094         if (devpriv)
1095                 comedi_isadma_free(devpriv->dma);
1096 }
1097 
1098 static int das1800_probe(struct comedi_device *dev)
1099 {
1100         const struct das1800_board *board = dev->board_ptr;
1101         unsigned char id;
1102 
1103         id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1104 
1105         /*
1106          * The dev->board_ptr will be set by comedi_device_attach() if the
1107          * board name provided by the user matches a board->name in this
1108          * driver. If so, this function sanity checks the id to verify that
1109          * the board is correct.
1110          */
1111         if (board) {
1112                 if (board->id == id)
1113                         return 0;
1114                 dev_err(dev->class_dev,
1115                         "probed id does not match board id (0x%x != 0x%x)\n",
1116                         id, board->id);
1117                 return -ENODEV;
1118         }
1119 
1120          /*
1121           * If the dev->board_ptr is not set, the user is trying to attach
1122           * an unspecified board to this driver. In this case the id is used
1123           * to 'probe' for the dev->board_ptr.
1124           */
1125         switch (id) {
1126         case DAS1800_ID_ST_DA:
1127                 /* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */
1128                 board = &das1800_boards[BOARD_DAS1801ST_DA];
1129                 break;
1130         case DAS1800_ID_HR_DA:
1131                 /* das-1702hr-da, das-1802hr-da */
1132                 board = &das1800_boards[BOARD_DAS1802HR_DA];
1133                 break;
1134         case DAS1800_ID_AO:
1135                 /* das-1701ao, das-1702ao, das-1801ao, das-1802ao */
1136                 board = &das1800_boards[BOARD_DAS1801AO];
1137                 break;
1138         case DAS1800_ID_HR:
1139                 /*  das-1702hr, das-1802hr */
1140                 board = &das1800_boards[BOARD_DAS1802HR];
1141                 break;
1142         case DAS1800_ID_ST:
1143                 /* das-1701st, das-1702st, das-1801st, das-1802st */
1144                 board = &das1800_boards[BOARD_DAS1801ST];
1145                 break;
1146         case DAS1800_ID_HC:
1147                 /* das-1801hc, das-1802hc */
1148                 board = &das1800_boards[BOARD_DAS1801HC];
1149                 break;
1150         default:
1151                 dev_err(dev->class_dev, "invalid probe id 0x%x\n", id);
1152                 return -ENODEV;
1153         }
1154         dev->board_ptr = board;
1155         dev->board_name = board->name;
1156         dev_warn(dev->class_dev,
1157                  "probed id 0x%0x: %s series (not recommended)\n",
1158                  id, board->name);
1159         return 0;
1160 }
1161 
1162 static int das1800_attach(struct comedi_device *dev,
1163                           struct comedi_devconfig *it)
1164 {
1165         const struct das1800_board *board;
1166         struct das1800_private *devpriv;
1167         struct comedi_subdevice *s;
1168         unsigned int irq = it->options[1];
1169         bool is_16bit;
1170         int ret;
1171         int i;
1172 
1173         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1174         if (!devpriv)
1175                 return -ENOMEM;
1176 
1177         ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1178         if (ret)
1179                 return ret;
1180 
1181         ret = das1800_probe(dev);
1182         if (ret)
1183                 return ret;
1184         board = dev->board_ptr;
1185 
1186         is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;
1187 
1188         /* waveform 'ao' boards have additional io ports */
1189         if (board->id == DAS1800_ID_AO) {
1190                 unsigned long iobase2 = dev->iobase + IOBASE2;
1191 
1192                 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1193                 if (ret)
1194                         return ret;
1195                 devpriv->iobase2 = iobase2;
1196         }
1197 
1198         if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1199             irq == 15) {
1200                 ret = request_irq(irq, das1800_interrupt, 0,
1201                                   dev->board_name, dev);
1202                 if (ret == 0) {
1203                         dev->irq = irq;
1204 
1205                         switch (irq) {
1206                         case 3:
1207                                 devpriv->irq_dma_bits |= 0x8;
1208                                 break;
1209                         case 5:
1210                                 devpriv->irq_dma_bits |= 0x10;
1211                                 break;
1212                         case 7:
1213                                 devpriv->irq_dma_bits |= 0x18;
1214                                 break;
1215                         case 10:
1216                                 devpriv->irq_dma_bits |= 0x28;
1217                                 break;
1218                         case 11:
1219                                 devpriv->irq_dma_bits |= 0x30;
1220                                 break;
1221                         case 15:
1222                                 devpriv->irq_dma_bits |= 0x38;
1223                                 break;
1224                         }
1225                 }
1226         }
1227 
1228         /* an irq and one dma channel is required to use dma */
1229         if (dev->irq & it->options[2])
1230                 das1800_init_dma(dev, it);
1231 
1232         devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
1233                                           sizeof(*devpriv->fifo_buf),
1234                                           GFP_KERNEL);
1235         if (!devpriv->fifo_buf)
1236                 return -ENOMEM;
1237 
1238         dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1239                                       I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1240         if (!dev->pacer)
1241                 return -ENOMEM;
1242 
1243         ret = comedi_alloc_subdevices(dev, 4);
1244         if (ret)
1245                 return ret;
1246 
1247         /*
1248          * Analog Input subdevice
1249          *
1250          * The "hc" type boards have 64 analog input channels and a 64
1251          * entry QRAM fifo.
1252          *
1253          * All the other board types have 16 on-board channels. Each channel
1254          * can be expanded to 16 channels with the addition of an EXP-1800
1255          * expansion board for a total of 256 channels. The QRAM fifo on
1256          * these boards has 256 entries.
1257          *
1258          * From the datasheets it's not clear what the comedi channel to
1259          * actual physical channel mapping is when EXP-1800 boards are used.
1260          */
1261         s = &dev->subdevices[0];
1262         s->type         = COMEDI_SUBD_AI;
1263         s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1264         if (board->id != DAS1800_ID_HC)
1265                 s->subdev_flags |= SDF_COMMON;
1266         s->n_chan       = (board->id == DAS1800_ID_HC) ? 64 : 256;
1267         s->maxdata      = is_16bit ? 0xffff : 0x0fff;
1268         s->range_table  = board->is_01_series ? &das1801_ai_range
1269                                               : &das1802_ai_range;
1270         s->insn_read    = das1800_ai_insn_read;
1271         if (dev->irq) {
1272                 dev->read_subdev = s;
1273                 s->subdev_flags |= SDF_CMD_READ;
1274                 s->len_chanlist = s->n_chan;
1275                 s->do_cmd       = das1800_ai_cmd;
1276                 s->do_cmdtest   = das1800_ai_cmdtest;
1277                 s->poll         = das1800_ai_poll;
1278                 s->cancel       = das1800_ai_cancel;
1279                 s->munge        = das1800_ai_munge;
1280         }
1281 
1282         /* Analog Output subdevice */
1283         s = &dev->subdevices[1];
1284         if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
1285                 s->type         = COMEDI_SUBD_AO;
1286                 s->subdev_flags = SDF_WRITABLE;
1287                 s->n_chan       = (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
1288                 s->maxdata      = is_16bit ? 0xffff : 0x0fff;
1289                 s->range_table  = &range_bipolar10;
1290                 s->insn_write   = das1800_ao_insn_write;
1291 
1292                 ret = comedi_alloc_subdev_readback(s);
1293                 if (ret)
1294                         return ret;
1295 
1296                 /* initialize all channels to 0V */
1297                 for (i = 0; i < s->n_chan; i++) {
1298                         /* spinlock is not necessary during the attach */
1299                         outb(DAC(i), dev->iobase + DAS1800_SELECT);
1300                         outw(0, dev->iobase + DAS1800_DAC);
1301                 }
1302         } else if (board->id == DAS1800_ID_AO) {
1303                 /*
1304                  * 'ao' boards have waveform analog outputs that are not
1305                  * currently supported.
1306                  */
1307                 s->type         = COMEDI_SUBD_UNUSED;
1308         } else {
1309                 s->type         = COMEDI_SUBD_UNUSED;
1310         }
1311 
1312         /* Digital Input subdevice */
1313         s = &dev->subdevices[2];
1314         s->type         = COMEDI_SUBD_DI;
1315         s->subdev_flags = SDF_READABLE;
1316         s->n_chan       = 4;
1317         s->maxdata      = 1;
1318         s->range_table  = &range_digital;
1319         s->insn_bits    = das1800_di_insn_bits;
1320 
1321         /* Digital Output subdevice */
1322         s = &dev->subdevices[3];
1323         s->type         = COMEDI_SUBD_DO;
1324         s->subdev_flags = SDF_WRITABLE;
1325         s->n_chan       = (board->id == DAS1800_ID_HC) ? 8 : 4;
1326         s->maxdata      = 1;
1327         s->range_table  = &range_digital;
1328         s->insn_bits    = das1800_do_insn_bits;
1329 
1330         das1800_ai_cancel(dev, dev->read_subdev);
1331 
1332         /*  initialize digital out channels */
1333         outb(0, dev->iobase + DAS1800_DIGITAL);
1334 
1335         return 0;
1336 };
1337 
1338 static void das1800_detach(struct comedi_device *dev)
1339 {
1340         struct das1800_private *devpriv = dev->private;
1341 
1342         das1800_free_dma(dev);
1343         if (devpriv) {
1344                 kfree(devpriv->fifo_buf);
1345                 if (devpriv->iobase2)
1346                         release_region(devpriv->iobase2, DAS1800_SIZE);
1347         }
1348         comedi_legacy_detach(dev);
1349 }
1350 
1351 static struct comedi_driver das1800_driver = {
1352         .driver_name    = "das1800",
1353         .module         = THIS_MODULE,
1354         .attach         = das1800_attach,
1355         .detach         = das1800_detach,
1356         .num_names      = ARRAY_SIZE(das1800_boards),
1357         .board_name     = &das1800_boards[0].name,
1358         .offset         = sizeof(struct das1800_board),
1359 };
1360 module_comedi_driver(das1800_driver);
1361 
1362 MODULE_AUTHOR("Comedi http://www.comedi.org");
1363 MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards");
1364 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */