root/drivers/staging/comedi/drivers/das16.c

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

DEFINITIONS

This source file includes following definitions.
  1. timer_period
  2. das16_ai_setup_dma
  3. das16_interrupt
  4. das16_timer_interrupt
  5. das16_ai_set_mux_range
  6. das16_ai_check_chanlist
  7. das16_cmd_test
  8. das16_set_pacer
  9. das16_cmd_exec
  10. das16_cancel
  11. das16_ai_munge
  12. das16_ai_eoc
  13. das16_ai_insn_read
  14. das16_ao_insn_write
  15. das16_di_insn_bits
  16. das16_do_insn_bits
  17. das16_probe
  18. das16_reset
  19. das16_alloc_dma
  20. das16_free_dma
  21. das16_ai_range
  22. das16_ao_range
  23. das16_attach
  24. das16_detach

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * das16.c
   4  * DAS16 driver
   5  *
   6  * COMEDI - Linux Control and Measurement Device Interface
   7  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   8  * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
   9  * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
  10  */
  11 
  12 /*
  13  * Driver: das16
  14  * Description: DAS16 compatible boards
  15  * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
  16  * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
  17  *   DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
  18  *   DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
  19  *   DAS-1602 (das-1602),
  20  *   [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
  21  *   PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16),
  22  *   CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr),
  23  *   CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12),
  24  *   CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
  25  *   CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
  26  *   CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
  27  * Status: works
  28  * Updated: 2003-10-12
  29  *
  30  * A rewrite of the das16 and das1600 drivers.
  31  *
  32  * Options:
  33  *      [0] - base io address
  34  *      [1] - irq (does nothing, irq is not used anymore)
  35  *      [2] - dma channel (optional, required for comedi_command support)
  36  *      [3] - master clock speed in MHz (optional, 1 or 10, ignored if
  37  *              board can probe clock, defaults to 1)
  38  *      [4] - analog input range lowest voltage in microvolts (optional,
  39  *              only useful if your board does not have software
  40  *              programmable gain)
  41  *      [5] - analog input range highest voltage in microvolts (optional,
  42  *              only useful if board does not have software programmable
  43  *              gain)
  44  *      [6] - analog output range lowest voltage in microvolts (optional)
  45  *      [7] - analog output range highest voltage in microvolts (optional)
  46  *
  47  * Passing a zero for an option is the same as leaving it unspecified.
  48  */
  49 
  50 /*
  51  * Testing and debugging help provided by Daniel Koch.
  52  *
  53  * Keithley Manuals:
  54  *      2309.PDF (das16)
  55  *      4919.PDF (das1400, 1600)
  56  *      4922.PDF (das-1400)
  57  *      4923.PDF (das1200, 1400, 1600)
  58  *
  59  * Computer boards manuals also available from their website
  60  * www.measurementcomputing.com
  61  */
  62 
  63 #include <linux/module.h>
  64 #include <linux/slab.h>
  65 #include <linux/interrupt.h>
  66 
  67 #include "../comedidev.h"
  68 
  69 #include "comedi_isadma.h"
  70 #include "comedi_8254.h"
  71 #include "8255.h"
  72 
  73 #define DAS16_DMA_SIZE 0xff00   /*  size in bytes of allocated dma buffer */
  74 
  75 /*
  76  * Register I/O map
  77  */
  78 #define DAS16_TRIG_REG                  0x00
  79 #define DAS16_AI_LSB_REG                0x00
  80 #define DAS16_AI_MSB_REG                0x01
  81 #define DAS16_MUX_REG                   0x02
  82 #define DAS16_DIO_REG                   0x03
  83 #define DAS16_AO_LSB_REG(x)             ((x) ? 0x06 : 0x04)
  84 #define DAS16_AO_MSB_REG(x)             ((x) ? 0x07 : 0x05)
  85 #define DAS16_STATUS_REG                0x08
  86 #define DAS16_STATUS_BUSY               BIT(7)
  87 #define DAS16_STATUS_UNIPOLAR           BIT(6)
  88 #define DAS16_STATUS_MUXBIT             BIT(5)
  89 #define DAS16_STATUS_INT                BIT(4)
  90 #define DAS16_CTRL_REG                  0x09
  91 #define DAS16_CTRL_INTE                 BIT(7)
  92 #define DAS16_CTRL_IRQ(x)               (((x) & 0x7) << 4)
  93 #define DAS16_CTRL_DMAE                 BIT(2)
  94 #define DAS16_CTRL_PACING_MASK          (3 << 0)
  95 #define DAS16_CTRL_INT_PACER            (3 << 0)
  96 #define DAS16_CTRL_EXT_PACER            (2 << 0)
  97 #define DAS16_CTRL_SOFT_PACER           (0 << 0)
  98 #define DAS16_PACER_REG                 0x0a
  99 #define DAS16_PACER_BURST_LEN(x)        (((x) & 0xf) << 4)
 100 #define DAS16_PACER_CTR0                BIT(1)
 101 #define DAS16_PACER_TRIG0               BIT(0)
 102 #define DAS16_GAIN_REG                  0x0b
 103 #define DAS16_TIMER_BASE_REG            0x0c    /* to 0x0f */
 104 
 105 #define DAS1600_CONV_REG                0x404
 106 #define DAS1600_CONV_DISABLE            BIT(6)
 107 #define DAS1600_BURST_REG               0x405
 108 #define DAS1600_BURST_VAL               BIT(6)
 109 #define DAS1600_ENABLE_REG              0x406
 110 #define DAS1600_ENABLE_VAL              BIT(6)
 111 #define DAS1600_STATUS_REG              0x407
 112 #define DAS1600_STATUS_BME              BIT(6)
 113 #define DAS1600_STATUS_ME               BIT(5)
 114 #define DAS1600_STATUS_CD               BIT(4)
 115 #define DAS1600_STATUS_WS               BIT(1)
 116 #define DAS1600_STATUS_CLK_10MHZ        BIT(0)
 117 
 118 static const struct comedi_lrange range_das1x01_bip = {
 119         4, {
 120                 BIP_RANGE(10),
 121                 BIP_RANGE(1),
 122                 BIP_RANGE(0.1),
 123                 BIP_RANGE(0.01)
 124         }
 125 };
 126 
 127 static const struct comedi_lrange range_das1x01_unip = {
 128         4, {
 129                 UNI_RANGE(10),
 130                 UNI_RANGE(1),
 131                 UNI_RANGE(0.1),
 132                 UNI_RANGE(0.01)
 133         }
 134 };
 135 
 136 static const struct comedi_lrange range_das1x02_bip = {
 137         4, {
 138                 BIP_RANGE(10),
 139                 BIP_RANGE(5),
 140                 BIP_RANGE(2.5),
 141                 BIP_RANGE(1.25)
 142         }
 143 };
 144 
 145 static const struct comedi_lrange range_das1x02_unip = {
 146         4, {
 147                 UNI_RANGE(10),
 148                 UNI_RANGE(5),
 149                 UNI_RANGE(2.5),
 150                 UNI_RANGE(1.25)
 151         }
 152 };
 153 
 154 static const struct comedi_lrange range_das16jr = {
 155         9, {
 156                 BIP_RANGE(10),
 157                 BIP_RANGE(5),
 158                 BIP_RANGE(2.5),
 159                 BIP_RANGE(1.25),
 160                 BIP_RANGE(0.625),
 161                 UNI_RANGE(10),
 162                 UNI_RANGE(5),
 163                 UNI_RANGE(2.5),
 164                 UNI_RANGE(1.25)
 165         }
 166 };
 167 
 168 static const struct comedi_lrange range_das16jr_16 = {
 169         8, {
 170                 BIP_RANGE(10),
 171                 BIP_RANGE(5),
 172                 BIP_RANGE(2.5),
 173                 BIP_RANGE(1.25),
 174                 UNI_RANGE(10),
 175                 UNI_RANGE(5),
 176                 UNI_RANGE(2.5),
 177                 UNI_RANGE(1.25)
 178         }
 179 };
 180 
 181 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
 182 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
 183 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
 184 
 185 enum {
 186         das16_pg_none = 0,
 187         das16_pg_16jr,
 188         das16_pg_16jr_16,
 189         das16_pg_1601,
 190         das16_pg_1602,
 191 };
 192 
 193 static const int *const das16_gainlists[] = {
 194         NULL,
 195         das16jr_gainlist,
 196         das16jr_16_gainlist,
 197         das1600_gainlist,
 198         das1600_gainlist,
 199 };
 200 
 201 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
 202         &range_unknown,
 203         &range_das16jr,
 204         &range_das16jr_16,
 205         &range_das1x01_unip,
 206         &range_das1x02_unip,
 207 };
 208 
 209 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
 210         &range_unknown,
 211         &range_das16jr,
 212         &range_das16jr_16,
 213         &range_das1x01_bip,
 214         &range_das1x02_bip,
 215 };
 216 
 217 struct das16_board {
 218         const char *name;
 219         unsigned int ai_maxdata;
 220         unsigned int ai_speed;  /*  max conversion speed in nanosec */
 221         unsigned int ai_pg;
 222         unsigned int has_ao:1;
 223         unsigned int has_8255:1;
 224 
 225         unsigned int i8255_offset;
 226 
 227         unsigned int size;
 228         unsigned int id;
 229 };
 230 
 231 static const struct das16_board das16_boards[] = {
 232         {
 233                 .name           = "das-16",
 234                 .ai_maxdata     = 0x0fff,
 235                 .ai_speed       = 15000,
 236                 .ai_pg          = das16_pg_none,
 237                 .has_ao         = 1,
 238                 .has_8255       = 1,
 239                 .i8255_offset   = 0x10,
 240                 .size           = 0x14,
 241                 .id             = 0x00,
 242         }, {
 243                 .name           = "das-16g",
 244                 .ai_maxdata     = 0x0fff,
 245                 .ai_speed       = 15000,
 246                 .ai_pg          = das16_pg_none,
 247                 .has_ao         = 1,
 248                 .has_8255       = 1,
 249                 .i8255_offset   = 0x10,
 250                 .size           = 0x14,
 251                 .id             = 0x00,
 252         }, {
 253                 .name           = "das-16f",
 254                 .ai_maxdata     = 0x0fff,
 255                 .ai_speed       = 8500,
 256                 .ai_pg          = das16_pg_none,
 257                 .has_ao         = 1,
 258                 .has_8255       = 1,
 259                 .i8255_offset   = 0x10,
 260                 .size           = 0x14,
 261                 .id             = 0x00,
 262         }, {
 263                 .name           = "cio-das16",
 264                 .ai_maxdata     = 0x0fff,
 265                 .ai_speed       = 20000,
 266                 .ai_pg          = das16_pg_none,
 267                 .has_ao         = 1,
 268                 .has_8255       = 1,
 269                 .i8255_offset   = 0x10,
 270                 .size           = 0x14,
 271                 .id             = 0x80,
 272         }, {
 273                 .name           = "cio-das16/f",
 274                 .ai_maxdata     = 0x0fff,
 275                 .ai_speed       = 10000,
 276                 .ai_pg          = das16_pg_none,
 277                 .has_ao         = 1,
 278                 .has_8255       = 1,
 279                 .i8255_offset   = 0x10,
 280                 .size           = 0x14,
 281                 .id             = 0x80,
 282         }, {
 283                 .name           = "cio-das16/jr",
 284                 .ai_maxdata     = 0x0fff,
 285                 .ai_speed       = 7692,
 286                 .ai_pg          = das16_pg_16jr,
 287                 .size           = 0x10,
 288                 .id             = 0x00,
 289         }, {
 290                 .name           = "pc104-das16jr",
 291                 .ai_maxdata     = 0x0fff,
 292                 .ai_speed       = 3300,
 293                 .ai_pg          = das16_pg_16jr,
 294                 .size           = 0x10,
 295                 .id             = 0x00,
 296         }, {
 297                 .name           = "cio-das16jr/16",
 298                 .ai_maxdata     = 0xffff,
 299                 .ai_speed       = 10000,
 300                 .ai_pg          = das16_pg_16jr_16,
 301                 .size           = 0x10,
 302                 .id             = 0x00,
 303         }, {
 304                 .name           = "pc104-das16jr/16",
 305                 .ai_maxdata     = 0xffff,
 306                 .ai_speed       = 10000,
 307                 .ai_pg          = das16_pg_16jr_16,
 308                 .size           = 0x10,
 309                 .id             = 0x00,
 310         }, {
 311                 .name           = "das-1201",
 312                 .ai_maxdata     = 0x0fff,
 313                 .ai_speed       = 20000,
 314                 .ai_pg          = das16_pg_none,
 315                 .has_8255       = 1,
 316                 .i8255_offset   = 0x400,
 317                 .size           = 0x408,
 318                 .id             = 0x20,
 319         }, {
 320                 .name           = "das-1202",
 321                 .ai_maxdata     = 0x0fff,
 322                 .ai_speed       = 10000,
 323                 .ai_pg          = das16_pg_none,
 324                 .has_8255       = 1,
 325                 .i8255_offset   = 0x400,
 326                 .size           = 0x408,
 327                 .id             = 0x20,
 328         }, {
 329                 .name           = "das-1401",
 330                 .ai_maxdata     = 0x0fff,
 331                 .ai_speed       = 10000,
 332                 .ai_pg          = das16_pg_1601,
 333                 .size           = 0x408,
 334                 .id             = 0xc0,
 335         }, {
 336                 .name           = "das-1402",
 337                 .ai_maxdata     = 0x0fff,
 338                 .ai_speed       = 10000,
 339                 .ai_pg          = das16_pg_1602,
 340                 .size           = 0x408,
 341                 .id             = 0xc0,
 342         }, {
 343                 .name           = "das-1601",
 344                 .ai_maxdata     = 0x0fff,
 345                 .ai_speed       = 10000,
 346                 .ai_pg          = das16_pg_1601,
 347                 .has_ao         = 1,
 348                 .has_8255       = 1,
 349                 .i8255_offset   = 0x400,
 350                 .size           = 0x408,
 351                 .id             = 0xc0,
 352         }, {
 353                 .name           = "das-1602",
 354                 .ai_maxdata     = 0x0fff,
 355                 .ai_speed       = 10000,
 356                 .ai_pg          = das16_pg_1602,
 357                 .has_ao         = 1,
 358                 .has_8255       = 1,
 359                 .i8255_offset   = 0x400,
 360                 .size           = 0x408,
 361                 .id             = 0xc0,
 362         }, {
 363                 .name           = "cio-das1401/12",
 364                 .ai_maxdata     = 0x0fff,
 365                 .ai_speed       = 6250,
 366                 .ai_pg          = das16_pg_1601,
 367                 .size           = 0x408,
 368                 .id             = 0xc0,
 369         }, {
 370                 .name           = "cio-das1402/12",
 371                 .ai_maxdata     = 0x0fff,
 372                 .ai_speed       = 6250,
 373                 .ai_pg          = das16_pg_1602,
 374                 .size           = 0x408,
 375                 .id             = 0xc0,
 376         }, {
 377                 .name           = "cio-das1402/16",
 378                 .ai_maxdata     = 0xffff,
 379                 .ai_speed       = 10000,
 380                 .ai_pg          = das16_pg_1602,
 381                 .size           = 0x408,
 382                 .id             = 0xc0,
 383         }, {
 384                 .name           = "cio-das1601/12",
 385                 .ai_maxdata     = 0x0fff,
 386                 .ai_speed       = 6250,
 387                 .ai_pg          = das16_pg_1601,
 388                 .has_ao         = 1,
 389                 .has_8255       = 1,
 390                 .i8255_offset   = 0x400,
 391                 .size           = 0x408,
 392                 .id             = 0xc0,
 393         }, {
 394                 .name           = "cio-das1602/12",
 395                 .ai_maxdata     = 0x0fff,
 396                 .ai_speed       = 10000,
 397                 .ai_pg          = das16_pg_1602,
 398                 .has_ao         = 1,
 399                 .has_8255       = 1,
 400                 .i8255_offset   = 0x400,
 401                 .size           = 0x408,
 402                 .id             = 0xc0,
 403         }, {
 404                 .name           = "cio-das1602/16",
 405                 .ai_maxdata     = 0xffff,
 406                 .ai_speed       = 10000,
 407                 .ai_pg          = das16_pg_1602,
 408                 .has_ao         = 1,
 409                 .has_8255       = 1,
 410                 .i8255_offset   = 0x400,
 411                 .size           = 0x408,
 412                 .id             = 0xc0,
 413         }, {
 414                 .name           = "cio-das16/330",
 415                 .ai_maxdata     = 0x0fff,
 416                 .ai_speed       = 3030,
 417                 .ai_pg          = das16_pg_16jr,
 418                 .size           = 0x14,
 419                 .id             = 0xf0,
 420         },
 421 };
 422 
 423 /*
 424  * Period for timer interrupt in jiffies.  It's a function
 425  * to deal with possibility of dynamic HZ patches
 426  */
 427 static inline int timer_period(void)
 428 {
 429         return HZ / 20;
 430 }
 431 
 432 struct das16_private_struct {
 433         struct comedi_isadma    *dma;
 434         struct comedi_device    *dev;
 435         unsigned int            clockbase;
 436         unsigned int            ctrl_reg;
 437         unsigned int            divisor1;
 438         unsigned int            divisor2;
 439         struct timer_list       timer;
 440         unsigned long           extra_iobase;
 441         unsigned int            can_burst:1;
 442         unsigned int            timer_running:1;
 443 };
 444 
 445 static void das16_ai_setup_dma(struct comedi_device *dev,
 446                                struct comedi_subdevice *s,
 447                                unsigned int unread_samples)
 448 {
 449         struct das16_private_struct *devpriv = dev->private;
 450         struct comedi_isadma *dma = devpriv->dma;
 451         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 452         unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize);
 453         unsigned int nsamples;
 454 
 455         /*
 456          * Determine dma size based on the buffer size plus the number of
 457          * unread samples and the number of samples remaining in the command.
 458          */
 459         nsamples = comedi_nsamples_left(s, max_samples + unread_samples);
 460         if (nsamples > unread_samples) {
 461                 nsamples -= unread_samples;
 462                 desc->size = comedi_samples_to_bytes(s, nsamples);
 463                 comedi_isadma_program(desc);
 464         }
 465 }
 466 
 467 static void das16_interrupt(struct comedi_device *dev)
 468 {
 469         struct das16_private_struct *devpriv = dev->private;
 470         struct comedi_subdevice *s = dev->read_subdev;
 471         struct comedi_async *async = s->async;
 472         struct comedi_cmd *cmd = &async->cmd;
 473         struct comedi_isadma *dma = devpriv->dma;
 474         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
 475         unsigned long spin_flags;
 476         unsigned int residue;
 477         unsigned int nbytes;
 478         unsigned int nsamples;
 479 
 480         spin_lock_irqsave(&dev->spinlock, spin_flags);
 481         if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
 482                 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 483                 return;
 484         }
 485 
 486         /*
 487          * The pc104-das16jr (at least) has problems if the dma
 488          * transfer is interrupted in the middle of transferring
 489          * a 16 bit sample.
 490          */
 491         residue = comedi_isadma_disable_on_sample(desc->chan,
 492                                                   comedi_bytes_per_sample(s));
 493 
 494         /* figure out how many samples to read */
 495         if (residue > desc->size) {
 496                 dev_err(dev->class_dev, "residue > transfer size!\n");
 497                 async->events |= COMEDI_CB_ERROR;
 498                 nbytes = 0;
 499         } else {
 500                 nbytes = desc->size - residue;
 501         }
 502         nsamples = comedi_bytes_to_samples(s, nbytes);
 503 
 504         /* restart DMA if more samples are needed */
 505         if (nsamples) {
 506                 dma->cur_dma = 1 - dma->cur_dma;
 507                 das16_ai_setup_dma(dev, s, nsamples);
 508         }
 509 
 510         spin_unlock_irqrestore(&dev->spinlock, spin_flags);
 511 
 512         comedi_buf_write_samples(s, desc->virt_addr, nsamples);
 513 
 514         if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
 515                 async->events |= COMEDI_CB_EOA;
 516 
 517         comedi_handle_events(dev, s);
 518 }
 519 
 520 static void das16_timer_interrupt(struct timer_list *t)
 521 {
 522         struct das16_private_struct *devpriv = from_timer(devpriv, t, timer);
 523         struct comedi_device *dev = devpriv->dev;
 524         unsigned long flags;
 525 
 526         das16_interrupt(dev);
 527 
 528         spin_lock_irqsave(&dev->spinlock, flags);
 529         if (devpriv->timer_running)
 530                 mod_timer(&devpriv->timer, jiffies + timer_period());
 531         spin_unlock_irqrestore(&dev->spinlock, flags);
 532 }
 533 
 534 static void das16_ai_set_mux_range(struct comedi_device *dev,
 535                                    unsigned int first_chan,
 536                                    unsigned int last_chan,
 537                                    unsigned int range)
 538 {
 539         const struct das16_board *board = dev->board_ptr;
 540 
 541         /* set multiplexer */
 542         outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG);
 543 
 544         /* some boards do not have programmable gain */
 545         if (board->ai_pg == das16_pg_none)
 546                 return;
 547 
 548         /*
 549          * Set gain (this is also burst rate register but according to
 550          * computer boards manual, burst rate does nothing, even on
 551          * keithley cards).
 552          */
 553         outb((das16_gainlists[board->ai_pg])[range],
 554              dev->iobase + DAS16_GAIN_REG);
 555 }
 556 
 557 static int das16_ai_check_chanlist(struct comedi_device *dev,
 558                                    struct comedi_subdevice *s,
 559                                    struct comedi_cmd *cmd)
 560 {
 561         unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
 562         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
 563         int i;
 564 
 565         for (i = 1; i < cmd->chanlist_len; i++) {
 566                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 567                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
 568 
 569                 if (chan != ((chan0 + i) % s->n_chan)) {
 570                         dev_dbg(dev->class_dev,
 571                                 "entries in chanlist must be consecutive channels, counting upwards\n");
 572                         return -EINVAL;
 573                 }
 574 
 575                 if (range != range0) {
 576                         dev_dbg(dev->class_dev,
 577                                 "entries in chanlist must all have the same gain\n");
 578                         return -EINVAL;
 579                 }
 580         }
 581 
 582         return 0;
 583 }
 584 
 585 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
 586                           struct comedi_cmd *cmd)
 587 {
 588         const struct das16_board *board = dev->board_ptr;
 589         struct das16_private_struct *devpriv = dev->private;
 590         int err = 0;
 591         unsigned int trig_mask;
 592         unsigned int arg;
 593 
 594         /* Step 1 : check if triggers are trivially valid */
 595 
 596         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
 597 
 598         trig_mask = TRIG_FOLLOW;
 599         if (devpriv->can_burst)
 600                 trig_mask |= TRIG_TIMER | TRIG_EXT;
 601         err |= comedi_check_trigger_src(&cmd->scan_begin_src, trig_mask);
 602 
 603         trig_mask = TRIG_TIMER | TRIG_EXT;
 604         if (devpriv->can_burst)
 605                 trig_mask |= TRIG_NOW;
 606         err |= comedi_check_trigger_src(&cmd->convert_src, trig_mask);
 607 
 608         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 609         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
 610 
 611         if (err)
 612                 return 1;
 613 
 614         /* Step 2a : make sure trigger sources are unique */
 615 
 616         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 617         err |= comedi_check_trigger_is_unique(cmd->convert_src);
 618         err |= comedi_check_trigger_is_unique(cmd->stop_src);
 619 
 620         /* Step 2b : and mutually compatible */
 621 
 622         /*  make sure scan_begin_src and convert_src don't conflict */
 623         if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
 624                 err |= -EINVAL;
 625         if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
 626                 err |= -EINVAL;
 627 
 628         if (err)
 629                 return 2;
 630 
 631         /* Step 3: check if arguments are trivially valid */
 632 
 633         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 634 
 635         if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
 636                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
 637 
 638         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 639                                            cmd->chanlist_len);
 640 
 641         /* check against maximum frequency */
 642         if (cmd->scan_begin_src == TRIG_TIMER) {
 643                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
 644                                                     board->ai_speed *
 645                                                     cmd->chanlist_len);
 646         }
 647 
 648         if (cmd->convert_src == TRIG_TIMER) {
 649                 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
 650                                                     board->ai_speed);
 651         }
 652 
 653         if (cmd->stop_src == TRIG_COUNT)
 654                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 655         else    /* TRIG_NONE */
 656                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 657 
 658         if (err)
 659                 return 3;
 660 
 661         /*  step 4: fix up arguments */
 662         if (cmd->scan_begin_src == TRIG_TIMER) {
 663                 arg = cmd->scan_begin_arg;
 664                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 665                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 666         }
 667         if (cmd->convert_src == TRIG_TIMER) {
 668                 arg = cmd->convert_arg;
 669                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 670                 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
 671         }
 672         if (err)
 673                 return 4;
 674 
 675         /* Step 5: check channel list if it exists */
 676         if (cmd->chanlist && cmd->chanlist_len > 0)
 677                 err |= das16_ai_check_chanlist(dev, s, cmd);
 678 
 679         if (err)
 680                 return 5;
 681 
 682         return 0;
 683 }
 684 
 685 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
 686                                     unsigned int flags)
 687 {
 688         comedi_8254_cascade_ns_to_timer(dev->pacer, &ns, flags);
 689         comedi_8254_update_divisors(dev->pacer);
 690         comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
 691 
 692         return ns;
 693 }
 694 
 695 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
 696 {
 697         struct das16_private_struct *devpriv = dev->private;
 698         struct comedi_isadma *dma = devpriv->dma;
 699         struct comedi_async *async = s->async;
 700         struct comedi_cmd *cmd = &async->cmd;
 701         unsigned int first_chan = CR_CHAN(cmd->chanlist[0]);
 702         unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
 703         unsigned int range = CR_RANGE(cmd->chanlist[0]);
 704         unsigned int byte;
 705         unsigned long flags;
 706 
 707         if (cmd->flags & CMDF_PRIORITY) {
 708                 dev_err(dev->class_dev,
 709                         "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
 710                 return -1;
 711         }
 712 
 713         if (devpriv->can_burst)
 714                 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
 715 
 716         /* set mux and range for chanlist scan */
 717         das16_ai_set_mux_range(dev, first_chan, last_chan, range);
 718 
 719         /* set counter mode and counts */
 720         cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
 721 
 722         /* enable counters */
 723         byte = 0;
 724         if (devpriv->can_burst) {
 725                 if (cmd->convert_src == TRIG_NOW) {
 726                         outb(DAS1600_BURST_VAL,
 727                              dev->iobase + DAS1600_BURST_REG);
 728                         /*  set burst length */
 729                         byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
 730                 } else {
 731                         outb(0, dev->iobase + DAS1600_BURST_REG);
 732                 }
 733         }
 734         outb(byte, dev->iobase + DAS16_PACER_REG);
 735 
 736         /* set up dma transfer */
 737         dma->cur_dma = 0;
 738         das16_ai_setup_dma(dev, s, 0);
 739 
 740         /*  set up timer */
 741         spin_lock_irqsave(&dev->spinlock, flags);
 742         devpriv->timer_running = 1;
 743         devpriv->timer.expires = jiffies + timer_period();
 744         add_timer(&devpriv->timer);
 745 
 746         /* enable DMA interrupt with external or internal pacing */
 747         devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK);
 748         devpriv->ctrl_reg |= DAS16_CTRL_DMAE;
 749         if (cmd->convert_src == TRIG_EXT)
 750                 devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
 751         else
 752                 devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
 753         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
 754 
 755         if (devpriv->can_burst)
 756                 outb(0, dev->iobase + DAS1600_CONV_REG);
 757         spin_unlock_irqrestore(&dev->spinlock, flags);
 758 
 759         return 0;
 760 }
 761 
 762 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
 763 {
 764         struct das16_private_struct *devpriv = dev->private;
 765         struct comedi_isadma *dma = devpriv->dma;
 766         unsigned long flags;
 767 
 768         spin_lock_irqsave(&dev->spinlock, flags);
 769 
 770         /* disable interrupts, dma and pacer clocked conversions */
 771         devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE |
 772                                DAS16_CTRL_PACING_MASK);
 773         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
 774 
 775         comedi_isadma_disable(dma->chan);
 776 
 777         /*  disable SW timer */
 778         if (devpriv->timer_running) {
 779                 devpriv->timer_running = 0;
 780                 del_timer(&devpriv->timer);
 781         }
 782 
 783         if (devpriv->can_burst)
 784                 outb(0, dev->iobase + DAS1600_BURST_REG);
 785 
 786         spin_unlock_irqrestore(&dev->spinlock, flags);
 787 
 788         return 0;
 789 }
 790 
 791 static void das16_ai_munge(struct comedi_device *dev,
 792                            struct comedi_subdevice *s, void *array,
 793                            unsigned int num_bytes,
 794                            unsigned int start_chan_index)
 795 {
 796         unsigned short *data = array;
 797         unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
 798         unsigned int i;
 799         __le16 *buf = array;
 800 
 801         for (i = 0; i < num_samples; i++) {
 802                 data[i] = le16_to_cpu(buf[i]);
 803                 if (s->maxdata == 0x0fff)
 804                         data[i] >>= 4;
 805                 data[i] &= s->maxdata;
 806         }
 807 }
 808 
 809 static int das16_ai_eoc(struct comedi_device *dev,
 810                         struct comedi_subdevice *s,
 811                         struct comedi_insn *insn,
 812                         unsigned long context)
 813 {
 814         unsigned int status;
 815 
 816         status = inb(dev->iobase + DAS16_STATUS_REG);
 817         if ((status & DAS16_STATUS_BUSY) == 0)
 818                 return 0;
 819         return -EBUSY;
 820 }
 821 
 822 static int das16_ai_insn_read(struct comedi_device *dev,
 823                               struct comedi_subdevice *s,
 824                               struct comedi_insn *insn,
 825                               unsigned int *data)
 826 {
 827         unsigned int chan = CR_CHAN(insn->chanspec);
 828         unsigned int range = CR_RANGE(insn->chanspec);
 829         unsigned int val;
 830         int ret;
 831         int i;
 832 
 833         /* set mux and range for single channel */
 834         das16_ai_set_mux_range(dev, chan, chan, range);
 835 
 836         for (i = 0; i < insn->n; i++) {
 837                 /* trigger conversion */
 838                 outb_p(0, dev->iobase + DAS16_TRIG_REG);
 839 
 840                 ret = comedi_timeout(dev, s, insn, das16_ai_eoc, 0);
 841                 if (ret)
 842                         return ret;
 843 
 844                 val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
 845                 val |= inb(dev->iobase + DAS16_AI_LSB_REG);
 846                 if (s->maxdata == 0x0fff)
 847                         val >>= 4;
 848                 val &= s->maxdata;
 849 
 850                 data[i] = val;
 851         }
 852 
 853         return insn->n;
 854 }
 855 
 856 static int das16_ao_insn_write(struct comedi_device *dev,
 857                                struct comedi_subdevice *s,
 858                                struct comedi_insn *insn,
 859                                unsigned int *data)
 860 {
 861         unsigned int chan = CR_CHAN(insn->chanspec);
 862         int i;
 863 
 864         for (i = 0; i < insn->n; i++) {
 865                 unsigned int val = data[i];
 866 
 867                 s->readback[chan] = val;
 868 
 869                 val <<= 4;
 870 
 871                 outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
 872                 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
 873         }
 874 
 875         return insn->n;
 876 }
 877 
 878 static int das16_di_insn_bits(struct comedi_device *dev,
 879                               struct comedi_subdevice *s,
 880                               struct comedi_insn *insn,
 881                               unsigned int *data)
 882 {
 883         data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
 884 
 885         return insn->n;
 886 }
 887 
 888 static int das16_do_insn_bits(struct comedi_device *dev,
 889                               struct comedi_subdevice *s,
 890                               struct comedi_insn *insn,
 891                               unsigned int *data)
 892 {
 893         if (comedi_dio_update_state(s, data))
 894                 outb(s->state, dev->iobase + DAS16_DIO_REG);
 895 
 896         data[1] = s->state;
 897 
 898         return insn->n;
 899 }
 900 
 901 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
 902 {
 903         const struct das16_board *board = dev->board_ptr;
 904         int diobits;
 905 
 906         /* diobits indicates boards */
 907         diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
 908         if (board->id != diobits) {
 909                 dev_err(dev->class_dev,
 910                         "requested board's id bits are incorrect (0x%x != 0x%x)\n",
 911                         board->id, diobits);
 912                 return -EINVAL;
 913         }
 914 
 915         return 0;
 916 }
 917 
 918 static void das16_reset(struct comedi_device *dev)
 919 {
 920         outb(0, dev->iobase + DAS16_STATUS_REG);
 921         outb(0, dev->iobase + DAS16_CTRL_REG);
 922         outb(0, dev->iobase + DAS16_PACER_REG);
 923 }
 924 
 925 static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
 926 {
 927         struct das16_private_struct *devpriv = dev->private;
 928 
 929         timer_setup(&devpriv->timer, das16_timer_interrupt, 0);
 930 
 931         /* only DMA channels 3 and 1 are valid */
 932         if (!(dma_chan == 1 || dma_chan == 3))
 933                 return;
 934 
 935         /* DMA uses two buffers */
 936         devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan,
 937                                            DAS16_DMA_SIZE, COMEDI_ISADMA_READ);
 938 }
 939 
 940 static void das16_free_dma(struct comedi_device *dev)
 941 {
 942         struct das16_private_struct *devpriv = dev->private;
 943 
 944         if (devpriv) {
 945                 del_timer_sync(&devpriv->timer);
 946                 comedi_isadma_free(devpriv->dma);
 947         }
 948 }
 949 
 950 static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev,
 951                                                   struct comedi_subdevice *s,
 952                                                   struct comedi_devconfig *it,
 953                                                   unsigned int pg_type,
 954                                                   unsigned int status)
 955 {
 956         unsigned int min = it->options[4];
 957         unsigned int max = it->options[5];
 958 
 959         /* get any user-defined input range */
 960         if (pg_type == das16_pg_none && (min || max)) {
 961                 struct comedi_lrange *lrange;
 962                 struct comedi_krange *krange;
 963 
 964                 /* allocate single-range range table */
 965                 lrange = comedi_alloc_spriv(s,
 966                                             sizeof(*lrange) + sizeof(*krange));
 967                 if (!lrange)
 968                         return &range_unknown;
 969 
 970                 /* initialize ai range */
 971                 lrange->length = 1;
 972                 krange = lrange->range;
 973                 krange->min = min;
 974                 krange->max = max;
 975                 krange->flags = UNIT_volt;
 976 
 977                 return lrange;
 978         }
 979 
 980         /* use software programmable range */
 981         if (status & DAS16_STATUS_UNIPOLAR)
 982                 return das16_ai_uni_lranges[pg_type];
 983         return das16_ai_bip_lranges[pg_type];
 984 }
 985 
 986 static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev,
 987                                                   struct comedi_subdevice *s,
 988                                                   struct comedi_devconfig *it)
 989 {
 990         unsigned int min = it->options[6];
 991         unsigned int max = it->options[7];
 992 
 993         /* get any user-defined output range */
 994         if (min || max) {
 995                 struct comedi_lrange *lrange;
 996                 struct comedi_krange *krange;
 997 
 998                 /* allocate single-range range table */
 999                 lrange = comedi_alloc_spriv(s,
1000                                             sizeof(*lrange) + sizeof(*krange));
1001                 if (!lrange)
1002                         return &range_unknown;
1003 
1004                 /* initialize ao range */
1005                 lrange->length = 1;
1006                 krange = lrange->range;
1007                 krange->min = min;
1008                 krange->max = max;
1009                 krange->flags = UNIT_volt;
1010 
1011                 return lrange;
1012         }
1013 
1014         return &range_unknown;
1015 }
1016 
1017 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1018 {
1019         const struct das16_board *board = dev->board_ptr;
1020         struct das16_private_struct *devpriv;
1021         struct comedi_subdevice *s;
1022         unsigned int osc_base;
1023         unsigned int status;
1024         int ret;
1025 
1026         /*  check that clock setting is valid */
1027         if (it->options[3]) {
1028                 if (it->options[3] != 1 && it->options[3] != 10) {
1029                         dev_err(dev->class_dev,
1030                                 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1031                         return -EINVAL;
1032                 }
1033         }
1034 
1035         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1036         if (!devpriv)
1037                 return -ENOMEM;
1038         devpriv->dev = dev;
1039 
1040         if (board->size < 0x400) {
1041                 ret = comedi_request_region(dev, it->options[0], board->size);
1042                 if (ret)
1043                         return ret;
1044         } else {
1045                 ret = comedi_request_region(dev, it->options[0], 0x10);
1046                 if (ret)
1047                         return ret;
1048                 /* Request an additional region for the 8255 */
1049                 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1050                                               board->size & 0x3ff);
1051                 if (ret)
1052                         return ret;
1053                 devpriv->extra_iobase = dev->iobase + 0x400;
1054                 devpriv->can_burst = 1;
1055         }
1056 
1057         /*  probe id bits to make sure they are consistent */
1058         if (das16_probe(dev, it))
1059                 return -EINVAL;
1060 
1061         /*  get master clock speed */
1062         osc_base = I8254_OSC_BASE_1MHZ;
1063         if (devpriv->can_burst) {
1064                 status = inb(dev->iobase + DAS1600_STATUS_REG);
1065                 if (status & DAS1600_STATUS_CLK_10MHZ)
1066                         osc_base = I8254_OSC_BASE_10MHZ;
1067         } else {
1068                 if (it->options[3])
1069                         osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
1070         }
1071 
1072         dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
1073                                       osc_base, I8254_IO8, 0);
1074         if (!dev->pacer)
1075                 return -ENOMEM;
1076 
1077         das16_alloc_dma(dev, it->options[2]);
1078 
1079         ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1080         if (ret)
1081                 return ret;
1082 
1083         status = inb(dev->iobase + DAS16_STATUS_REG);
1084 
1085         /* Analog Input subdevice */
1086         s = &dev->subdevices[0];
1087         s->type         = COMEDI_SUBD_AI;
1088         s->subdev_flags = SDF_READABLE;
1089         if (status & DAS16_STATUS_MUXBIT) {
1090                 s->subdev_flags |= SDF_GROUND;
1091                 s->n_chan       = 16;
1092         } else {
1093                 s->subdev_flags |= SDF_DIFF;
1094                 s->n_chan       = 8;
1095         }
1096         s->len_chanlist = s->n_chan;
1097         s->maxdata      = board->ai_maxdata;
1098         s->range_table  = das16_ai_range(dev, s, it, board->ai_pg, status);
1099         s->insn_read    = das16_ai_insn_read;
1100         if (devpriv->dma) {
1101                 dev->read_subdev = s;
1102                 s->subdev_flags |= SDF_CMD_READ;
1103                 s->do_cmdtest   = das16_cmd_test;
1104                 s->do_cmd       = das16_cmd_exec;
1105                 s->cancel       = das16_cancel;
1106                 s->munge        = das16_ai_munge;
1107         }
1108 
1109         /* Analog Output subdevice */
1110         s = &dev->subdevices[1];
1111         if (board->has_ao) {
1112                 s->type         = COMEDI_SUBD_AO;
1113                 s->subdev_flags = SDF_WRITABLE;
1114                 s->n_chan       = 2;
1115                 s->maxdata      = 0x0fff;
1116                 s->range_table  = das16_ao_range(dev, s, it);
1117                 s->insn_write   = das16_ao_insn_write;
1118 
1119                 ret = comedi_alloc_subdev_readback(s);
1120                 if (ret)
1121                         return ret;
1122         } else {
1123                 s->type         = COMEDI_SUBD_UNUSED;
1124         }
1125 
1126         /* Digital Input subdevice */
1127         s = &dev->subdevices[2];
1128         s->type         = COMEDI_SUBD_DI;
1129         s->subdev_flags = SDF_READABLE;
1130         s->n_chan       = 4;
1131         s->maxdata      = 1;
1132         s->range_table  = &range_digital;
1133         s->insn_bits    = das16_di_insn_bits;
1134 
1135         /* Digital Output subdevice */
1136         s = &dev->subdevices[3];
1137         s->type         = COMEDI_SUBD_DO;
1138         s->subdev_flags = SDF_WRITABLE;
1139         s->n_chan       = 4;
1140         s->maxdata      = 1;
1141         s->range_table  = &range_digital;
1142         s->insn_bits    = das16_do_insn_bits;
1143 
1144         /* initialize digital output lines */
1145         outb(s->state, dev->iobase + DAS16_DIO_REG);
1146 
1147         /* 8255 Digital I/O subdevice */
1148         if (board->has_8255) {
1149                 s = &dev->subdevices[4];
1150                 ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
1151                 if (ret)
1152                         return ret;
1153         }
1154 
1155         das16_reset(dev);
1156         /* set the interrupt level */
1157         devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1158         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1159 
1160         if (devpriv->can_burst) {
1161                 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1162                 outb(0, dev->iobase + DAS1600_CONV_REG);
1163                 outb(0, dev->iobase + DAS1600_BURST_REG);
1164         }
1165 
1166         return 0;
1167 }
1168 
1169 static void das16_detach(struct comedi_device *dev)
1170 {
1171         const struct das16_board *board = dev->board_ptr;
1172         struct das16_private_struct *devpriv = dev->private;
1173 
1174         if (devpriv) {
1175                 if (dev->iobase)
1176                         das16_reset(dev);
1177                 das16_free_dma(dev);
1178 
1179                 if (devpriv->extra_iobase)
1180                         release_region(devpriv->extra_iobase,
1181                                        board->size & 0x3ff);
1182         }
1183 
1184         comedi_legacy_detach(dev);
1185 }
1186 
1187 static struct comedi_driver das16_driver = {
1188         .driver_name    = "das16",
1189         .module         = THIS_MODULE,
1190         .attach         = das16_attach,
1191         .detach         = das16_detach,
1192         .board_name     = &das16_boards[0].name,
1193         .num_names      = ARRAY_SIZE(das16_boards),
1194         .offset         = sizeof(das16_boards[0]),
1195 };
1196 module_comedi_driver(das16_driver);
1197 
1198 MODULE_AUTHOR("Comedi http://www.comedi.org");
1199 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1200 MODULE_LICENSE("GPL");

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