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