das16.c revision 25436dc9d84f1be60ff549c9ab712bba2835f284
1/* 2 comedi/drivers/das16.c 3 DAS16 driver 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 2000 David A. Schleef <ds@schleef.org> 7 Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com> 8 Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net> 9 10 This program is free software; you can redistribute it and/or modify 11 it under the terms of the GNU General Public License as published by 12 the Free Software Foundation; either version 2 of the License, or 13 (at your option) any later version. 14 15 This program is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public License 21 along with this program; if not, write to the Free Software 22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 23 24************************************************************************ 25*/ 26/* 27Driver: das16 28Description: DAS16 compatible boards 29Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze 30Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g), 31 DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202), 32 DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601), 33 DAS-1602 (das-1602), 34 [ComputerBoards] PC104-DAS16/JR (pc104-das16jr), 35 PC104-DAS16JR/16 (pc104-das16jr/16), 36 CIO-DAS16JR/16 (cio-das16jr/16), 37 CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12), 38 CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16), 39 CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12), 40 CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330) 41Status: works 42Updated: 2003-10-12 43 44A rewrite of the das16 and das1600 drivers. 45Options: 46 [0] - base io address 47 [1] - irq (does nothing, irq is not used anymore) 48 [2] - dma (optional, required for comedi_command support) 49 [3] - master clock speed in MHz (optional, 1 or 10, ignored if 50 board can probe clock, defaults to 1) 51 [4] - analog input range lowest voltage in microvolts (optional, 52 only useful if your board does not have software 53 programmable gain) 54 [5] - analog input range highest voltage in microvolts (optional, 55 only useful if board does not have software programmable 56 gain) 57 [6] - analog output range lowest voltage in microvolts (optional) 58 [7] - analog output range highest voltage in microvolts (optional) 59 [8] - use timer mode for DMA. Timer mode is needed e.g. for 60 buggy DMA controllers in NS CS5530A (Geode Companion), and for 61 'jr' cards that lack a hardware fifo. This option is no 62 longer needed, since timer mode is _always_ used. 63 64Passing a zero for an option is the same as leaving it unspecified. 65 66*/ 67/* 68 69Testing and debugging help provided by Daniel Koch. 70 71Keithley Manuals: 72 2309.PDF (das16) 73 4919.PDF (das1400, 1600) 74 4922.PDF (das-1400) 75 4923.PDF (das1200, 1400, 1600) 76 77Computer boards manuals also available from their website www.measurementcomputing.com 78 79*/ 80 81#include <linux/pci.h> 82#include <linux/interrupt.h> 83#include <asm/dma.h> 84#include "../comedidev.h" 85 86#include "8253.h" 87#include "8255.h" 88#include "comedi_fc.h" 89 90#undef DEBUG 91/* #define DEBUG */ 92 93#ifdef DEBUG 94#define DEBUG_PRINT(format, args...) printk("das16: " format, ## args) 95#else 96#define DEBUG_PRINT(format, args...) 97#endif 98 99#define DAS16_SIZE 20 /* number of ioports */ 100#define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */ 101 102/* 103 cio-das16.pdf 104 105 "das16" 106 "das16/f" 107 108 0 a/d bits 0-3 start 12 bit 109 1 a/d bits 4-11 unused 110 2 mux read mux set 111 3 di 4 bit do 4 bit 112 4 unused ao0_lsb 113 5 unused ao0_msb 114 6 unused ao1_lsb 115 7 unused ao1_msb 116 8 status eoc uni/bip interrupt reset 117 9 dma, int, trig ctrl set dma, int 118 a pacer control unused 119 b reserved reserved 120 cdef 8254 121 0123 8255 122 123*/ 124 125/* 126 cio-das16jr.pdf 127 128 "das16jr" 129 130 0 a/d bits 0-3 start 12 bit 131 1 a/d bits 4-11 unused 132 2 mux read mux set 133 3 di 4 bit do 4 bit 134 4567 unused unused 135 8 status eoc uni/bip interrupt reset 136 9 dma, int, trig ctrl set dma, int 137 a pacer control unused 138 b gain status gain control 139 cdef 8254 140 141*/ 142 143/* 144 cio-das16jr_16.pdf 145 146 "das16jr_16" 147 148 0 a/d bits 0-7 start 16 bit 149 1 a/d bits 8-15 unused 150 2 mux read mux set 151 3 di 4 bit do 4 bit 152 4567 unused unused 153 8 status eoc uni/bip interrupt reset 154 9 dma, int, trig ctrl set dma, int 155 a pacer control unused 156 b gain status gain control 157 cdef 8254 158 159*/ 160/* 161 cio-das160x-1x.pdf 162 163 "das1601/12" 164 "das1602/12" 165 "das1602/16" 166 167 0 a/d bits 0-3 start 12 bit 168 1 a/d bits 4-11 unused 169 2 mux read mux set 170 3 di 4 bit do 4 bit 171 4 unused ao0_lsb 172 5 unused ao0_msb 173 6 unused ao1_lsb 174 7 unused ao1_msb 175 8 status eoc uni/bip interrupt reset 176 9 dma, int, trig ctrl set dma, int 177 a pacer control unused 178 b gain status gain control 179 cdef 8254 180 400 8255 181 404 unused conversion enable 182 405 unused burst enable 183 406 unused das1600 enable 184 407 status 185 186*/ 187 188static const int sample_size = 2; /* size in bytes of a sample from board */ 189 190#define DAS16_TRIG 0 191#define DAS16_AI_LSB 0 192#define DAS16_AI_MSB 1 193#define DAS16_MUX 2 194#define DAS16_DIO 3 195#define DAS16_AO_LSB(x) ((x)?6:4) 196#define DAS16_AO_MSB(x) ((x)?7:5) 197#define DAS16_STATUS 8 198#define BUSY (1<<7) 199#define UNIPOLAR (1<<6) 200#define DAS16_MUXBIT (1<<5) 201#define DAS16_INT (1<<4) 202#define DAS16_CONTROL 9 203#define DAS16_INTE (1<<7) 204#define DAS16_IRQ(x) (((x) & 0x7) << 4) 205#define DMA_ENABLE (1<<2) 206#define PACING_MASK 0x3 207#define INT_PACER 0x03 208#define EXT_PACER 0x02 209#define DAS16_SOFT 0x00 210#define DAS16_PACER 0x0A 211#define DAS16_CTR0 (1<<1) 212#define DAS16_TRIG0 (1<<0) 213#define BURST_LEN_BITS(x) (((x) & 0xf) << 4) 214#define DAS16_GAIN 0x0B 215#define DAS16_CNTR0_DATA 0x0C 216#define DAS16_CNTR1_DATA 0x0D 217#define DAS16_CNTR2_DATA 0x0E 218#define DAS16_CNTR_CONTROL 0x0F 219#define DAS16_TERM_CNT 0x00 220#define DAS16_ONE_SHOT 0x02 221#define DAS16_RATE_GEN 0x04 222#define DAS16_CNTR_LSB_MSB 0x30 223#define DAS16_CNTR0 0x00 224#define DAS16_CNTR1 0x40 225#define DAS16_CNTR2 0x80 226 227#define DAS1600_CONV 0x404 228#define DAS1600_CONV_DISABLE 0x40 229#define DAS1600_BURST 0x405 230#define DAS1600_BURST_VAL 0x40 231#define DAS1600_ENABLE 0x406 232#define DAS1600_ENABLE_VAL 0x40 233#define DAS1600_STATUS_B 0x407 234#define DAS1600_BME 0x40 235#define DAS1600_ME 0x20 236#define DAS1600_CD 0x10 237#define DAS1600_WS 0x02 238#define DAS1600_CLK_10MHZ 0x01 239 240static const struct comedi_lrange range_das1x01_bip = { 4, { 241 BIP_RANGE(10), 242 BIP_RANGE(1), 243 BIP_RANGE(0.1), 244 BIP_RANGE(0.01), 245 } 246}; 247static const struct comedi_lrange range_das1x01_unip = { 4, { 248 UNI_RANGE(10), 249 UNI_RANGE(1), 250 UNI_RANGE(0.1), 251 UNI_RANGE(0.01), 252 } 253}; 254static const struct comedi_lrange range_das1x02_bip = { 4, { 255 BIP_RANGE(10), 256 BIP_RANGE(5), 257 BIP_RANGE(2.5), 258 BIP_RANGE(1.25), 259 } 260}; 261static const struct comedi_lrange range_das1x02_unip = { 4, { 262 UNI_RANGE(10), 263 UNI_RANGE(5), 264 UNI_RANGE(2.5), 265 UNI_RANGE(1.25), 266 } 267}; 268static const struct comedi_lrange range_das16jr = { 9, { 269 /* also used by 16/330 */ 270 BIP_RANGE(10), 271 BIP_RANGE(5), 272 BIP_RANGE(2.5), 273 BIP_RANGE(1.25), 274 BIP_RANGE(0.625), 275 UNI_RANGE(10), 276 UNI_RANGE(5), 277 UNI_RANGE(2.5), 278 UNI_RANGE(1.25), 279 } 280}; 281static const struct comedi_lrange range_das16jr_16 = { 8, { 282 BIP_RANGE(10), 283 BIP_RANGE(5), 284 BIP_RANGE(2.5), 285 BIP_RANGE(1.25), 286 UNI_RANGE(10), 287 UNI_RANGE(5), 288 UNI_RANGE(2.5), 289 UNI_RANGE(1.25), 290 } 291}; 292 293static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 }; 294static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 }; 295static const int das1600_gainlist[] = { 0, 1, 2, 3 }; 296enum { 297 das16_pg_none = 0, 298 das16_pg_16jr, 299 das16_pg_16jr_16, 300 das16_pg_1601, 301 das16_pg_1602, 302}; 303static const int *const das16_gainlists[] = { 304 NULL, 305 das16jr_gainlist, 306 das16jr_16_gainlist, 307 das1600_gainlist, 308 das1600_gainlist, 309}; 310static const struct comedi_lrange *const das16_ai_uni_lranges[] = { 311 &range_unknown, 312 &range_das16jr, 313 &range_das16jr_16, 314 &range_das1x01_unip, 315 &range_das1x02_unip, 316}; 317static const struct comedi_lrange *const das16_ai_bip_lranges[] = { 318 &range_unknown, 319 &range_das16jr, 320 &range_das16jr_16, 321 &range_das1x01_bip, 322 &range_das1x02_bip, 323}; 324 325struct munge_info { 326 uint8_t byte; 327 unsigned have_byte:1; 328}; 329 330static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 331 struct comedi_insn *insn, unsigned int *data); 332static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, 333 struct comedi_insn *insn, unsigned int *data); 334static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, 335 struct comedi_insn *insn, unsigned int *data); 336static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 337 struct comedi_insn *insn, unsigned int *data); 338 339static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, 340 struct comedi_cmd *cmd); 341static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s); 342static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s); 343static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, 344 void *array, unsigned int num_bytes, unsigned int start_chan_index); 345 346static void das16_reset(struct comedi_device *dev); 347static irqreturn_t das16_dma_interrupt(int irq, void *d); 348static void das16_timer_interrupt(unsigned long arg); 349static void das16_interrupt(struct comedi_device *dev); 350 351static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, 352 int flags); 353static int das1600_mode_detect(struct comedi_device *dev); 354static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, 355 struct comedi_cmd cmd); 356 357static void reg_dump(struct comedi_device *dev); 358 359struct das16_board { 360 const char *name; 361 void *ai; 362 unsigned int ai_nbits; 363 unsigned int ai_speed; /* max conversion speed in nanosec */ 364 unsigned int ai_pg; 365 void *ao; 366 unsigned int ao_nbits; 367 void *di; 368 void *do_; 369 370 unsigned int i8255_offset; 371 unsigned int i8254_offset; 372 373 unsigned int size; 374 unsigned int id; 375}; 376 377static const struct das16_board das16_boards[] = { 378 { 379 .name = "das-16", 380 .ai = das16_ai_rinsn, 381 .ai_nbits = 12, 382 .ai_speed = 15000, 383 .ai_pg = das16_pg_none, 384 .ao = das16_ao_winsn, 385 .ao_nbits = 12, 386 .di = das16_di_rbits, 387 .do_ = das16_do_wbits, 388 .i8255_offset = 0x10, 389 .i8254_offset = 0x0c, 390 .size = 0x14, 391 .id = 0x00, 392 }, 393 { 394 .name = "das-16g", 395 .ai = das16_ai_rinsn, 396 .ai_nbits = 12, 397 .ai_speed = 15000, 398 .ai_pg = das16_pg_none, 399 .ao = das16_ao_winsn, 400 .ao_nbits = 12, 401 .di = das16_di_rbits, 402 .do_ = das16_do_wbits, 403 .i8255_offset = 0x10, 404 .i8254_offset = 0x0c, 405 .size = 0x14, 406 .id = 0x00, 407 }, 408 { 409 .name = "das-16f", 410 .ai = das16_ai_rinsn, 411 .ai_nbits = 12, 412 .ai_speed = 8500, 413 .ai_pg = das16_pg_none, 414 .ao = das16_ao_winsn, 415 .ao_nbits = 12, 416 .di = das16_di_rbits, 417 .do_ = das16_do_wbits, 418 .i8255_offset = 0x10, 419 .i8254_offset = 0x0c, 420 .size = 0x14, 421 .id = 0x00, 422 }, 423 { 424 .name = "cio-das16", /* cio-das16.pdf */ 425 .ai = das16_ai_rinsn, 426 .ai_nbits = 12, 427 .ai_speed = 20000, 428 .ai_pg = das16_pg_none, 429 .ao = das16_ao_winsn, 430 .ao_nbits = 12, 431 .di = das16_di_rbits, 432 .do_ = das16_do_wbits, 433 .i8255_offset = 0x10, 434 .i8254_offset = 0x0c, 435 .size = 0x14, 436 .id = 0x80, 437 }, 438 { 439 .name = "cio-das16/f", /* das16.pdf */ 440 .ai = das16_ai_rinsn, 441 .ai_nbits = 12, 442 .ai_speed = 10000, 443 .ai_pg = das16_pg_none, 444 .ao = das16_ao_winsn, 445 .ao_nbits = 12, 446 .di = das16_di_rbits, 447 .do_ = das16_do_wbits, 448 .i8255_offset = 0x10, 449 .i8254_offset = 0x0c, 450 .size = 0x14, 451 .id = 0x80, 452 }, 453 { 454 .name = "cio-das16/jr", /* cio-das16jr.pdf */ 455 .ai = das16_ai_rinsn, 456 .ai_nbits = 12, 457 .ai_speed = 7692, 458 .ai_pg = das16_pg_16jr, 459 .ao = NULL, 460 .di = das16_di_rbits, 461 .do_ = das16_do_wbits, 462 .i8255_offset = 0, 463 .i8254_offset = 0x0c, 464 .size = 0x10, 465 .id = 0x00, 466 }, 467 { 468 .name = "pc104-das16jr", /* pc104-das16jr_xx.pdf */ 469 .ai = das16_ai_rinsn, 470 .ai_nbits = 12, 471 .ai_speed = 3300, 472 .ai_pg = das16_pg_16jr, 473 .ao = NULL, 474 .di = das16_di_rbits, 475 .do_ = das16_do_wbits, 476 .i8255_offset = 0, 477 .i8254_offset = 0x0c, 478 .size = 0x10, 479 .id = 0x00, 480 }, 481 { 482 .name = "cio-das16jr/16", /* cio-das16jr_16.pdf */ 483 .ai = das16_ai_rinsn, 484 .ai_nbits = 16, 485 .ai_speed = 10000, 486 .ai_pg = das16_pg_16jr_16, 487 .ao = NULL, 488 .di = das16_di_rbits, 489 .do_ = das16_do_wbits, 490 .i8255_offset = 0, 491 .i8254_offset = 0x0c, 492 .size = 0x10, 493 .id = 0x00, 494 }, 495 { 496 .name = "pc104-das16jr/16", /* pc104-das16jr_xx.pdf */ 497 .ai = das16_ai_rinsn, 498 .ai_nbits = 16, 499 .ai_speed = 10000, 500 .ai_pg = das16_pg_16jr_16, 501 .ao = NULL, 502 .di = das16_di_rbits, 503 .do_ = das16_do_wbits, 504 .i8255_offset = 0, 505 .i8254_offset = 0x0c, 506 .size = 0x10, 507 .id = 0x00, 508 }, 509 { 510 .name = "das-1201", /* 4924.pdf (keithley user's manual) */ 511 .ai = das16_ai_rinsn, 512 .ai_nbits = 12, 513 .ai_speed = 20000, 514 .ai_pg = das16_pg_none, 515 .ao = NULL, 516 .di = das16_di_rbits, 517 .do_ = das16_do_wbits, 518 .i8255_offset = 0x400, 519 .i8254_offset = 0x0c, 520 .size = 0x408, 521 .id = 0x20, 522 }, 523 { 524 .name = "das-1202", /* 4924.pdf (keithley user's manual) */ 525 .ai = das16_ai_rinsn, 526 .ai_nbits = 12, 527 .ai_speed = 10000, 528 .ai_pg = das16_pg_none, 529 .ao = NULL, 530 .di = das16_di_rbits, 531 .do_ = das16_do_wbits, 532 .i8255_offset = 0x400, 533 .i8254_offset = 0x0c, 534 .size = 0x408, 535 .id = 0x20, 536 }, 537 { 538 .name = "das-1401", /* 4919.pdf and 4922.pdf (keithley user's manual) */ 539 .ai = das16_ai_rinsn, 540 .ai_nbits = 12, 541 .ai_speed = 10000, 542 .ai_pg = das16_pg_1601, 543 .ao = NULL, 544 .di = das16_di_rbits, 545 .do_ = das16_do_wbits, 546 .i8255_offset = 0x0, 547 .i8254_offset = 0x0c, 548 .size = 0x408, 549 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */ 550 }, 551 { 552 .name = "das-1402", /* 4919.pdf and 4922.pdf (keithley user's manual) */ 553 .ai = das16_ai_rinsn, 554 .ai_nbits = 12, 555 .ai_speed = 10000, 556 .ai_pg = das16_pg_1602, 557 .ao = NULL, 558 .di = das16_di_rbits, 559 .do_ = das16_do_wbits, 560 .i8255_offset = 0x0, 561 .i8254_offset = 0x0c, 562 .size = 0x408, 563 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */ 564 }, 565 { 566 .name = "das-1601", /* 4919.pdf */ 567 .ai = das16_ai_rinsn, 568 .ai_nbits = 12, 569 .ai_speed = 10000, 570 .ai_pg = das16_pg_1601, 571 .ao = das16_ao_winsn, 572 .ao_nbits = 12, 573 .di = das16_di_rbits, 574 .do_ = das16_do_wbits, 575 .i8255_offset = 0x400, 576 .i8254_offset = 0x0c, 577 .size = 0x408, 578 .id = 0xc0}, 579 { 580 .name = "das-1602", /* 4919.pdf */ 581 .ai = das16_ai_rinsn, 582 .ai_nbits = 12, 583 .ai_speed = 10000, 584 .ai_pg = das16_pg_1602, 585 .ao = das16_ao_winsn, 586 .ao_nbits = 12, 587 .di = das16_di_rbits, 588 .do_ = das16_do_wbits, 589 .i8255_offset = 0x400, 590 .i8254_offset = 0x0c, 591 .size = 0x408, 592 .id = 0xc0}, 593 { 594 .name = "cio-das1401/12", /* cio-das1400_series.pdf */ 595 .ai = das16_ai_rinsn, 596 .ai_nbits = 12, 597 .ai_speed = 6250, 598 .ai_pg = das16_pg_1601, 599 .ao = NULL, 600 .di = das16_di_rbits, 601 .do_ = das16_do_wbits, 602 .i8255_offset = 0, 603 .i8254_offset = 0x0c, 604 .size = 0x408, 605 .id = 0xc0}, 606 { 607 .name = "cio-das1402/12", /* cio-das1400_series.pdf */ 608 .ai = das16_ai_rinsn, 609 .ai_nbits = 12, 610 .ai_speed = 6250, 611 .ai_pg = das16_pg_1602, 612 .ao = NULL, 613 .di = das16_di_rbits, 614 .do_ = das16_do_wbits, 615 .i8255_offset = 0, 616 .i8254_offset = 0x0c, 617 .size = 0x408, 618 .id = 0xc0}, 619 { 620 .name = "cio-das1402/16", /* cio-das1400_series.pdf */ 621 .ai = das16_ai_rinsn, 622 .ai_nbits = 16, 623 .ai_speed = 10000, 624 .ai_pg = das16_pg_1602, 625 .ao = NULL, 626 .di = das16_di_rbits, 627 .do_ = das16_do_wbits, 628 .i8255_offset = 0, 629 .i8254_offset = 0x0c, 630 .size = 0x408, 631 .id = 0xc0}, 632 { 633 .name = "cio-das1601/12", /* cio-das160x-1x.pdf */ 634 .ai = das16_ai_rinsn, 635 .ai_nbits = 12, 636 .ai_speed = 6250, 637 .ai_pg = das16_pg_1601, 638 .ao = das16_ao_winsn, 639 .ao_nbits = 12, 640 .di = das16_di_rbits, 641 .do_ = das16_do_wbits, 642 .i8255_offset = 0x400, 643 .i8254_offset = 0x0c, 644 .size = 0x408, 645 .id = 0xc0}, 646 { 647 .name = "cio-das1602/12", /* cio-das160x-1x.pdf */ 648 .ai = das16_ai_rinsn, 649 .ai_nbits = 12, 650 .ai_speed = 10000, 651 .ai_pg = das16_pg_1602, 652 .ao = das16_ao_winsn, 653 .ao_nbits = 12, 654 .di = das16_di_rbits, 655 .do_ = das16_do_wbits, 656 .i8255_offset = 0x400, 657 .i8254_offset = 0x0c, 658 .size = 0x408, 659 .id = 0xc0}, 660 { 661 .name = "cio-das1602/16", /* cio-das160x-1x.pdf */ 662 .ai = das16_ai_rinsn, 663 .ai_nbits = 16, 664 .ai_speed = 10000, 665 .ai_pg = das16_pg_1602, 666 .ao = das16_ao_winsn, 667 .ao_nbits = 12, 668 .di = das16_di_rbits, 669 .do_ = das16_do_wbits, 670 .i8255_offset = 0x400, 671 .i8254_offset = 0x0c, 672 .size = 0x408, 673 .id = 0xc0}, 674 { 675 .name = "cio-das16/330", /* ? */ 676 .ai = das16_ai_rinsn, 677 .ai_nbits = 12, 678 .ai_speed = 3030, 679 .ai_pg = das16_pg_16jr, 680 .ao = NULL, 681 .di = das16_di_rbits, 682 .do_ = das16_do_wbits, 683 .i8255_offset = 0, 684 .i8254_offset = 0x0c, 685 .size = 0x14, 686 .id = 0xf0}, 687#if 0 688 { 689 .name = "das16/330i", /* ? */ 690 }, 691 { 692 .name = "das16/jr/ctr5", /* ? */ 693 }, 694 { 695 .name = "cio-das16/m1/16", /* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */ 696 }, 697#endif 698}; 699 700static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it); 701static int das16_detach(struct comedi_device *dev); 702static struct comedi_driver driver_das16 = { 703 .driver_name = "das16", 704 .module = THIS_MODULE, 705 .attach = das16_attach, 706 .detach = das16_detach, 707 .board_name = &das16_boards[0].name, 708 .num_names = ARRAY_SIZE(das16_boards), 709 .offset = sizeof(das16_boards[0]), 710}; 711 712#define DAS16_TIMEOUT 1000 713 714/* Period for timer interrupt in jiffies. It's a function 715 * to deal with possibility of dynamic HZ patches */ 716static inline int timer_period(void) 717{ 718 return HZ / 20; 719} 720struct das16_private_struct { 721 unsigned int ai_unipolar; /* unipolar flag */ 722 unsigned int ai_singleended; /* single ended flag */ 723 unsigned int clockbase; /* master clock speed in ns */ 724 volatile unsigned int control_state; /* dma, interrupt and trigger control bits */ 725 volatile unsigned long adc_byte_count; /* number of bytes remaining */ 726 unsigned int divisor1; /* divisor dividing master clock to get conversion frequency */ 727 unsigned int divisor2; /* divisor dividing master clock to get conversion frequency */ 728 unsigned int dma_chan; /* dma channel */ 729 uint16_t *dma_buffer[2]; 730 dma_addr_t dma_buffer_addr[2]; 731 unsigned int current_buffer; 732 volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */ 733 /* user-defined analog input and output ranges defined from config options */ 734 struct comedi_lrange *user_ai_range_table; 735 struct comedi_lrange *user_ao_range_table; 736 737 struct timer_list timer; /* for timed interrupt */ 738 volatile short timer_running; 739 volatile short timer_mode; /* true if using timer mode */ 740}; 741#define devpriv ((struct das16_private_struct *)(dev->private)) 742#define thisboard ((struct das16_board *)(dev->board_ptr)) 743 744static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s, 745 struct comedi_cmd *cmd) 746{ 747 int err = 0, tmp; 748 int gain, start_chan, i; 749 int mask; 750 751 /* make sure triggers are valid */ 752 tmp = cmd->start_src; 753 cmd->start_src &= TRIG_NOW; 754 if (!cmd->start_src || tmp != cmd->start_src) 755 err++; 756 757 tmp = cmd->scan_begin_src; 758 mask = TRIG_FOLLOW; 759 /* if board supports burst mode */ 760 if (thisboard->size > 0x400) 761 mask |= TRIG_TIMER | TRIG_EXT; 762 cmd->scan_begin_src &= mask; 763 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 764 err++; 765 766 tmp = cmd->convert_src; 767 mask = TRIG_TIMER | TRIG_EXT; 768 /* if board supports burst mode */ 769 if (thisboard->size > 0x400) 770 mask |= TRIG_NOW; 771 cmd->convert_src &= mask; 772 if (!cmd->convert_src || tmp != cmd->convert_src) 773 err++; 774 775 tmp = cmd->scan_end_src; 776 cmd->scan_end_src &= TRIG_COUNT; 777 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 778 err++; 779 780 tmp = cmd->stop_src; 781 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 782 if (!cmd->stop_src || tmp != cmd->stop_src) 783 err++; 784 785 if (err) 786 return 1; 787 788 /* step 2: make sure trigger sources are unique and mutually compatible */ 789 if (cmd->scan_begin_src != TRIG_TIMER && 790 cmd->scan_begin_src != TRIG_EXT && 791 cmd->scan_begin_src != TRIG_FOLLOW) 792 err++; 793 if (cmd->convert_src != TRIG_TIMER && 794 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) 795 err++; 796 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT) 797 err++; 798 799 /* make sure scan_begin_src and convert_src dont conflict */ 800 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW) 801 err++; 802 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW) 803 err++; 804 805 if (err) 806 return 2; 807 808 /* step 3: make sure arguments are trivially compatible */ 809 if (cmd->start_arg != 0) { 810 cmd->start_arg = 0; 811 err++; 812 } 813 814 if (cmd->scan_begin_src == TRIG_FOLLOW) { 815 /* internal trigger */ 816 if (cmd->scan_begin_arg != 0) { 817 cmd->scan_begin_arg = 0; 818 err++; 819 } 820 } 821 822 if (cmd->scan_end_arg != cmd->chanlist_len) { 823 cmd->scan_end_arg = cmd->chanlist_len; 824 err++; 825 } 826 /* check against maximum frequency */ 827 if (cmd->scan_begin_src == TRIG_TIMER) { 828 if (cmd->scan_begin_arg < 829 thisboard->ai_speed * cmd->chanlist_len) { 830 cmd->scan_begin_arg = 831 thisboard->ai_speed * cmd->chanlist_len; 832 err++; 833 } 834 } 835 if (cmd->convert_src == TRIG_TIMER) { 836 if (cmd->convert_arg < thisboard->ai_speed) { 837 cmd->convert_arg = thisboard->ai_speed; 838 err++; 839 } 840 } 841 842 if (cmd->stop_src == TRIG_NONE) { 843 if (cmd->stop_arg != 0) { 844 cmd->stop_arg = 0; 845 err++; 846 } 847 } 848 if (err) 849 return 3; 850 851 /* step 4: fix up arguments */ 852 if (cmd->scan_begin_src == TRIG_TIMER) { 853 unsigned int tmp = cmd->scan_begin_arg; 854 /* set divisors, correct timing arguments */ 855 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, 856 &(devpriv->divisor1), &(devpriv->divisor2), 857 &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK); 858 err += (tmp != cmd->scan_begin_arg); 859 } 860 if (cmd->convert_src == TRIG_TIMER) { 861 unsigned int tmp = cmd->convert_arg; 862 /* set divisors, correct timing arguments */ 863 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, 864 &(devpriv->divisor1), &(devpriv->divisor2), 865 &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK); 866 err += (tmp != cmd->convert_arg); 867 } 868 if (err) 869 return 4; 870 871 /* check channel/gain list against card's limitations */ 872 if (cmd->chanlist) { 873 gain = CR_RANGE(cmd->chanlist[0]); 874 start_chan = CR_CHAN(cmd->chanlist[0]); 875 for (i = 1; i < cmd->chanlist_len; i++) { 876 if (CR_CHAN(cmd->chanlist[i]) != 877 (start_chan + i) % s->n_chan) { 878 comedi_error(dev, 879 "entries in chanlist must be consecutive channels, counting upwards\n"); 880 err++; 881 } 882 if (CR_RANGE(cmd->chanlist[i]) != gain) { 883 comedi_error(dev, 884 "entries in chanlist must all have the same gain\n"); 885 err++; 886 } 887 } 888 } 889 if (err) 890 return 5; 891 892 return 0; 893} 894 895static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s) 896{ 897 struct comedi_async *async = s->async; 898 struct comedi_cmd *cmd = &async->cmd; 899 unsigned int byte; 900 unsigned long flags; 901 int range; 902 903 if (devpriv->dma_chan == 0 || (dev->irq == 0 904 && devpriv->timer_mode == 0)) { 905 comedi_error(dev, 906 "irq (or use of 'timer mode') dma required to execute comedi_cmd"); 907 return -1; 908 } 909 if (cmd->flags & TRIG_RT) { 910 comedi_error(dev, 911 "isa dma transfers cannot be performed with TRIG_RT, aborting"); 912 return -1; 913 } 914 915 devpriv->adc_byte_count = 916 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t); 917 918 /* disable conversions for das1600 mode */ 919 if (thisboard->size > 0x400) { 920 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV); 921 } 922 /* set scan limits */ 923 byte = CR_CHAN(cmd->chanlist[0]); 924 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4; 925 outb(byte, dev->iobase + DAS16_MUX); 926 927 /* set gain (this is also burst rate register but according to 928 * computer boards manual, burst rate does nothing, even on keithley cards) */ 929 if (thisboard->ai_pg != das16_pg_none) { 930 range = CR_RANGE(cmd->chanlist[0]); 931 outb((das16_gainlists[thisboard->ai_pg])[range], 932 dev->iobase + DAS16_GAIN); 933 } 934 935 /* set counter mode and counts */ 936 cmd->convert_arg = 937 das16_set_pacer(dev, cmd->convert_arg, 938 cmd->flags & TRIG_ROUND_MASK); 939 DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg); 940 941 /* enable counters */ 942 byte = 0; 943 /* Enable burst mode if appropriate. */ 944 if (thisboard->size > 0x400) { 945 if (cmd->convert_src == TRIG_NOW) { 946 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST); 947 /* set burst length */ 948 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1); 949 } else { 950 outb(0, dev->iobase + DAS1600_BURST); 951 } 952 } 953 outb(byte, dev->iobase + DAS16_PACER); 954 955 /* set up dma transfer */ 956 flags = claim_dma_lock(); 957 disable_dma(devpriv->dma_chan); 958 /* clear flip-flop to make sure 2-byte registers for 959 * count and address get set correctly */ 960 clear_dma_ff(devpriv->dma_chan); 961 devpriv->current_buffer = 0; 962 set_dma_addr(devpriv->dma_chan, 963 devpriv->dma_buffer_addr[devpriv->current_buffer]); 964 /* set appropriate size of transfer */ 965 devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd); 966 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); 967 enable_dma(devpriv->dma_chan); 968 release_dma_lock(flags); 969 970 /* set up interrupt */ 971 if (devpriv->timer_mode) { 972 devpriv->timer_running = 1; 973 devpriv->timer.expires = jiffies + timer_period(); 974 add_timer(&devpriv->timer); 975 devpriv->control_state &= ~DAS16_INTE; 976 } else { 977 /* clear interrupt bit */ 978 outb(0x00, dev->iobase + DAS16_STATUS); 979 /* enable interrupts */ 980 devpriv->control_state |= DAS16_INTE; 981 } 982 devpriv->control_state |= DMA_ENABLE; 983 devpriv->control_state &= ~PACING_MASK; 984 if (cmd->convert_src == TRIG_EXT) 985 devpriv->control_state |= EXT_PACER; 986 else 987 devpriv->control_state |= INT_PACER; 988 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); 989 990 /* Enable conversions if using das1600 mode */ 991 if (thisboard->size > 0x400) { 992 outb(0, dev->iobase + DAS1600_CONV); 993 } 994 995 return 0; 996} 997 998static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 999{ 1000 unsigned long flags; 1001 1002 spin_lock_irqsave(&dev->spinlock, flags); 1003 /* disable interrupts, dma and pacer clocked conversions */ 1004 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE; 1005 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); 1006 if (devpriv->dma_chan) 1007 disable_dma(devpriv->dma_chan); 1008 1009 /* disable SW timer */ 1010 if (devpriv->timer_mode && devpriv->timer_running) { 1011 devpriv->timer_running = 0; 1012 del_timer(&devpriv->timer); 1013 } 1014 1015 /* disable burst mode */ 1016 if (thisboard->size > 0x400) { 1017 outb(0, dev->iobase + DAS1600_BURST); 1018 } 1019 1020 spin_unlock_irqrestore(&dev->spinlock, flags); 1021 1022 return 0; 1023} 1024 1025static void das16_reset(struct comedi_device *dev) 1026{ 1027 outb(0, dev->iobase + DAS16_STATUS); 1028 outb(0, dev->iobase + DAS16_CONTROL); 1029 outb(0, dev->iobase + DAS16_PACER); 1030 outb(0, dev->iobase + DAS16_CNTR_CONTROL); 1031} 1032 1033static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s, 1034 struct comedi_insn *insn, unsigned int *data) 1035{ 1036 int i, n; 1037 int range; 1038 int chan; 1039 int msb, lsb; 1040 1041 /* disable interrupts and pacing */ 1042 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK; 1043 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); 1044 1045 /* set multiplexer */ 1046 chan = CR_CHAN(insn->chanspec); 1047 chan |= CR_CHAN(insn->chanspec) << 4; 1048 outb(chan, dev->iobase + DAS16_MUX); 1049 1050 /* set gain */ 1051 if (thisboard->ai_pg != das16_pg_none) { 1052 range = CR_RANGE(insn->chanspec); 1053 outb((das16_gainlists[thisboard->ai_pg])[range], 1054 dev->iobase + DAS16_GAIN); 1055 } 1056 1057 for (n = 0; n < insn->n; n++) { 1058 /* trigger conversion */ 1059 outb_p(0, dev->iobase + DAS16_TRIG); 1060 1061 for (i = 0; i < DAS16_TIMEOUT; i++) { 1062 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY)) 1063 break; 1064 } 1065 if (i == DAS16_TIMEOUT) { 1066 printk("das16: timeout\n"); 1067 return -ETIME; 1068 } 1069 msb = inb(dev->iobase + DAS16_AI_MSB); 1070 lsb = inb(dev->iobase + DAS16_AI_LSB); 1071 if (thisboard->ai_nbits == 12) { 1072 data[n] = ((lsb >> 4) & 0xf) | (msb << 4); 1073 } else { 1074 data[n] = lsb | (msb << 8); 1075 } 1076 } 1077 1078 return n; 1079} 1080 1081static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s, 1082 struct comedi_insn *insn, unsigned int *data) 1083{ 1084 unsigned int bits; 1085 1086 bits = inb(dev->iobase + DAS16_DIO) & 0xf; 1087 data[1] = bits; 1088 data[0] = 0; 1089 1090 return 2; 1091} 1092 1093static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s, 1094 struct comedi_insn *insn, unsigned int *data) 1095{ 1096 unsigned int wbits; 1097 1098 /* only set bits that have been masked */ 1099 data[0] &= 0xf; 1100 wbits = s->state; 1101 /* zero bits that have been masked */ 1102 wbits &= ~data[0]; 1103 /* set masked bits */ 1104 wbits |= data[0] & data[1]; 1105 s->state = wbits; 1106 data[1] = wbits; 1107 1108 outb(s->state, dev->iobase + DAS16_DIO); 1109 1110 return 2; 1111} 1112 1113static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s, 1114 struct comedi_insn *insn, unsigned int *data) 1115{ 1116 int i; 1117 int lsb, msb; 1118 int chan; 1119 1120 chan = CR_CHAN(insn->chanspec); 1121 1122 for (i = 0; i < insn->n; i++) { 1123 if (thisboard->ao_nbits == 12) { 1124 lsb = (data[i] << 4) & 0xff; 1125 msb = (data[i] >> 4) & 0xff; 1126 } else { 1127 lsb = data[i] & 0xff; 1128 msb = (data[i] >> 8) & 0xff; 1129 } 1130 outb(lsb, dev->iobase + DAS16_AO_LSB(chan)); 1131 outb(msb, dev->iobase + DAS16_AO_MSB(chan)); 1132 } 1133 1134 return i; 1135} 1136 1137static irqreturn_t das16_dma_interrupt(int irq, void *d) 1138{ 1139 int status; 1140 struct comedi_device *dev = d; 1141 1142 status = inb(dev->iobase + DAS16_STATUS); 1143 1144 if ((status & DAS16_INT) == 0) { 1145 DEBUG_PRINT("spurious interrupt\n"); 1146 return IRQ_NONE; 1147 } 1148 1149 /* clear interrupt */ 1150 outb(0x00, dev->iobase + DAS16_STATUS); 1151 das16_interrupt(dev); 1152 return IRQ_HANDLED; 1153} 1154 1155static void das16_timer_interrupt(unsigned long arg) 1156{ 1157 struct comedi_device *dev = (struct comedi_device *) arg; 1158 1159 das16_interrupt(dev); 1160 1161 if (devpriv->timer_running) 1162 mod_timer(&devpriv->timer, jiffies + timer_period()); 1163} 1164 1165/* the pc104-das16jr (at least) has problems if the dma 1166 transfer is interrupted in the middle of transferring 1167 a 16 bit sample, so this function takes care to get 1168 an even transfer count after disabling dma 1169 channel. 1170*/ 1171static int disable_dma_on_even(struct comedi_device *dev) 1172{ 1173 int residue; 1174 int i; 1175 static const int disable_limit = 100; 1176 static const int enable_timeout = 100; 1177 disable_dma(devpriv->dma_chan); 1178 residue = get_dma_residue(devpriv->dma_chan); 1179 for (i = 0; i < disable_limit && (residue % 2); ++i) { 1180 int j; 1181 enable_dma(devpriv->dma_chan); 1182 for (j = 0; j < enable_timeout; ++j) { 1183 int new_residue; 1184 udelay(2); 1185 new_residue = get_dma_residue(devpriv->dma_chan); 1186 if (new_residue != residue) 1187 break; 1188 } 1189 disable_dma(devpriv->dma_chan); 1190 residue = get_dma_residue(devpriv->dma_chan); 1191 } 1192 if (i == disable_limit) { 1193 comedi_error(dev, 1194 "failed to get an even dma transfer, could be trouble."); 1195 } 1196 return residue; 1197} 1198 1199static void das16_interrupt(struct comedi_device *dev) 1200{ 1201 unsigned long dma_flags, spin_flags; 1202 struct comedi_subdevice *s = dev->read_subdev; 1203 struct comedi_async *async; 1204 struct comedi_cmd *cmd; 1205 int num_bytes, residue; 1206 int buffer_index; 1207 1208 if (dev->attached == 0) { 1209 comedi_error(dev, "premature interrupt"); 1210 return; 1211 } 1212 /* initialize async here to make sure it is not NULL */ 1213 async = s->async; 1214 cmd = &async->cmd; 1215 1216 if (devpriv->dma_chan == 0) { 1217 comedi_error(dev, "interrupt with no dma channel?"); 1218 return; 1219 } 1220 1221 spin_lock_irqsave(&dev->spinlock, spin_flags); 1222 if ((devpriv->control_state & DMA_ENABLE) == 0) { 1223 spin_unlock_irqrestore(&dev->spinlock, spin_flags); 1224 DEBUG_PRINT("interrupt while dma disabled?\n"); 1225 return; 1226 } 1227 1228 dma_flags = claim_dma_lock(); 1229 clear_dma_ff(devpriv->dma_chan); 1230 residue = disable_dma_on_even(dev); 1231 1232 /* figure out how many points to read */ 1233 if (residue > devpriv->dma_transfer_size) { 1234 comedi_error(dev, "residue > transfer size!\n"); 1235 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 1236 num_bytes = 0; 1237 } else 1238 num_bytes = devpriv->dma_transfer_size - residue; 1239 1240 if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) { 1241 num_bytes = devpriv->adc_byte_count; 1242 async->events |= COMEDI_CB_EOA; 1243 } 1244 1245 buffer_index = devpriv->current_buffer; 1246 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2; 1247 devpriv->adc_byte_count -= num_bytes; 1248 1249 /* figure out how many bytes for next transfer */ 1250 if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 && 1251 devpriv->dma_transfer_size > devpriv->adc_byte_count) 1252 devpriv->dma_transfer_size = devpriv->adc_byte_count; 1253 1254 /* re-enable dma */ 1255 if ((async->events & COMEDI_CB_EOA) == 0) { 1256 set_dma_addr(devpriv->dma_chan, 1257 devpriv->dma_buffer_addr[devpriv->current_buffer]); 1258 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size); 1259 enable_dma(devpriv->dma_chan); 1260 /* reenable conversions for das1600 mode, (stupid hardware) */ 1261 if (thisboard->size > 0x400 && devpriv->timer_mode == 0) { 1262 outb(0x00, dev->iobase + DAS1600_CONV); 1263 } 1264 } 1265 release_dma_lock(dma_flags); 1266 1267 spin_unlock_irqrestore(&dev->spinlock, spin_flags); 1268 1269 cfc_write_array_to_buffer(s, 1270 devpriv->dma_buffer[buffer_index], num_bytes); 1271 1272 cfc_handle_events(dev, s); 1273} 1274 1275static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns, 1276 int rounding_flags) 1277{ 1278 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1), 1279 &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK); 1280 1281 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */ 1282 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2); 1283 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2); 1284 1285 return ns; 1286} 1287 1288static void reg_dump(struct comedi_device *dev) 1289{ 1290 DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n"); 1291 DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX)); 1292 DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO)); 1293 DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS)); 1294 DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL)); 1295 DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER)); 1296 DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN)); 1297 DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n", 1298 inb(dev->iobase + DAS16_CNTR_CONTROL)); 1299 DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV)); 1300 DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST)); 1301 DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE)); 1302 DEBUG_PRINT("DAS1600_STATUS_B: %x\n", 1303 inb(dev->iobase + DAS1600_STATUS_B)); 1304} 1305 1306static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it) 1307{ 1308 int status; 1309 int diobits; 1310 1311 /* status is available on all boards */ 1312 1313 status = inb(dev->iobase + DAS16_STATUS); 1314 1315 if ((status & UNIPOLAR)) { 1316 devpriv->ai_unipolar = 1; 1317 } else { 1318 devpriv->ai_unipolar = 0; 1319 } 1320 1321 if ((status & DAS16_MUXBIT)) { 1322 devpriv->ai_singleended = 1; 1323 } else { 1324 devpriv->ai_singleended = 0; 1325 } 1326 1327 /* diobits indicates boards */ 1328 1329 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0; 1330 1331 printk(" id bits are 0x%02x\n", diobits); 1332 if (thisboard->id != diobits) { 1333 printk(" requested board's id bits are 0x%x (ignore)\n", 1334 thisboard->id); 1335 } 1336 1337 return 0; 1338} 1339 1340static int das1600_mode_detect(struct comedi_device *dev) 1341{ 1342 int status = 0; 1343 1344 status = inb(dev->iobase + DAS1600_STATUS_B); 1345 1346 if (status & DAS1600_CLK_10MHZ) { 1347 devpriv->clockbase = 100; 1348 printk(" 10MHz pacer clock\n"); 1349 } else { 1350 devpriv->clockbase = 1000; 1351 printk(" 1MHz pacer clock\n"); 1352 } 1353 1354 reg_dump(dev); 1355 1356 return 0; 1357} 1358 1359/* 1360 * 1361 * Options list: 1362 * 0 I/O base 1363 * 1 IRQ 1364 * 2 DMA 1365 * 3 Clock speed (in MHz) 1366 */ 1367 1368static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1369{ 1370 struct comedi_subdevice *s; 1371 int ret; 1372 unsigned int irq; 1373 unsigned long iobase; 1374 unsigned int dma_chan; 1375 int timer_mode; 1376 unsigned long flags; 1377 struct comedi_krange *user_ai_range, *user_ao_range; 1378 1379 iobase = it->options[0]; 1380#if 0 1381 irq = it->options[1]; 1382 timer_mode = it->options[8]; 1383#endif 1384 /* always use time_mode since using irq can drop samples while 1385 * waiting for dma done interrupt (due to hardware limitations) */ 1386 irq = 0; 1387 timer_mode = 1; 1388 if (timer_mode) 1389 irq = 0; 1390 1391 printk("comedi%d: das16:", dev->minor); 1392 1393 /* check that clock setting is valid */ 1394 if (it->options[3]) { 1395 if (it->options[3] != 0 && 1396 it->options[3] != 1 && it->options[3] != 10) { 1397 printk("\n Invalid option. Master clock must be set to 1 or 10 (MHz)\n"); 1398 return -EINVAL; 1399 } 1400 } 1401 1402 ret = alloc_private(dev, sizeof(struct das16_private_struct)); 1403 if (ret < 0) 1404 return ret; 1405 1406 if (thisboard->size < 0x400) { 1407 printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size); 1408 if (!request_region(iobase, thisboard->size, "das16")) { 1409 printk(" I/O port conflict\n"); 1410 return -EIO; 1411 } 1412 } else { 1413 printk(" 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n", 1414 iobase, iobase + 0x0f, 1415 iobase + 0x400, 1416 iobase + 0x400 + (thisboard->size & 0x3ff)); 1417 if (!request_region(iobase, 0x10, "das16")) { 1418 printk(" I/O port conflict: 0x%04lx-0x%04lx\n", 1419 iobase, iobase + 0x0f); 1420 return -EIO; 1421 } 1422 if (!request_region(iobase + 0x400, thisboard->size & 0x3ff, 1423 "das16")) { 1424 release_region(iobase, 0x10); 1425 printk(" I/O port conflict: 0x%04lx-0x%04lx\n", 1426 iobase + 0x400, 1427 iobase + 0x400 + (thisboard->size & 0x3ff)); 1428 return -EIO; 1429 } 1430 } 1431 1432 dev->iobase = iobase; 1433 1434 /* probe id bits to make sure they are consistent */ 1435 if (das16_probe(dev, it)) { 1436 printk(" id bits do not match selected board, aborting\n"); 1437 return -EINVAL; 1438 } 1439 dev->board_name = thisboard->name; 1440 1441 /* get master clock speed */ 1442 if (thisboard->size < 0x400) { 1443 if (it->options[3]) 1444 devpriv->clockbase = 1000 / it->options[3]; 1445 else 1446 devpriv->clockbase = 1000; /* 1 MHz default */ 1447 } else { 1448 das1600_mode_detect(dev); 1449 } 1450 1451 /* now for the irq */ 1452 if (irq > 1 && irq < 8) { 1453 ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev); 1454 1455 if (ret < 0) 1456 return ret; 1457 dev->irq = irq; 1458 printk(" ( irq = %u )", irq); 1459 } else if (irq == 0) { 1460 printk(" ( no irq )"); 1461 } else { 1462 printk(" invalid irq\n"); 1463 return -EINVAL; 1464 } 1465 1466 /* initialize dma */ 1467 dma_chan = it->options[2]; 1468 if (dma_chan == 1 || dma_chan == 3) { 1469 /* allocate dma buffers */ 1470 int i; 1471 for (i = 0; i < 2; i++) { 1472 devpriv->dma_buffer[i] = pci_alloc_consistent(NULL, 1473 DAS16_DMA_SIZE, &devpriv->dma_buffer_addr[i]); 1474 if (devpriv->dma_buffer[i] == NULL) 1475 return -ENOMEM; 1476 } 1477 if (request_dma(dma_chan, "das16")) { 1478 printk(" failed to allocate dma channel %i\n", 1479 dma_chan); 1480 return -EINVAL; 1481 } 1482 devpriv->dma_chan = dma_chan; 1483 flags = claim_dma_lock(); 1484 disable_dma(devpriv->dma_chan); 1485 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ); 1486 release_dma_lock(flags); 1487 printk(" ( dma = %u)\n", dma_chan); 1488 } else if (dma_chan == 0) { 1489 printk(" ( no dma )\n"); 1490 } else { 1491 printk(" invalid dma channel\n"); 1492 return -EINVAL; 1493 } 1494 1495 /* get any user-defined input range */ 1496 if (thisboard->ai_pg == das16_pg_none && 1497 (it->options[4] || it->options[5])) { 1498 /* allocate single-range range table */ 1499 devpriv->user_ai_range_table = 1500 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange), 1501 GFP_KERNEL); 1502 /* initialize ai range */ 1503 devpriv->user_ai_range_table->length = 1; 1504 user_ai_range = devpriv->user_ai_range_table->range; 1505 user_ai_range->min = it->options[4]; 1506 user_ai_range->max = it->options[5]; 1507 user_ai_range->flags = UNIT_volt; 1508 } 1509 /* get any user-defined output range */ 1510 if (it->options[6] || it->options[7]) { 1511 /* allocate single-range range table */ 1512 devpriv->user_ao_range_table = 1513 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange), 1514 GFP_KERNEL); 1515 /* initialize ao range */ 1516 devpriv->user_ao_range_table->length = 1; 1517 user_ao_range = devpriv->user_ao_range_table->range; 1518 user_ao_range->min = it->options[6]; 1519 user_ao_range->max = it->options[7]; 1520 user_ao_range->flags = UNIT_volt; 1521 } 1522 1523 if (timer_mode) { 1524 init_timer(&(devpriv->timer)); 1525 devpriv->timer.function = das16_timer_interrupt; 1526 devpriv->timer.data = (unsigned long)dev; 1527 } 1528 devpriv->timer_mode = timer_mode ? 1 : 0; 1529 1530 ret = alloc_subdevices(dev, 5); 1531 if (ret < 0) 1532 return ret; 1533 1534 s = dev->subdevices + 0; 1535 dev->read_subdev = s; 1536 /* ai */ 1537 if (thisboard->ai) { 1538 s->type = COMEDI_SUBD_AI; 1539 s->subdev_flags = SDF_READABLE | SDF_CMD_READ; 1540 if (devpriv->ai_singleended) { 1541 s->n_chan = 16; 1542 s->len_chanlist = 16; 1543 s->subdev_flags |= SDF_GROUND; 1544 } else { 1545 s->n_chan = 8; 1546 s->len_chanlist = 8; 1547 s->subdev_flags |= SDF_DIFF; 1548 } 1549 s->maxdata = (1 << thisboard->ai_nbits) - 1; 1550 if (devpriv->user_ai_range_table) { /* user defined ai range */ 1551 s->range_table = devpriv->user_ai_range_table; 1552 } else if (devpriv->ai_unipolar) { 1553 s->range_table = das16_ai_uni_lranges[thisboard->ai_pg]; 1554 } else { 1555 s->range_table = das16_ai_bip_lranges[thisboard->ai_pg]; 1556 } 1557 s->insn_read = thisboard->ai; 1558 s->do_cmdtest = das16_cmd_test; 1559 s->do_cmd = das16_cmd_exec; 1560 s->cancel = das16_cancel; 1561 s->munge = das16_ai_munge; 1562 } else { 1563 s->type = COMEDI_SUBD_UNUSED; 1564 } 1565 1566 s = dev->subdevices + 1; 1567 /* ao */ 1568 if (thisboard->ao) { 1569 s->type = COMEDI_SUBD_AO; 1570 s->subdev_flags = SDF_WRITABLE; 1571 s->n_chan = 2; 1572 s->maxdata = (1 << thisboard->ao_nbits) - 1; 1573 if (devpriv->user_ao_range_table) { /* user defined ao range */ 1574 s->range_table = devpriv->user_ao_range_table; 1575 } else { 1576 s->range_table = &range_unknown; 1577 } 1578 s->insn_write = thisboard->ao; 1579 } else { 1580 s->type = COMEDI_SUBD_UNUSED; 1581 } 1582 1583 s = dev->subdevices + 2; 1584 /* di */ 1585 if (thisboard->di) { 1586 s->type = COMEDI_SUBD_DI; 1587 s->subdev_flags = SDF_READABLE; 1588 s->n_chan = 4; 1589 s->maxdata = 1; 1590 s->range_table = &range_digital; 1591 s->insn_bits = thisboard->di; 1592 } else { 1593 s->type = COMEDI_SUBD_UNUSED; 1594 } 1595 1596 s = dev->subdevices + 3; 1597 /* do */ 1598 if (thisboard->do_) { 1599 s->type = COMEDI_SUBD_DO; 1600 s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 1601 s->n_chan = 4; 1602 s->maxdata = 1; 1603 s->range_table = &range_digital; 1604 s->insn_bits = thisboard->do_; 1605 /* initialize digital output lines */ 1606 outb(s->state, dev->iobase + DAS16_DIO); 1607 } else { 1608 s->type = COMEDI_SUBD_UNUSED; 1609 } 1610 1611 s = dev->subdevices + 4; 1612 /* 8255 */ 1613 if (thisboard->i8255_offset != 0) { 1614 subdev_8255_init(dev, s, NULL, (dev->iobase + 1615 thisboard->i8255_offset)); 1616 } else { 1617 s->type = COMEDI_SUBD_UNUSED; 1618 } 1619 1620 das16_reset(dev); 1621 /* set the interrupt level */ 1622 devpriv->control_state = DAS16_IRQ(dev->irq); 1623 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL); 1624 1625 /* turn on das1600 mode if available */ 1626 if (thisboard->size > 0x400) { 1627 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE); 1628 outb(0, dev->iobase + DAS1600_CONV); 1629 outb(0, dev->iobase + DAS1600_BURST); 1630 } 1631 1632 return 0; 1633} 1634 1635static int das16_detach(struct comedi_device *dev) 1636{ 1637 printk("comedi%d: das16: remove\n", dev->minor); 1638 1639 das16_reset(dev); 1640 1641 if (dev->subdevices) 1642 subdev_8255_cleanup(dev, dev->subdevices + 4); 1643 1644 if (devpriv) { 1645 int i; 1646 for (i = 0; i < 2; i++) { 1647 if (devpriv->dma_buffer[i]) 1648 pci_free_consistent(NULL, DAS16_DMA_SIZE, 1649 devpriv->dma_buffer[i], 1650 devpriv->dma_buffer_addr[i]); 1651 } 1652 if (devpriv->dma_chan) 1653 free_dma(devpriv->dma_chan); 1654 if (devpriv->user_ai_range_table) 1655 kfree(devpriv->user_ai_range_table); 1656 if (devpriv->user_ao_range_table) 1657 kfree(devpriv->user_ao_range_table); 1658 } 1659 1660 if (dev->irq) 1661 free_irq(dev->irq, dev); 1662 1663 if (dev->iobase) { 1664 if (thisboard->size < 0x400) { 1665 release_region(dev->iobase, thisboard->size); 1666 } else { 1667 release_region(dev->iobase, 0x10); 1668 release_region(dev->iobase + 0x400, 1669 thisboard->size & 0x3ff); 1670 } 1671 } 1672 1673 return 0; 1674} 1675 1676COMEDI_INITCLEANUP(driver_das16); 1677 1678/* utility function that suggests a dma transfer size in bytes */ 1679static unsigned int das16_suggest_transfer_size(struct comedi_device *dev, 1680 struct comedi_cmd cmd) 1681{ 1682 unsigned int size; 1683 unsigned int freq; 1684 1685 /* if we are using timer interrupt, we don't care how long it 1686 * will take to complete transfer since it will be interrupted 1687 * by timer interrupt */ 1688 if (devpriv->timer_mode) 1689 return DAS16_DMA_SIZE; 1690 1691 /* otherwise, we are relying on dma terminal count interrupt, 1692 * so pick a reasonable size */ 1693 if (cmd.convert_src == TRIG_TIMER) 1694 freq = 1000000000 / cmd.convert_arg; 1695 else if (cmd.scan_begin_src == TRIG_TIMER) 1696 freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len; 1697 /* return some default value */ 1698 else 1699 freq = 0xffffffff; 1700 1701 if (cmd.flags & TRIG_WAKE_EOS) { 1702 size = sample_size * cmd.chanlist_len; 1703 } else { 1704 /* make buffer fill in no more than 1/3 second */ 1705 size = (freq / 3) * sample_size; 1706 } 1707 1708 /* set a minimum and maximum size allowed */ 1709 if (size > DAS16_DMA_SIZE) 1710 size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size; 1711 else if (size < sample_size) 1712 size = sample_size; 1713 1714 if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count) 1715 size = devpriv->adc_byte_count; 1716 1717 return size; 1718} 1719 1720static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s, 1721 void *array, unsigned int num_bytes, unsigned int start_chan_index) 1722{ 1723 unsigned int i, num_samples = num_bytes / sizeof(short); 1724 short *data = array; 1725 1726 for (i = 0; i < num_samples; i++) { 1727 data[i] = le16_to_cpu(data[i]); 1728 if (thisboard->ai_nbits == 12) { 1729 data[i] = (data[i] >> 4) & 0xfff; 1730 } 1731 } 1732} 1733