This source file includes following definitions.
- timer_period
- das16_ai_setup_dma
- das16_interrupt
- das16_timer_interrupt
- das16_ai_set_mux_range
- das16_ai_check_chanlist
- das16_cmd_test
- das16_set_pacer
- das16_cmd_exec
- das16_cancel
- das16_ai_munge
- das16_ai_eoc
- das16_ai_insn_read
- das16_ao_insn_write
- das16_di_insn_bits
- das16_do_insn_bits
- das16_probe
- das16_reset
- das16_alloc_dma
- das16_free_dma
- das16_ai_range
- das16_ao_range
- das16_attach
- das16_detach
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 
  48 
  49 
  50 
  51 
  52 
  53 
  54 
  55 
  56 
  57 
  58 
  59 
  60 
  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   
  74 
  75 
  76 
  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    
 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;  
 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 
 425 
 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 
 457 
 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 
 488 
 489 
 490 
 491         residue = comedi_isadma_disable_on_sample(desc->chan,
 492                                                   comedi_bytes_per_sample(s));
 493 
 494         
 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         
 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         
 542         outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG);
 543 
 544         
 545         if (board->ai_pg == das16_pg_none)
 546                 return;
 547 
 548         
 549 
 550 
 551 
 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         
 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         
 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         
 621 
 622         
 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         
 632 
 633         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 634 
 635         if (cmd->scan_begin_src == TRIG_FOLLOW) 
 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         
 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    
 656                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 657 
 658         if (err)
 659                 return 3;
 660 
 661         
 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         
 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         
 717         das16_ai_set_mux_range(dev, first_chan, last_chan, range);
 718 
 719         
 720         cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
 721 
 722         
 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                         
 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         
 737         dma->cur_dma = 0;
 738         das16_ai_setup_dma(dev, s, 0);
 739 
 740         
 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         
 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         
 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         
 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         
 834         das16_ai_set_mux_range(dev, chan, chan, range);
 835 
 836         for (i = 0; i < insn->n; i++) {
 837                 
 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         
 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         
 932         if (!(dma_chan == 1 || dma_chan == 3))
 933                 return;
 934 
 935         
 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         
 960         if (pg_type == das16_pg_none && (min || max)) {
 961                 struct comedi_lrange *lrange;
 962                 struct comedi_krange *krange;
 963 
 964                 
 965                 lrange = comedi_alloc_spriv(s,
 966                                             sizeof(*lrange) + sizeof(*krange));
 967                 if (!lrange)
 968                         return &range_unknown;
 969 
 970                 
 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         
 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         
 994         if (min || max) {
 995                 struct comedi_lrange *lrange;
 996                 struct comedi_krange *krange;
 997 
 998                 
 999                 lrange = comedi_alloc_spriv(s,
1000                                             sizeof(*lrange) + sizeof(*krange));
1001                 if (!lrange)
1002                         return &range_unknown;
1003 
1004                 
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         
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                 
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         
1058         if (das16_probe(dev, it))
1059                 return -EINVAL;
1060 
1061         
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         
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         
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         
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         
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         
1145         outb(s->state, dev->iobase + DAS16_DIO_REG);
1146 
1147         
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         
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");