dt3000.c revision 27020ffed9166d65ce1e5b523051d13bfa2329b0
1/* 2 comedi/drivers/dt3000.c 3 Data Translation DT3000 series driver 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 1999 David A. Schleef <ds@schleef.org> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22*/ 23/* 24Driver: dt3000 25Description: Data Translation DT3000 series 26Author: ds 27Devices: [Data Translation] DT3001 (dt3000), DT3001-PGL, DT3002, DT3003, 28 DT3003-PGL, DT3004, DT3005, DT3004-200 29Updated: Mon, 14 Apr 2008 15:41:24 +0100 30Status: works 31 32Configuration Options: 33 [0] - PCI bus of device (optional) 34 [1] - PCI slot of device (optional) 35 If bus/slot is not specified, the first supported 36 PCI device found will be used. 37 38There is code to support AI commands, but it may not work. 39 40AO commands are not supported. 41*/ 42 43/* 44 The DT3000 series is Data Translation's attempt to make a PCI 45 data acquisition board. The design of this series is very nice, 46 since each board has an on-board DSP (Texas Instruments TMS320C52). 47 However, a few details are a little annoying. The boards lack 48 bus-mastering DMA, which eliminates them from serious work. 49 They also are not capable of autocalibration, which is a common 50 feature in modern hardware. The default firmware is pretty bad, 51 making it nearly impossible to write an RT compatible driver. 52 It would make an interesting project to write a decent firmware 53 for these boards. 54 55 Data Translation originally wanted an NDA for the documentation 56 for the 3k series. However, if you ask nicely, they might send 57 you the docs without one, also. 58*/ 59 60#define DEBUG 1 61 62#include <linux/interrupt.h> 63#include "../comedidev.h" 64#include <linux/delay.h> 65 66#include "comedi_fc.h" 67 68#define PCI_VENDOR_ID_DT 0x1116 69 70static const struct comedi_lrange range_dt3000_ai = { 4, { 71 RANGE(-10, 10), 72 RANGE(-5, 5), 73 RANGE(-2.5, 2.5), 74 RANGE(-1.25, 1.25) 75 } 76}; 77 78static const struct comedi_lrange range_dt3000_ai_pgl = { 4, { 79 RANGE(-10, 10), 80 RANGE(-1, 1), 81 RANGE(-0.1, 0.1), 82 RANGE(-0.02, 0.02) 83 } 84}; 85 86struct dt3k_boardtype { 87 88 const char *name; 89 unsigned int device_id; 90 int adchan; 91 int adbits; 92 int ai_speed; 93 const struct comedi_lrange *adrange; 94 int dachan; 95 int dabits; 96}; 97 98static const struct dt3k_boardtype dt3k_boardtypes[] = { 99 {.name = "dt3001", 100 .device_id = 0x22, 101 .adchan = 16, 102 .adbits = 12, 103 .adrange = &range_dt3000_ai, 104 .ai_speed = 3000, 105 .dachan = 2, 106 .dabits = 12, 107 }, 108 {.name = "dt3001-pgl", 109 .device_id = 0x27, 110 .adchan = 16, 111 .adbits = 12, 112 .adrange = &range_dt3000_ai_pgl, 113 .ai_speed = 3000, 114 .dachan = 2, 115 .dabits = 12, 116 }, 117 {.name = "dt3002", 118 .device_id = 0x23, 119 .adchan = 32, 120 .adbits = 12, 121 .adrange = &range_dt3000_ai, 122 .ai_speed = 3000, 123 .dachan = 0, 124 .dabits = 0, 125 }, 126 {.name = "dt3003", 127 .device_id = 0x24, 128 .adchan = 64, 129 .adbits = 12, 130 .adrange = &range_dt3000_ai, 131 .ai_speed = 3000, 132 .dachan = 2, 133 .dabits = 12, 134 }, 135 {.name = "dt3003-pgl", 136 .device_id = 0x28, 137 .adchan = 64, 138 .adbits = 12, 139 .adrange = &range_dt3000_ai_pgl, 140 .ai_speed = 3000, 141 .dachan = 2, 142 .dabits = 12, 143 }, 144 {.name = "dt3004", 145 .device_id = 0x25, 146 .adchan = 16, 147 .adbits = 16, 148 .adrange = &range_dt3000_ai, 149 .ai_speed = 10000, 150 .dachan = 2, 151 .dabits = 12, 152 }, 153 {.name = "dt3005", /* a.k.a. 3004-200 */ 154 .device_id = 0x26, 155 .adchan = 16, 156 .adbits = 16, 157 .adrange = &range_dt3000_ai, 158 .ai_speed = 5000, 159 .dachan = 2, 160 .dabits = 12, 161 }, 162}; 163 164#define this_board ((const struct dt3k_boardtype *)dev->board_ptr) 165 166#define DT3000_SIZE (4*0x1000) 167 168/* dual-ported RAM location definitions */ 169 170#define DPR_DAC_buffer (4*0x000) 171#define DPR_ADC_buffer (4*0x800) 172#define DPR_Command (4*0xfd3) 173#define DPR_SubSys (4*0xfd3) 174#define DPR_Encode (4*0xfd4) 175#define DPR_Params(a) (4*(0xfd5+(a))) 176#define DPR_Tick_Reg_Lo (4*0xff5) 177#define DPR_Tick_Reg_Hi (4*0xff6) 178#define DPR_DA_Buf_Front (4*0xff7) 179#define DPR_DA_Buf_Rear (4*0xff8) 180#define DPR_AD_Buf_Front (4*0xff9) 181#define DPR_AD_Buf_Rear (4*0xffa) 182#define DPR_Int_Mask (4*0xffb) 183#define DPR_Intr_Flag (4*0xffc) 184#define DPR_Response_Mbx (4*0xffe) 185#define DPR_Command_Mbx (4*0xfff) 186 187#define AI_FIFO_DEPTH 2003 188#define AO_FIFO_DEPTH 2048 189 190/* command list */ 191 192#define CMD_GETBRDINFO 0 193#define CMD_CONFIG 1 194#define CMD_GETCONFIG 2 195#define CMD_START 3 196#define CMD_STOP 4 197#define CMD_READSINGLE 5 198#define CMD_WRITESINGLE 6 199#define CMD_CALCCLOCK 7 200#define CMD_READEVENTS 8 201#define CMD_WRITECTCTRL 16 202#define CMD_READCTCTRL 17 203#define CMD_WRITECT 18 204#define CMD_READCT 19 205#define CMD_WRITEDATA 32 206#define CMD_READDATA 33 207#define CMD_WRITEIO 34 208#define CMD_READIO 35 209#define CMD_WRITECODE 36 210#define CMD_READCODE 37 211#define CMD_EXECUTE 38 212#define CMD_HALT 48 213 214#define SUBS_AI 0 215#define SUBS_AO 1 216#define SUBS_DIN 2 217#define SUBS_DOUT 3 218#define SUBS_MEM 4 219#define SUBS_CT 5 220 221/* interrupt flags */ 222#define DT3000_CMDONE 0x80 223#define DT3000_CTDONE 0x40 224#define DT3000_DAHWERR 0x20 225#define DT3000_DASWERR 0x10 226#define DT3000_DAEMPTY 0x08 227#define DT3000_ADHWERR 0x04 228#define DT3000_ADSWERR 0x02 229#define DT3000_ADFULL 0x01 230 231#define DT3000_COMPLETION_MASK 0xff00 232#define DT3000_COMMAND_MASK 0x00ff 233#define DT3000_NOTPROCESSED 0x0000 234#define DT3000_NOERROR 0x5500 235#define DT3000_ERROR 0xaa00 236#define DT3000_NOTSUPPORTED 0xff00 237 238#define DT3000_EXTERNAL_CLOCK 1 239#define DT3000_RISING_EDGE 2 240 241#define TMODE_MASK 0x1c 242 243#define DT3000_AD_TRIG_INTERNAL (0<<2) 244#define DT3000_AD_TRIG_EXTERNAL (1<<2) 245#define DT3000_AD_RETRIG_INTERNAL (2<<2) 246#define DT3000_AD_RETRIG_EXTERNAL (3<<2) 247#define DT3000_AD_EXTRETRIG (4<<2) 248 249#define DT3000_CHANNEL_MODE_SE 0 250#define DT3000_CHANNEL_MODE_DI 1 251 252struct dt3k_private { 253 void __iomem *io_addr; 254 unsigned int lock; 255 unsigned int ao_readback[2]; 256 unsigned int ai_front; 257 unsigned int ai_rear; 258}; 259 260#define devpriv ((struct dt3k_private *)dev->private) 261 262static void dt3k_ai_empty_fifo(struct comedi_device *dev, 263 struct comedi_subdevice *s); 264static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg, 265 unsigned int round_mode); 266static int dt3k_ai_cancel(struct comedi_device *dev, 267 struct comedi_subdevice *s); 268#ifdef DEBUG 269static void debug_intr_flags(unsigned int flags); 270#endif 271 272#define TIMEOUT 100 273 274static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) 275{ 276 int i; 277 unsigned int status = 0; 278 279 writew(cmd, devpriv->io_addr + DPR_Command_Mbx); 280 281 for (i = 0; i < TIMEOUT; i++) { 282 status = readw(devpriv->io_addr + DPR_Command_Mbx); 283 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED) 284 break; 285 udelay(1); 286 } 287 if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) 288 return 0; 289 290 dev_dbg(dev->class_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n", 291 status); 292 293 return -ETIME; 294} 295 296static unsigned int dt3k_readsingle(struct comedi_device *dev, 297 unsigned int subsys, unsigned int chan, 298 unsigned int gain) 299{ 300 writew(subsys, devpriv->io_addr + DPR_SubSys); 301 302 writew(chan, devpriv->io_addr + DPR_Params(0)); 303 writew(gain, devpriv->io_addr + DPR_Params(1)); 304 305 dt3k_send_cmd(dev, CMD_READSINGLE); 306 307 return readw(devpriv->io_addr + DPR_Params(2)); 308} 309 310static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys, 311 unsigned int chan, unsigned int data) 312{ 313 writew(subsys, devpriv->io_addr + DPR_SubSys); 314 315 writew(chan, devpriv->io_addr + DPR_Params(0)); 316 writew(0, devpriv->io_addr + DPR_Params(1)); 317 writew(data, devpriv->io_addr + DPR_Params(2)); 318 319 dt3k_send_cmd(dev, CMD_WRITESINGLE); 320} 321 322static int debug_n_ints; 323 324/* FIXME! Assumes shared interrupt is for this card. */ 325/* What's this debug_n_ints stuff? Obviously needs some work... */ 326static irqreturn_t dt3k_interrupt(int irq, void *d) 327{ 328 struct comedi_device *dev = d; 329 struct comedi_subdevice *s; 330 unsigned int status; 331 332 if (!dev->attached) 333 return IRQ_NONE; 334 335 s = &dev->subdevices[0]; 336 status = readw(devpriv->io_addr + DPR_Intr_Flag); 337#ifdef DEBUG 338 debug_intr_flags(status); 339#endif 340 341 if (status & DT3000_ADFULL) { 342 dt3k_ai_empty_fifo(dev, s); 343 s->async->events |= COMEDI_CB_BLOCK; 344 } 345 346 if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) 347 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 348 349 debug_n_ints++; 350 if (debug_n_ints >= 10) { 351 dt3k_ai_cancel(dev, s); 352 s->async->events |= COMEDI_CB_EOA; 353 } 354 355 comedi_event(dev, s); 356 return IRQ_HANDLED; 357} 358 359#ifdef DEBUG 360static char *intr_flags[] = { 361 "AdFull", "AdSwError", "AdHwError", "DaEmpty", 362 "DaSwError", "DaHwError", "CtDone", "CmDone", 363}; 364 365static void debug_intr_flags(unsigned int flags) 366{ 367 int i; 368 printk(KERN_DEBUG "dt3k: intr_flags:"); 369 for (i = 0; i < 8; i++) { 370 if (flags & (1 << i)) 371 printk(KERN_CONT " %s", intr_flags[i]); 372 } 373 printk(KERN_CONT "\n"); 374} 375#endif 376 377static void dt3k_ai_empty_fifo(struct comedi_device *dev, 378 struct comedi_subdevice *s) 379{ 380 int front; 381 int rear; 382 int count; 383 int i; 384 short data; 385 386 front = readw(devpriv->io_addr + DPR_AD_Buf_Front); 387 count = front - devpriv->ai_front; 388 if (count < 0) 389 count += AI_FIFO_DEPTH; 390 391 dev_dbg(dev->class_dev, "reading %d samples\n", count); 392 393 rear = devpriv->ai_rear; 394 395 for (i = 0; i < count; i++) { 396 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear); 397 comedi_buf_put(s->async, data); 398 rear++; 399 if (rear >= AI_FIFO_DEPTH) 400 rear = 0; 401 } 402 403 devpriv->ai_rear = rear; 404 writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear); 405} 406 407static int dt3k_ai_cmdtest(struct comedi_device *dev, 408 struct comedi_subdevice *s, struct comedi_cmd *cmd) 409{ 410 int err = 0; 411 int tmp; 412 413 /* Step 1 : check if triggers are trivially valid */ 414 415 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); 416 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); 417 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER); 418 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 419 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT); 420 421 if (err) 422 return 1; 423 424 /* Step 2a : make sure trigger sources are unique */ 425 /* Step 2b : and mutually compatible */ 426 427 if (err) 428 return 2; 429 430 /* step 3: make sure arguments are trivially compatible */ 431 432 if (cmd->start_arg != 0) { 433 cmd->start_arg = 0; 434 err++; 435 } 436 437 if (cmd->scan_begin_src == TRIG_TIMER) { 438 if (cmd->scan_begin_arg < this_board->ai_speed) { 439 cmd->scan_begin_arg = this_board->ai_speed; 440 err++; 441 } 442 if (cmd->scan_begin_arg > 100 * 16 * 65535) { 443 cmd->scan_begin_arg = 100 * 16 * 65535; 444 err++; 445 } 446 } else { 447 /* not supported */ 448 } 449 if (cmd->convert_src == TRIG_TIMER) { 450 if (cmd->convert_arg < this_board->ai_speed) { 451 cmd->convert_arg = this_board->ai_speed; 452 err++; 453 } 454 if (cmd->convert_arg > 50 * 16 * 65535) { 455 cmd->convert_arg = 50 * 16 * 65535; 456 err++; 457 } 458 } else { 459 /* not supported */ 460 } 461 462 if (cmd->scan_end_arg != cmd->chanlist_len) { 463 cmd->scan_end_arg = cmd->chanlist_len; 464 err++; 465 } 466 if (cmd->stop_src == TRIG_COUNT) { 467 if (cmd->stop_arg > 0x00ffffff) { 468 cmd->stop_arg = 0x00ffffff; 469 err++; 470 } 471 } else { 472 /* TRIG_NONE */ 473 if (cmd->stop_arg != 0) { 474 cmd->stop_arg = 0; 475 err++; 476 } 477 } 478 479 if (err) 480 return 3; 481 482 /* step 4: fix up any arguments */ 483 484 if (cmd->scan_begin_src == TRIG_TIMER) { 485 tmp = cmd->scan_begin_arg; 486 dt3k_ns_to_timer(100, &cmd->scan_begin_arg, 487 cmd->flags & TRIG_ROUND_MASK); 488 if (tmp != cmd->scan_begin_arg) 489 err++; 490 } else { 491 /* not supported */ 492 } 493 if (cmd->convert_src == TRIG_TIMER) { 494 tmp = cmd->convert_arg; 495 dt3k_ns_to_timer(50, &cmd->convert_arg, 496 cmd->flags & TRIG_ROUND_MASK); 497 if (tmp != cmd->convert_arg) 498 err++; 499 if (cmd->scan_begin_src == TRIG_TIMER && 500 cmd->scan_begin_arg < 501 cmd->convert_arg * cmd->scan_end_arg) { 502 cmd->scan_begin_arg = 503 cmd->convert_arg * cmd->scan_end_arg; 504 err++; 505 } 506 } else { 507 /* not supported */ 508 } 509 510 if (err) 511 return 4; 512 513 return 0; 514} 515 516static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, 517 unsigned int round_mode) 518{ 519 int divider, base, prescale; 520 521 /* This function needs improvment */ 522 /* Don't know if divider==0 works. */ 523 524 for (prescale = 0; prescale < 16; prescale++) { 525 base = timer_base * (prescale + 1); 526 switch (round_mode) { 527 case TRIG_ROUND_NEAREST: 528 default: 529 divider = (*nanosec + base / 2) / base; 530 break; 531 case TRIG_ROUND_DOWN: 532 divider = (*nanosec) / base; 533 break; 534 case TRIG_ROUND_UP: 535 divider = (*nanosec) / base; 536 break; 537 } 538 if (divider < 65536) { 539 *nanosec = divider * base; 540 return (prescale << 16) | (divider); 541 } 542 } 543 544 prescale = 15; 545 base = timer_base * (1 << prescale); 546 divider = 65535; 547 *nanosec = divider * base; 548 return (prescale << 16) | (divider); 549} 550 551static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 552{ 553 struct comedi_cmd *cmd = &s->async->cmd; 554 int i; 555 unsigned int chan, range, aref; 556 unsigned int divider; 557 unsigned int tscandiv; 558 int ret; 559 unsigned int mode; 560 561 dev_dbg(dev->class_dev, "dt3k_ai_cmd:\n"); 562 for (i = 0; i < cmd->chanlist_len; i++) { 563 chan = CR_CHAN(cmd->chanlist[i]); 564 range = CR_RANGE(cmd->chanlist[i]); 565 566 writew((range << 6) | chan, 567 devpriv->io_addr + DPR_ADC_buffer + i); 568 } 569 aref = CR_AREF(cmd->chanlist[0]); 570 571 writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0)); 572 dev_dbg(dev->class_dev, "param[0]=0x%04x\n", cmd->scan_end_arg); 573 574 if (cmd->convert_src == TRIG_TIMER) { 575 divider = dt3k_ns_to_timer(50, &cmd->convert_arg, 576 cmd->flags & TRIG_ROUND_MASK); 577 writew((divider >> 16), devpriv->io_addr + DPR_Params(1)); 578 dev_dbg(dev->class_dev, "param[1]=0x%04x\n", divider >> 16); 579 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2)); 580 dev_dbg(dev->class_dev, "param[2]=0x%04x\n", divider & 0xffff); 581 } else { 582 /* not supported */ 583 } 584 585 if (cmd->scan_begin_src == TRIG_TIMER) { 586 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, 587 cmd->flags & TRIG_ROUND_MASK); 588 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3)); 589 dev_dbg(dev->class_dev, "param[3]=0x%04x\n", tscandiv >> 16); 590 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4)); 591 dev_dbg(dev->class_dev, "param[4]=0x%04x\n", tscandiv & 0xffff); 592 } else { 593 /* not supported */ 594 } 595 596 mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; 597 writew(mode, devpriv->io_addr + DPR_Params(5)); 598 dev_dbg(dev->class_dev, "param[5]=0x%04x\n", mode); 599 writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6)); 600 dev_dbg(dev->class_dev, "param[6]=0x%04x\n", aref == AREF_DIFF); 601 602 writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7)); 603 dev_dbg(dev->class_dev, "param[7]=0x%04x\n", AI_FIFO_DEPTH / 2); 604 605 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 606 ret = dt3k_send_cmd(dev, CMD_CONFIG); 607 608 writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, 609 devpriv->io_addr + DPR_Int_Mask); 610 611 debug_n_ints = 0; 612 613 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 614 ret = dt3k_send_cmd(dev, CMD_START); 615 616 return 0; 617} 618 619static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 620{ 621 int ret; 622 623 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 624 ret = dt3k_send_cmd(dev, CMD_STOP); 625 626 writew(0, devpriv->io_addr + DPR_Int_Mask); 627 628 return 0; 629} 630 631static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, 632 struct comedi_insn *insn, unsigned int *data) 633{ 634 int i; 635 unsigned int chan, gain, aref; 636 637 chan = CR_CHAN(insn->chanspec); 638 gain = CR_RANGE(insn->chanspec); 639 /* XXX docs don't explain how to select aref */ 640 aref = CR_AREF(insn->chanspec); 641 642 for (i = 0; i < insn->n; i++) 643 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain); 644 645 return i; 646} 647 648static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, 649 struct comedi_insn *insn, unsigned int *data) 650{ 651 int i; 652 unsigned int chan; 653 654 chan = CR_CHAN(insn->chanspec); 655 for (i = 0; i < insn->n; i++) { 656 dt3k_writesingle(dev, SUBS_AO, chan, data[i]); 657 devpriv->ao_readback[chan] = data[i]; 658 } 659 660 return i; 661} 662 663static int dt3k_ao_insn_read(struct comedi_device *dev, 664 struct comedi_subdevice *s, 665 struct comedi_insn *insn, unsigned int *data) 666{ 667 int i; 668 unsigned int chan; 669 670 chan = CR_CHAN(insn->chanspec); 671 for (i = 0; i < insn->n; i++) 672 data[i] = devpriv->ao_readback[chan]; 673 674 return i; 675} 676 677static void dt3k_dio_config(struct comedi_device *dev, int bits) 678{ 679 /* XXX */ 680 writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys); 681 682 writew(bits, devpriv->io_addr + DPR_Params(0)); 683#if 0 684 /* don't know */ 685 writew(0, devpriv->io_addr + DPR_Params(1)); 686 writew(0, devpriv->io_addr + DPR_Params(2)); 687#endif 688 689 dt3k_send_cmd(dev, CMD_CONFIG); 690} 691 692static int dt3k_dio_insn_config(struct comedi_device *dev, 693 struct comedi_subdevice *s, 694 struct comedi_insn *insn, unsigned int *data) 695{ 696 int mask; 697 698 mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0; 699 700 switch (data[0]) { 701 case INSN_CONFIG_DIO_OUTPUT: 702 s->io_bits |= mask; 703 break; 704 case INSN_CONFIG_DIO_INPUT: 705 s->io_bits &= ~mask; 706 break; 707 case INSN_CONFIG_DIO_QUERY: 708 data[1] = 709 (s-> 710 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : 711 COMEDI_INPUT; 712 return insn->n; 713 break; 714 default: 715 return -EINVAL; 716 break; 717 } 718 mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3); 719 dt3k_dio_config(dev, mask); 720 721 return insn->n; 722} 723 724static int dt3k_dio_insn_bits(struct comedi_device *dev, 725 struct comedi_subdevice *s, 726 struct comedi_insn *insn, unsigned int *data) 727{ 728 if (data[0]) { 729 s->state &= ~data[0]; 730 s->state |= data[1] & data[0]; 731 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state); 732 } 733 data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); 734 735 return insn->n; 736} 737 738static int dt3k_mem_insn_read(struct comedi_device *dev, 739 struct comedi_subdevice *s, 740 struct comedi_insn *insn, unsigned int *data) 741{ 742 unsigned int addr = CR_CHAN(insn->chanspec); 743 int i; 744 745 for (i = 0; i < insn->n; i++) { 746 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys); 747 writew(addr, devpriv->io_addr + DPR_Params(0)); 748 writew(1, devpriv->io_addr + DPR_Params(1)); 749 750 dt3k_send_cmd(dev, CMD_READCODE); 751 752 data[i] = readw(devpriv->io_addr + DPR_Params(2)); 753 } 754 755 return i; 756} 757 758static struct pci_dev *dt3000_find_pci_dev(struct comedi_device *dev, 759 struct comedi_devconfig *it) 760{ 761 struct pci_dev *pcidev = NULL; 762 int bus = it->options[0]; 763 int slot = it->options[1]; 764 int i; 765 766 for_each_pci_dev(pcidev) { 767 if (bus || slot) { 768 if (bus != pcidev->bus->number || 769 slot != PCI_SLOT(pcidev->devfn)) 770 continue; 771 } 772 if (pcidev->vendor != PCI_VENDOR_ID_DT) 773 continue; 774 for (i = 0; i < ARRAY_SIZE(dt3k_boardtypes); i++) { 775 if (dt3k_boardtypes[i].device_id != pcidev->device) 776 continue; 777 dev->board_ptr = dt3k_boardtypes + i; 778 return pcidev; 779 } 780 } 781 dev_err(dev->class_dev, 782 "No supported board found! (req. bus %d, slot %d)\n", 783 bus, slot); 784 return NULL; 785} 786 787static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) 788{ 789 struct pci_dev *pcidev; 790 struct comedi_subdevice *s; 791 resource_size_t pci_base; 792 int ret = 0; 793 794 dev_dbg(dev->class_dev, "dt3000:\n"); 795 796 ret = alloc_private(dev, sizeof(struct dt3k_private)); 797 if (ret < 0) 798 return ret; 799 800 pcidev = dt3000_find_pci_dev(dev, it); 801 if (!pcidev) 802 return -EIO; 803 comedi_set_hw_dev(dev, &pcidev->dev); 804 805 ret = comedi_pci_enable(pcidev, "dt3000"); 806 if (ret < 0) 807 return ret; 808 dev->iobase = 1; /* the "detach" needs this */ 809 810 pci_base = pci_resource_start(pcidev, 0); 811 devpriv->io_addr = ioremap(pci_base, DT3000_SIZE); 812 if (!devpriv->io_addr) 813 return -ENOMEM; 814 815 dev->board_name = this_board->name; 816 817 if (request_irq(pcidev->irq, dt3k_interrupt, IRQF_SHARED, 818 "dt3000", dev)) { 819 dev_err(dev->class_dev, "unable to allocate IRQ %u\n", 820 pcidev->irq); 821 return -EINVAL; 822 } 823 dev->irq = pcidev->irq; 824 825 ret = comedi_alloc_subdevices(dev, 4); 826 if (ret) 827 return ret; 828 829 s = &dev->subdevices[0]; 830 dev->read_subdev = s; 831 832 /* ai subdevice */ 833 s->type = COMEDI_SUBD_AI; 834 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; 835 s->n_chan = this_board->adchan; 836 s->insn_read = dt3k_ai_insn; 837 s->maxdata = (1 << this_board->adbits) - 1; 838 s->len_chanlist = 512; 839 s->range_table = &range_dt3000_ai; /* XXX */ 840 s->do_cmd = dt3k_ai_cmd; 841 s->do_cmdtest = dt3k_ai_cmdtest; 842 s->cancel = dt3k_ai_cancel; 843 844 s = &dev->subdevices[1]; 845 /* ao subsystem */ 846 s->type = COMEDI_SUBD_AO; 847 s->subdev_flags = SDF_WRITABLE; 848 s->n_chan = 2; 849 s->insn_read = dt3k_ao_insn_read; 850 s->insn_write = dt3k_ao_insn; 851 s->maxdata = (1 << this_board->dabits) - 1; 852 s->len_chanlist = 1; 853 s->range_table = &range_bipolar10; 854 855 s = &dev->subdevices[2]; 856 /* dio subsystem */ 857 s->type = COMEDI_SUBD_DIO; 858 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 859 s->n_chan = 8; 860 s->insn_config = dt3k_dio_insn_config; 861 s->insn_bits = dt3k_dio_insn_bits; 862 s->maxdata = 1; 863 s->len_chanlist = 8; 864 s->range_table = &range_digital; 865 866 s = &dev->subdevices[3]; 867 /* mem subsystem */ 868 s->type = COMEDI_SUBD_MEMORY; 869 s->subdev_flags = SDF_READABLE; 870 s->n_chan = 0x1000; 871 s->insn_read = dt3k_mem_insn_read; 872 s->maxdata = 0xff; 873 s->len_chanlist = 1; 874 s->range_table = &range_unknown; 875 876#if 0 877 s = &dev->subdevices[4]; 878 /* proc subsystem */ 879 s->type = COMEDI_SUBD_PROC; 880#endif 881 882 return 0; 883} 884 885static void dt3000_detach(struct comedi_device *dev) 886{ 887 struct pci_dev *pcidev = comedi_to_pci_dev(dev); 888 889 if (dev->irq) 890 free_irq(dev->irq, dev); 891 if (devpriv) { 892 if (devpriv->io_addr) 893 iounmap(devpriv->io_addr); 894 } 895 if (pcidev) { 896 if (dev->iobase) 897 comedi_pci_disable(pcidev); 898 pci_dev_put(pcidev); 899 } 900} 901 902static struct comedi_driver dt3000_driver = { 903 .driver_name = "dt3000", 904 .module = THIS_MODULE, 905 .attach = dt3000_attach, 906 .detach = dt3000_detach, 907}; 908 909static int __devinit dt3000_pci_probe(struct pci_dev *dev, 910 const struct pci_device_id *ent) 911{ 912 return comedi_pci_auto_config(dev, &dt3000_driver); 913} 914 915static void __devexit dt3000_pci_remove(struct pci_dev *dev) 916{ 917 comedi_pci_auto_unconfig(dev); 918} 919 920static DEFINE_PCI_DEVICE_TABLE(dt3000_pci_table) = { 921 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) }, 922 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) }, 923 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) }, 924 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) }, 925 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) }, 926 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) }, 927 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) }, 928 { 0 } 929}; 930MODULE_DEVICE_TABLE(pci, dt3000_pci_table); 931 932static struct pci_driver dt3000_pci_driver = { 933 .name = "dt3000", 934 .id_table = dt3000_pci_table, 935 .probe = dt3000_pci_probe, 936 .remove = __devexit_p(dt3000_pci_remove), 937}; 938module_comedi_pci_driver(dt3000_driver, dt3000_pci_driver); 939 940MODULE_AUTHOR("Comedi http://www.comedi.org"); 941MODULE_DESCRIPTION("Comedi low-level driver"); 942MODULE_LICENSE("GPL"); 943