1/* 2 comedi/drivers/das800.c 3 Driver for Keitley das800 series boards and compatibles 4 Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net> 5 6 COMEDI - Linux Control and Measurement Device Interface 7 Copyright (C) 2000 David A. Schleef <ds@schleef.org> 8 9 This program is free software; you can redistribute it and/or modify 10 it under the terms of the GNU General Public License as published by 11 the Free Software Foundation; either version 2 of the License, or 12 (at your option) any later version. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License for more details. 18*/ 19/* 20Driver: das800 21Description: Keithley Metrabyte DAS800 (& compatibles) 22Author: Frank Mori Hess <fmhess@users.sourceforge.net> 23Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801), 24 DAS-802 (das-802), 25 [Measurement Computing] CIO-DAS800 (cio-das800), 26 CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802), 27 CIO-DAS802/16 (cio-das802/16) 28Status: works, cio-das802/16 untested - email me if you have tested it 29 30Configuration options: 31 [0] - I/O port base address 32 [1] - IRQ (optional, required for timed or externally triggered conversions) 33 34Notes: 35 IRQ can be omitted, although the cmd interface will not work without it. 36 37 All entries in the channel/gain list must use the same gain and be 38 consecutive channels counting upwards in channel number (these are 39 hardware limitations.) 40 41 I've never tested the gain setting stuff since I only have a 42 DAS-800 board with fixed gain. 43 44 The cio-das802/16 does not have a fifo-empty status bit! Therefore 45 only fifo-half-full transfers are possible with this card. 46*/ 47/* 48 49cmd triggers supported: 50 start_src: TRIG_NOW | TRIG_EXT 51 scan_begin_src: TRIG_FOLLOW 52 scan_end_src: TRIG_COUNT 53 convert_src: TRIG_TIMER | TRIG_EXT 54 stop_src: TRIG_NONE | TRIG_COUNT 55 56 57*/ 58 59#include <linux/module.h> 60#include <linux/interrupt.h> 61#include "../comedidev.h" 62 63#include <linux/delay.h> 64 65#include "8253.h" 66#include "comedi_fc.h" 67 68#define N_CHAN_AI 8 /* number of analog input channels */ 69 70/* Registers for the das800 */ 71 72#define DAS800_LSB 0 73#define FIFO_EMPTY 0x1 74#define FIFO_OVF 0x2 75#define DAS800_MSB 1 76#define DAS800_CONTROL1 2 77#define CONTROL1_INTE 0x8 78#define DAS800_CONV_CONTROL 2 79#define ITE 0x1 80#define CASC 0x2 81#define DTEN 0x4 82#define IEOC 0x8 83#define EACS 0x10 84#define CONV_HCEN 0x80 85#define DAS800_SCAN_LIMITS 2 86#define DAS800_STATUS 2 87#define IRQ 0x8 88#define BUSY 0x80 89#define DAS800_GAIN 3 90#define CIO_FFOV 0x8 /* cio-das802/16 fifo overflow */ 91#define CIO_ENHF 0x90 /* cio-das802/16 fifo half full int ena */ 92#define CONTROL1 0x80 93#define CONV_CONTROL 0xa0 94#define SCAN_LIMITS 0xc0 95#define ID 0xe0 96#define DAS800_8254 4 97#define DAS800_STATUS2 7 98#define STATUS2_HCEN 0x80 99#define STATUS2_INTE 0X20 100#define DAS800_ID 7 101 102#define DAS802_16_HALF_FIFO_SZ 128 103 104struct das800_board { 105 const char *name; 106 int ai_speed; 107 const struct comedi_lrange *ai_range; 108 int resolution; 109}; 110 111static const struct comedi_lrange range_das801_ai = { 112 9, { 113 BIP_RANGE(5), 114 BIP_RANGE(10), 115 UNI_RANGE(10), 116 BIP_RANGE(0.5), 117 UNI_RANGE(1), 118 BIP_RANGE(0.05), 119 UNI_RANGE(0.1), 120 BIP_RANGE(0.01), 121 UNI_RANGE(0.02) 122 } 123}; 124 125static const struct comedi_lrange range_cio_das801_ai = { 126 9, { 127 BIP_RANGE(5), 128 BIP_RANGE(10), 129 UNI_RANGE(10), 130 BIP_RANGE(0.5), 131 UNI_RANGE(1), 132 BIP_RANGE(0.05), 133 UNI_RANGE(0.1), 134 BIP_RANGE(0.005), 135 UNI_RANGE(0.01) 136 } 137}; 138 139static const struct comedi_lrange range_das802_ai = { 140 9, { 141 BIP_RANGE(5), 142 BIP_RANGE(10), 143 UNI_RANGE(10), 144 BIP_RANGE(2.5), 145 UNI_RANGE(5), 146 BIP_RANGE(1.25), 147 UNI_RANGE(2.5), 148 BIP_RANGE(0.625), 149 UNI_RANGE(1.25) 150 } 151}; 152 153static const struct comedi_lrange range_das80216_ai = { 154 8, { 155 BIP_RANGE(10), 156 UNI_RANGE(10), 157 BIP_RANGE(5), 158 UNI_RANGE(5), 159 BIP_RANGE(2.5), 160 UNI_RANGE(2.5), 161 BIP_RANGE(1.25), 162 UNI_RANGE(1.25) 163 } 164}; 165 166enum das800_boardinfo { 167 BOARD_DAS800, 168 BOARD_CIODAS800, 169 BOARD_DAS801, 170 BOARD_CIODAS801, 171 BOARD_DAS802, 172 BOARD_CIODAS802, 173 BOARD_CIODAS80216, 174}; 175 176static const struct das800_board das800_boards[] = { 177 [BOARD_DAS800] = { 178 .name = "das-800", 179 .ai_speed = 25000, 180 .ai_range = &range_bipolar5, 181 .resolution = 12, 182 }, 183 [BOARD_CIODAS800] = { 184 .name = "cio-das800", 185 .ai_speed = 20000, 186 .ai_range = &range_bipolar5, 187 .resolution = 12, 188 }, 189 [BOARD_DAS801] = { 190 .name = "das-801", 191 .ai_speed = 25000, 192 .ai_range = &range_das801_ai, 193 .resolution = 12, 194 }, 195 [BOARD_CIODAS801] = { 196 .name = "cio-das801", 197 .ai_speed = 20000, 198 .ai_range = &range_cio_das801_ai, 199 .resolution = 12, 200 }, 201 [BOARD_DAS802] = { 202 .name = "das-802", 203 .ai_speed = 25000, 204 .ai_range = &range_das802_ai, 205 .resolution = 12, 206 }, 207 [BOARD_CIODAS802] = { 208 .name = "cio-das802", 209 .ai_speed = 20000, 210 .ai_range = &range_das802_ai, 211 .resolution = 12, 212 }, 213 [BOARD_CIODAS80216] = { 214 .name = "cio-das802/16", 215 .ai_speed = 10000, 216 .ai_range = &range_das80216_ai, 217 .resolution = 16, 218 }, 219}; 220 221struct das800_private { 222 unsigned int count; /* number of data points left to be taken */ 223 unsigned int divisor1; /* counter 1 value for timed conversions */ 224 unsigned int divisor2; /* counter 2 value for timed conversions */ 225 unsigned int do_bits; /* digital output bits */ 226}; 227 228static void das800_ind_write(struct comedi_device *dev, 229 unsigned val, unsigned reg) 230{ 231 /* 232 * Select dev->iobase + 2 to be desired register 233 * then write to that register. 234 */ 235 outb(reg, dev->iobase + DAS800_GAIN); 236 outb(val, dev->iobase + 2); 237} 238 239static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg) 240{ 241 /* 242 * Select dev->iobase + 7 to be desired register 243 * then read from that register. 244 */ 245 outb(reg, dev->iobase + DAS800_GAIN); 246 return inb(dev->iobase + 7); 247} 248 249static void das800_enable(struct comedi_device *dev) 250{ 251 const struct das800_board *thisboard = dev->board_ptr; 252 struct das800_private *devpriv = dev->private; 253 unsigned long irq_flags; 254 255 spin_lock_irqsave(&dev->spinlock, irq_flags); 256 /* enable fifo-half full interrupts for cio-das802/16 */ 257 if (thisboard->resolution == 16) 258 outb(CIO_ENHF, dev->iobase + DAS800_GAIN); 259 /* enable hardware triggering */ 260 das800_ind_write(dev, CONV_HCEN, CONV_CONTROL); 261 /* enable card's interrupt */ 262 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); 263 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 264} 265 266static void das800_disable(struct comedi_device *dev) 267{ 268 unsigned long irq_flags; 269 270 spin_lock_irqsave(&dev->spinlock, irq_flags); 271 /* disable hardware triggering of conversions */ 272 das800_ind_write(dev, 0x0, CONV_CONTROL); 273 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 274} 275 276static void das800_set_frequency(struct comedi_device *dev) 277{ 278 struct das800_private *devpriv = dev->private; 279 unsigned long timer_base = dev->iobase + DAS800_8254; 280 281 i8254_set_mode(timer_base, 0, 1, I8254_MODE2 | I8254_BINARY); 282 i8254_set_mode(timer_base, 0, 2, I8254_MODE2 | I8254_BINARY); 283 i8254_write(timer_base, 0, 1, devpriv->divisor1); 284 i8254_write(timer_base, 0, 2, devpriv->divisor2); 285} 286 287static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 288{ 289 struct das800_private *devpriv = dev->private; 290 291 devpriv->count = 0; 292 das800_disable(dev); 293 return 0; 294} 295 296static int das800_ai_check_chanlist(struct comedi_device *dev, 297 struct comedi_subdevice *s, 298 struct comedi_cmd *cmd) 299{ 300 unsigned int chan0 = CR_CHAN(cmd->chanlist[0]); 301 unsigned int range0 = CR_RANGE(cmd->chanlist[0]); 302 int i; 303 304 for (i = 1; i < cmd->chanlist_len; i++) { 305 unsigned int chan = CR_CHAN(cmd->chanlist[i]); 306 unsigned int range = CR_RANGE(cmd->chanlist[i]); 307 308 if (chan != (chan0 + i) % s->n_chan) { 309 dev_dbg(dev->class_dev, 310 "chanlist must be consecutive, counting upwards\n"); 311 return -EINVAL; 312 } 313 314 if (range != range0) { 315 dev_dbg(dev->class_dev, 316 "chanlist must all have the same gain\n"); 317 return -EINVAL; 318 } 319 } 320 321 return 0; 322} 323 324static int das800_ai_do_cmdtest(struct comedi_device *dev, 325 struct comedi_subdevice *s, 326 struct comedi_cmd *cmd) 327{ 328 const struct das800_board *thisboard = dev->board_ptr; 329 struct das800_private *devpriv = dev->private; 330 int err = 0; 331 unsigned int arg; 332 333 /* Step 1 : check if triggers are trivially valid */ 334 335 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT); 336 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW); 337 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT); 338 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 339 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); 340 341 if (err) 342 return 1; 343 344 /* Step 2a : make sure trigger sources are unique */ 345 346 err |= cfc_check_trigger_is_unique(cmd->start_src); 347 err |= cfc_check_trigger_is_unique(cmd->convert_src); 348 err |= cfc_check_trigger_is_unique(cmd->stop_src); 349 350 /* Step 2b : and mutually compatible */ 351 352 if (err) 353 return 2; 354 355 /* Step 3: check if arguments are trivially valid */ 356 357 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 358 359 if (cmd->convert_src == TRIG_TIMER) 360 err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 361 thisboard->ai_speed); 362 363 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1); 364 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len); 365 366 if (cmd->stop_src == TRIG_COUNT) 367 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); 368 else /* TRIG_NONE */ 369 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 370 371 if (err) 372 return 3; 373 374 /* step 4: fix up any arguments */ 375 376 if (cmd->convert_src == TRIG_TIMER) { 377 arg = cmd->convert_arg; 378 i8253_cascade_ns_to_timer(I8254_OSC_BASE_1MHZ, 379 &devpriv->divisor1, 380 &devpriv->divisor2, 381 &arg, cmd->flags); 382 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg); 383 } 384 385 if (err) 386 return 4; 387 388 /* Step 5: check channel list if it exists */ 389 if (cmd->chanlist && cmd->chanlist_len > 0) 390 err |= das800_ai_check_chanlist(dev, s, cmd); 391 392 if (err) 393 return 5; 394 395 return 0; 396} 397 398static int das800_ai_do_cmd(struct comedi_device *dev, 399 struct comedi_subdevice *s) 400{ 401 const struct das800_board *thisboard = dev->board_ptr; 402 struct das800_private *devpriv = dev->private; 403 struct comedi_async *async = s->async; 404 struct comedi_cmd *cmd = &async->cmd; 405 unsigned int gain = CR_RANGE(cmd->chanlist[0]); 406 unsigned int start_chan = CR_CHAN(cmd->chanlist[0]); 407 unsigned int end_chan = (start_chan + cmd->chanlist_len - 1) % 8; 408 unsigned int scan_chans = (end_chan << 3) | start_chan; 409 int conv_bits; 410 unsigned long irq_flags; 411 412 das800_disable(dev); 413 414 spin_lock_irqsave(&dev->spinlock, irq_flags); 415 /* set scan limits */ 416 das800_ind_write(dev, scan_chans, SCAN_LIMITS); 417 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 418 419 /* set gain */ 420 if (thisboard->resolution == 12 && gain > 0) 421 gain += 0x7; 422 gain &= 0xf; 423 outb(gain, dev->iobase + DAS800_GAIN); 424 425 if (cmd->stop_src == TRIG_COUNT) 426 devpriv->count = cmd->stop_arg * cmd->chanlist_len; 427 else /* TRIG_NONE */ 428 devpriv->count = 0; 429 430 /* enable auto channel scan, send interrupts on end of conversion 431 * and set clock source to internal or external 432 */ 433 conv_bits = 0; 434 conv_bits |= EACS | IEOC; 435 if (cmd->start_src == TRIG_EXT) 436 conv_bits |= DTEN; 437 if (cmd->convert_src == TRIG_TIMER) { 438 conv_bits |= CASC | ITE; 439 /* set conversion frequency */ 440 das800_set_frequency(dev); 441 } 442 443 spin_lock_irqsave(&dev->spinlock, irq_flags); 444 das800_ind_write(dev, conv_bits, CONV_CONTROL); 445 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 446 447 das800_enable(dev); 448 return 0; 449} 450 451static unsigned int das800_ai_get_sample(struct comedi_device *dev) 452{ 453 unsigned int lsb = inb(dev->iobase + DAS800_LSB); 454 unsigned int msb = inb(dev->iobase + DAS800_MSB); 455 456 return (msb << 8) | lsb; 457} 458 459static irqreturn_t das800_interrupt(int irq, void *d) 460{ 461 struct comedi_device *dev = d; 462 struct das800_private *devpriv = dev->private; 463 struct comedi_subdevice *s = dev->read_subdev; 464 struct comedi_async *async; 465 struct comedi_cmd *cmd; 466 unsigned long irq_flags; 467 unsigned int status; 468 unsigned int val; 469 bool fifo_empty; 470 bool fifo_overflow; 471 int i; 472 473 status = inb(dev->iobase + DAS800_STATUS); 474 if (!(status & IRQ)) 475 return IRQ_NONE; 476 if (!dev->attached) 477 return IRQ_HANDLED; 478 479 async = s->async; 480 cmd = &async->cmd; 481 482 spin_lock_irqsave(&dev->spinlock, irq_flags); 483 status = das800_ind_read(dev, CONTROL1) & STATUS2_HCEN; 484 /* 485 * Don't release spinlock yet since we want to make sure 486 * no one else disables hardware conversions. 487 */ 488 489 /* if hardware conversions are not enabled, then quit */ 490 if (status == 0) { 491 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 492 return IRQ_HANDLED; 493 } 494 495 for (i = 0; i < DAS802_16_HALF_FIFO_SZ; i++) { 496 val = das800_ai_get_sample(dev); 497 if (s->maxdata == 0x0fff) { 498 fifo_empty = !!(val & FIFO_EMPTY); 499 fifo_overflow = !!(val & FIFO_OVF); 500 } else { 501 /* cio-das802/16 has no fifo empty status bit */ 502 fifo_empty = false; 503 fifo_overflow = !!(inb(dev->iobase + DAS800_GAIN) & 504 CIO_FFOV); 505 } 506 if (fifo_empty || fifo_overflow) 507 break; 508 509 if (s->maxdata == 0x0fff) 510 val >>= 4; /* 12-bit sample */ 511 512 /* if there are more data points to collect */ 513 if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) { 514 /* write data point to buffer */ 515 cfc_write_to_buffer(s, val & s->maxdata); 516 devpriv->count--; 517 } 518 } 519 async->events |= COMEDI_CB_BLOCK; 520 521 if (fifo_overflow) { 522 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 523 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 524 cfc_handle_events(dev, s); 525 return IRQ_HANDLED; 526 } 527 528 if (cmd->stop_src == TRIG_NONE || devpriv->count > 0) { 529 /* Re-enable card's interrupt. 530 * We already have spinlock, so indirect addressing is safe */ 531 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, 532 CONTROL1); 533 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 534 } else { 535 /* otherwise, stop taking data */ 536 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 537 das800_disable(dev); 538 async->events |= COMEDI_CB_EOA; 539 } 540 cfc_handle_events(dev, s); 541 return IRQ_HANDLED; 542} 543 544static int das800_ai_eoc(struct comedi_device *dev, 545 struct comedi_subdevice *s, 546 struct comedi_insn *insn, 547 unsigned long context) 548{ 549 unsigned int status; 550 551 status = inb(dev->iobase + DAS800_STATUS); 552 if ((status & BUSY) == 0) 553 return 0; 554 return -EBUSY; 555} 556 557static int das800_ai_insn_read(struct comedi_device *dev, 558 struct comedi_subdevice *s, 559 struct comedi_insn *insn, 560 unsigned int *data) 561{ 562 struct das800_private *devpriv = dev->private; 563 unsigned int chan = CR_CHAN(insn->chanspec); 564 unsigned int range = CR_RANGE(insn->chanspec); 565 unsigned long irq_flags; 566 unsigned int val; 567 int ret; 568 int i; 569 570 das800_disable(dev); 571 572 /* set multiplexer */ 573 spin_lock_irqsave(&dev->spinlock, irq_flags); 574 das800_ind_write(dev, chan | devpriv->do_bits, CONTROL1); 575 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 576 577 /* set gain / range */ 578 if (s->maxdata == 0x0fff && range) 579 range += 0x7; 580 range &= 0xf; 581 outb(range, dev->iobase + DAS800_GAIN); 582 583 udelay(5); 584 585 for (i = 0; i < insn->n; i++) { 586 /* trigger conversion */ 587 outb_p(0, dev->iobase + DAS800_MSB); 588 589 ret = comedi_timeout(dev, s, insn, das800_ai_eoc, 0); 590 if (ret) 591 return ret; 592 593 val = das800_ai_get_sample(dev); 594 if (s->maxdata == 0x0fff) 595 val >>= 4; /* 12-bit sample */ 596 data[i] = val & s->maxdata; 597 } 598 599 return insn->n; 600} 601 602static int das800_di_insn_bits(struct comedi_device *dev, 603 struct comedi_subdevice *s, 604 struct comedi_insn *insn, 605 unsigned int *data) 606{ 607 data[1] = (inb(dev->iobase + DAS800_STATUS) >> 4) & 0x7; 608 609 return insn->n; 610} 611 612static int das800_do_insn_bits(struct comedi_device *dev, 613 struct comedi_subdevice *s, 614 struct comedi_insn *insn, 615 unsigned int *data) 616{ 617 struct das800_private *devpriv = dev->private; 618 unsigned long irq_flags; 619 620 if (comedi_dio_update_state(s, data)) { 621 devpriv->do_bits = s->state << 4; 622 623 spin_lock_irqsave(&dev->spinlock, irq_flags); 624 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, 625 CONTROL1); 626 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 627 } 628 629 data[1] = s->state; 630 631 return insn->n; 632} 633 634static int das800_probe(struct comedi_device *dev) 635{ 636 const struct das800_board *thisboard = dev->board_ptr; 637 int board = thisboard ? thisboard - das800_boards : -EINVAL; 638 int id_bits; 639 unsigned long irq_flags; 640 641 spin_lock_irqsave(&dev->spinlock, irq_flags); 642 id_bits = das800_ind_read(dev, ID) & 0x3; 643 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 644 645 switch (id_bits) { 646 case 0x0: 647 if (board == BOARD_DAS800 || board == BOARD_CIODAS800) 648 break; 649 dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n"); 650 board = BOARD_DAS800; 651 break; 652 case 0x2: 653 if (board == BOARD_DAS801 || board == BOARD_CIODAS801) 654 break; 655 dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n"); 656 board = BOARD_DAS801; 657 break; 658 case 0x3: 659 if (board == BOARD_DAS802 || board == BOARD_CIODAS802 || 660 board == BOARD_CIODAS80216) 661 break; 662 dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n"); 663 board = BOARD_DAS802; 664 break; 665 default: 666 dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n", 667 id_bits); 668 board = -EINVAL; 669 break; 670 } 671 return board; 672} 673 674static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it) 675{ 676 const struct das800_board *thisboard; 677 struct das800_private *devpriv; 678 struct comedi_subdevice *s; 679 unsigned int irq = it->options[1]; 680 unsigned long irq_flags; 681 int board; 682 int ret; 683 684 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv)); 685 if (!devpriv) 686 return -ENOMEM; 687 688 ret = comedi_request_region(dev, it->options[0], 0x8); 689 if (ret) 690 return ret; 691 692 board = das800_probe(dev); 693 if (board < 0) { 694 dev_dbg(dev->class_dev, "unable to determine board type\n"); 695 return -ENODEV; 696 } 697 dev->board_ptr = das800_boards + board; 698 thisboard = dev->board_ptr; 699 dev->board_name = thisboard->name; 700 701 if (irq > 1 && irq <= 7) { 702 ret = request_irq(irq, das800_interrupt, 0, dev->board_name, 703 dev); 704 if (ret == 0) 705 dev->irq = irq; 706 } 707 708 ret = comedi_alloc_subdevices(dev, 3); 709 if (ret) 710 return ret; 711 712 /* Analog Input subdevice */ 713 s = &dev->subdevices[0]; 714 dev->read_subdev = s; 715 s->type = COMEDI_SUBD_AI; 716 s->subdev_flags = SDF_READABLE | SDF_GROUND; 717 s->n_chan = 8; 718 s->maxdata = (1 << thisboard->resolution) - 1; 719 s->range_table = thisboard->ai_range; 720 s->insn_read = das800_ai_insn_read; 721 if (dev->irq) { 722 s->subdev_flags |= SDF_CMD_READ; 723 s->len_chanlist = 8; 724 s->do_cmdtest = das800_ai_do_cmdtest; 725 s->do_cmd = das800_ai_do_cmd; 726 s->cancel = das800_cancel; 727 } 728 729 /* Digital Input subdevice */ 730 s = &dev->subdevices[1]; 731 s->type = COMEDI_SUBD_DI; 732 s->subdev_flags = SDF_READABLE; 733 s->n_chan = 3; 734 s->maxdata = 1; 735 s->range_table = &range_digital; 736 s->insn_bits = das800_di_insn_bits; 737 738 /* Digital Output subdevice */ 739 s = &dev->subdevices[2]; 740 s->type = COMEDI_SUBD_DO; 741 s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 742 s->n_chan = 4; 743 s->maxdata = 1; 744 s->range_table = &range_digital; 745 s->insn_bits = das800_do_insn_bits; 746 747 das800_disable(dev); 748 749 /* initialize digital out channels */ 750 spin_lock_irqsave(&dev->spinlock, irq_flags); 751 das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1); 752 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 753 754 return 0; 755}; 756 757static struct comedi_driver driver_das800 = { 758 .driver_name = "das800", 759 .module = THIS_MODULE, 760 .attach = das800_attach, 761 .detach = comedi_legacy_detach, 762 .num_names = ARRAY_SIZE(das800_boards), 763 .board_name = &das800_boards[0].name, 764 .offset = sizeof(struct das800_board), 765}; 766module_comedi_driver(driver_das800); 767 768MODULE_AUTHOR("Comedi http://www.comedi.org"); 769MODULE_DESCRIPTION("Comedi low-level driver"); 770MODULE_LICENSE("GPL"); 771