dt3000.c revision 5cf76a8bf818ffc12e1a7a443eda83c9a4e13452
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_pci.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 n_dt3k_boards sizeof(dt3k_boardtypes)/sizeof(struct dt3k_boardtype) 165#define this_board ((const struct dt3k_boardtype *)dev->board_ptr) 166 167static DEFINE_PCI_DEVICE_TABLE(dt3k_pci_table) = { 168 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0022) }, 169 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0027) }, 170 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0023) }, 171 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0024) }, 172 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0028) }, 173 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0025) }, 174 { PCI_DEVICE(PCI_VENDOR_ID_DT, 0x0026) }, 175 { 0 } 176}; 177 178MODULE_DEVICE_TABLE(pci, dt3k_pci_table); 179 180#define DT3000_SIZE (4*0x1000) 181 182/* dual-ported RAM location definitions */ 183 184#define DPR_DAC_buffer (4*0x000) 185#define DPR_ADC_buffer (4*0x800) 186#define DPR_Command (4*0xfd3) 187#define DPR_SubSys (4*0xfd3) 188#define DPR_Encode (4*0xfd4) 189#define DPR_Params(a) (4*(0xfd5+(a))) 190#define DPR_Tick_Reg_Lo (4*0xff5) 191#define DPR_Tick_Reg_Hi (4*0xff6) 192#define DPR_DA_Buf_Front (4*0xff7) 193#define DPR_DA_Buf_Rear (4*0xff8) 194#define DPR_AD_Buf_Front (4*0xff9) 195#define DPR_AD_Buf_Rear (4*0xffa) 196#define DPR_Int_Mask (4*0xffb) 197#define DPR_Intr_Flag (4*0xffc) 198#define DPR_Response_Mbx (4*0xffe) 199#define DPR_Command_Mbx (4*0xfff) 200 201#define AI_FIFO_DEPTH 2003 202#define AO_FIFO_DEPTH 2048 203 204/* command list */ 205 206#define CMD_GETBRDINFO 0 207#define CMD_CONFIG 1 208#define CMD_GETCONFIG 2 209#define CMD_START 3 210#define CMD_STOP 4 211#define CMD_READSINGLE 5 212#define CMD_WRITESINGLE 6 213#define CMD_CALCCLOCK 7 214#define CMD_READEVENTS 8 215#define CMD_WRITECTCTRL 16 216#define CMD_READCTCTRL 17 217#define CMD_WRITECT 18 218#define CMD_READCT 19 219#define CMD_WRITEDATA 32 220#define CMD_READDATA 33 221#define CMD_WRITEIO 34 222#define CMD_READIO 35 223#define CMD_WRITECODE 36 224#define CMD_READCODE 37 225#define CMD_EXECUTE 38 226#define CMD_HALT 48 227 228#define SUBS_AI 0 229#define SUBS_AO 1 230#define SUBS_DIN 2 231#define SUBS_DOUT 3 232#define SUBS_MEM 4 233#define SUBS_CT 5 234 235/* interrupt flags */ 236#define DT3000_CMDONE 0x80 237#define DT3000_CTDONE 0x40 238#define DT3000_DAHWERR 0x20 239#define DT3000_DASWERR 0x10 240#define DT3000_DAEMPTY 0x08 241#define DT3000_ADHWERR 0x04 242#define DT3000_ADSWERR 0x02 243#define DT3000_ADFULL 0x01 244 245#define DT3000_COMPLETION_MASK 0xff00 246#define DT3000_COMMAND_MASK 0x00ff 247#define DT3000_NOTPROCESSED 0x0000 248#define DT3000_NOERROR 0x5500 249#define DT3000_ERROR 0xaa00 250#define DT3000_NOTSUPPORTED 0xff00 251 252#define DT3000_EXTERNAL_CLOCK 1 253#define DT3000_RISING_EDGE 2 254 255#define TMODE_MASK 0x1c 256 257#define DT3000_AD_TRIG_INTERNAL (0<<2) 258#define DT3000_AD_TRIG_EXTERNAL (1<<2) 259#define DT3000_AD_RETRIG_INTERNAL (2<<2) 260#define DT3000_AD_RETRIG_EXTERNAL (3<<2) 261#define DT3000_AD_EXTRETRIG (4<<2) 262 263#define DT3000_CHANNEL_MODE_SE 0 264#define DT3000_CHANNEL_MODE_DI 1 265 266struct dt3k_private { 267 268 struct pci_dev *pci_dev; 269 resource_size_t phys_addr; 270 void *io_addr; 271 unsigned int lock; 272 unsigned int ao_readback[2]; 273 unsigned int ai_front; 274 unsigned int ai_rear; 275}; 276 277#define devpriv ((struct dt3k_private *)dev->private) 278 279static int dt3000_attach(struct comedi_device *dev, 280 struct comedi_devconfig *it); 281static int dt3000_detach(struct comedi_device *dev); 282static struct comedi_driver driver_dt3000 = { 283 .driver_name = "dt3000", 284 .module = THIS_MODULE, 285 .attach = dt3000_attach, 286 .detach = dt3000_detach, 287}; 288 289static int __devinit driver_dt3000_pci_probe(struct pci_dev *dev, 290 const struct pci_device_id *ent) 291{ 292 return comedi_pci_auto_config(dev, driver_dt3000.driver_name); 293} 294 295static void __devexit driver_dt3000_pci_remove(struct pci_dev *dev) 296{ 297 comedi_pci_auto_unconfig(dev); 298} 299 300static struct pci_driver driver_dt3000_pci_driver = { 301 .id_table = dt3k_pci_table, 302 .probe = &driver_dt3000_pci_probe, 303 .remove = __devexit_p(&driver_dt3000_pci_remove) 304}; 305 306static int __init driver_dt3000_init_module(void) 307{ 308 int retval; 309 310 retval = comedi_driver_register(&driver_dt3000); 311 if (retval < 0) 312 return retval; 313 314 driver_dt3000_pci_driver.name = (char *)driver_dt3000.driver_name; 315 return pci_register_driver(&driver_dt3000_pci_driver); 316} 317 318static void __exit driver_dt3000_cleanup_module(void) 319{ 320 pci_unregister_driver(&driver_dt3000_pci_driver); 321 comedi_driver_unregister(&driver_dt3000); 322} 323 324module_init(driver_dt3000_init_module); 325module_exit(driver_dt3000_cleanup_module); 326 327static void dt3k_ai_empty_fifo(struct comedi_device *dev, 328 struct comedi_subdevice *s); 329static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *arg, 330 unsigned int round_mode); 331static int dt3k_ai_cancel(struct comedi_device *dev, 332 struct comedi_subdevice *s); 333#ifdef DEBUG 334static void debug_intr_flags(unsigned int flags); 335#endif 336 337#define TIMEOUT 100 338 339static int dt3k_send_cmd(struct comedi_device *dev, unsigned int cmd) 340{ 341 int i; 342 unsigned int status = 0; 343 344 writew(cmd, devpriv->io_addr + DPR_Command_Mbx); 345 346 for (i = 0; i < TIMEOUT; i++) { 347 status = readw(devpriv->io_addr + DPR_Command_Mbx); 348 if ((status & DT3000_COMPLETION_MASK) != DT3000_NOTPROCESSED) 349 break; 350 udelay(1); 351 } 352 if ((status & DT3000_COMPLETION_MASK) == DT3000_NOERROR) 353 return 0; 354 355 dev_dbg(dev->hw_dev, "dt3k_send_cmd() timeout/error status=0x%04x\n", 356 status); 357 358 return -ETIME; 359} 360 361static unsigned int dt3k_readsingle(struct comedi_device *dev, 362 unsigned int subsys, unsigned int chan, 363 unsigned int gain) 364{ 365 writew(subsys, devpriv->io_addr + DPR_SubSys); 366 367 writew(chan, devpriv->io_addr + DPR_Params(0)); 368 writew(gain, devpriv->io_addr + DPR_Params(1)); 369 370 dt3k_send_cmd(dev, CMD_READSINGLE); 371 372 return readw(devpriv->io_addr + DPR_Params(2)); 373} 374 375static void dt3k_writesingle(struct comedi_device *dev, unsigned int subsys, 376 unsigned int chan, unsigned int data) 377{ 378 writew(subsys, devpriv->io_addr + DPR_SubSys); 379 380 writew(chan, devpriv->io_addr + DPR_Params(0)); 381 writew(0, devpriv->io_addr + DPR_Params(1)); 382 writew(data, devpriv->io_addr + DPR_Params(2)); 383 384 dt3k_send_cmd(dev, CMD_WRITESINGLE); 385} 386 387static int debug_n_ints; 388 389/* FIXME! Assumes shared interrupt is for this card. */ 390/* What's this debug_n_ints stuff? Obviously needs some work... */ 391static irqreturn_t dt3k_interrupt(int irq, void *d) 392{ 393 struct comedi_device *dev = d; 394 struct comedi_subdevice *s; 395 unsigned int status; 396 397 if (!dev->attached) 398 return IRQ_NONE; 399 400 s = dev->subdevices + 0; 401 status = readw(devpriv->io_addr + DPR_Intr_Flag); 402#ifdef DEBUG 403 debug_intr_flags(status); 404#endif 405 406 if (status & DT3000_ADFULL) { 407 dt3k_ai_empty_fifo(dev, s); 408 s->async->events |= COMEDI_CB_BLOCK; 409 } 410 411 if (status & (DT3000_ADSWERR | DT3000_ADHWERR)) 412 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 413 414 debug_n_ints++; 415 if (debug_n_ints >= 10) { 416 dt3k_ai_cancel(dev, s); 417 s->async->events |= COMEDI_CB_EOA; 418 } 419 420 comedi_event(dev, s); 421 return IRQ_HANDLED; 422} 423 424#ifdef DEBUG 425static char *intr_flags[] = { 426 "AdFull", "AdSwError", "AdHwError", "DaEmpty", 427 "DaSwError", "DaHwError", "CtDone", "CmDone", 428}; 429 430static void debug_intr_flags(unsigned int flags) 431{ 432 int i; 433 printk(KERN_DEBUG "dt3k: intr_flags:"); 434 for (i = 0; i < 8; i++) { 435 if (flags & (1 << i)) 436 printk(KERN_CONT " %s", intr_flags[i]); 437 } 438 printk(KERN_CONT "\n"); 439} 440#endif 441 442static void dt3k_ai_empty_fifo(struct comedi_device *dev, 443 struct comedi_subdevice *s) 444{ 445 int front; 446 int rear; 447 int count; 448 int i; 449 short data; 450 451 front = readw(devpriv->io_addr + DPR_AD_Buf_Front); 452 count = front - devpriv->ai_front; 453 if (count < 0) 454 count += AI_FIFO_DEPTH; 455 456 dev_dbg(dev->hw_dev, "reading %d samples\n", count); 457 458 rear = devpriv->ai_rear; 459 460 for (i = 0; i < count; i++) { 461 data = readw(devpriv->io_addr + DPR_ADC_buffer + rear); 462 comedi_buf_put(s->async, data); 463 rear++; 464 if (rear >= AI_FIFO_DEPTH) 465 rear = 0; 466 } 467 468 devpriv->ai_rear = rear; 469 writew(rear, devpriv->io_addr + DPR_AD_Buf_Rear); 470} 471 472static int dt3k_ai_cmdtest(struct comedi_device *dev, 473 struct comedi_subdevice *s, struct comedi_cmd *cmd) 474{ 475 int err = 0; 476 int tmp; 477 478 /* step 1: make sure trigger sources are trivially valid */ 479 480 tmp = cmd->start_src; 481 cmd->start_src &= TRIG_NOW; 482 if (!cmd->start_src || tmp != cmd->start_src) 483 err++; 484 485 tmp = cmd->scan_begin_src; 486 cmd->scan_begin_src &= TRIG_TIMER; 487 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 488 err++; 489 490 tmp = cmd->convert_src; 491 cmd->convert_src &= TRIG_TIMER; 492 if (!cmd->convert_src || tmp != cmd->convert_src) 493 err++; 494 495 tmp = cmd->scan_end_src; 496 cmd->scan_end_src &= TRIG_COUNT; 497 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 498 err++; 499 500 tmp = cmd->stop_src; 501 cmd->stop_src &= TRIG_COUNT; 502 if (!cmd->stop_src || tmp != cmd->stop_src) 503 err++; 504 505 if (err) 506 return 1; 507 508 /* step 2: make sure trigger sources are unique and mutually compatible */ 509 510 if (err) 511 return 2; 512 513 /* step 3: make sure arguments are trivially compatible */ 514 515 if (cmd->start_arg != 0) { 516 cmd->start_arg = 0; 517 err++; 518 } 519 520 if (cmd->scan_begin_src == TRIG_TIMER) { 521 if (cmd->scan_begin_arg < this_board->ai_speed) { 522 cmd->scan_begin_arg = this_board->ai_speed; 523 err++; 524 } 525 if (cmd->scan_begin_arg > 100 * 16 * 65535) { 526 cmd->scan_begin_arg = 100 * 16 * 65535; 527 err++; 528 } 529 } else { 530 /* not supported */ 531 } 532 if (cmd->convert_src == TRIG_TIMER) { 533 if (cmd->convert_arg < this_board->ai_speed) { 534 cmd->convert_arg = this_board->ai_speed; 535 err++; 536 } 537 if (cmd->convert_arg > 50 * 16 * 65535) { 538 cmd->convert_arg = 50 * 16 * 65535; 539 err++; 540 } 541 } else { 542 /* not supported */ 543 } 544 545 if (cmd->scan_end_arg != cmd->chanlist_len) { 546 cmd->scan_end_arg = cmd->chanlist_len; 547 err++; 548 } 549 if (cmd->stop_src == TRIG_COUNT) { 550 if (cmd->stop_arg > 0x00ffffff) { 551 cmd->stop_arg = 0x00ffffff; 552 err++; 553 } 554 } else { 555 /* TRIG_NONE */ 556 if (cmd->stop_arg != 0) { 557 cmd->stop_arg = 0; 558 err++; 559 } 560 } 561 562 if (err) 563 return 3; 564 565 /* step 4: fix up any arguments */ 566 567 if (cmd->scan_begin_src == TRIG_TIMER) { 568 tmp = cmd->scan_begin_arg; 569 dt3k_ns_to_timer(100, &cmd->scan_begin_arg, 570 cmd->flags & TRIG_ROUND_MASK); 571 if (tmp != cmd->scan_begin_arg) 572 err++; 573 } else { 574 /* not supported */ 575 } 576 if (cmd->convert_src == TRIG_TIMER) { 577 tmp = cmd->convert_arg; 578 dt3k_ns_to_timer(50, &cmd->convert_arg, 579 cmd->flags & TRIG_ROUND_MASK); 580 if (tmp != cmd->convert_arg) 581 err++; 582 if (cmd->scan_begin_src == TRIG_TIMER && 583 cmd->scan_begin_arg < 584 cmd->convert_arg * cmd->scan_end_arg) { 585 cmd->scan_begin_arg = 586 cmd->convert_arg * cmd->scan_end_arg; 587 err++; 588 } 589 } else { 590 /* not supported */ 591 } 592 593 if (err) 594 return 4; 595 596 return 0; 597} 598 599static int dt3k_ns_to_timer(unsigned int timer_base, unsigned int *nanosec, 600 unsigned int round_mode) 601{ 602 int divider, base, prescale; 603 604 /* This function needs improvment */ 605 /* Don't know if divider==0 works. */ 606 607 for (prescale = 0; prescale < 16; prescale++) { 608 base = timer_base * (prescale + 1); 609 switch (round_mode) { 610 case TRIG_ROUND_NEAREST: 611 default: 612 divider = (*nanosec + base / 2) / base; 613 break; 614 case TRIG_ROUND_DOWN: 615 divider = (*nanosec) / base; 616 break; 617 case TRIG_ROUND_UP: 618 divider = (*nanosec) / base; 619 break; 620 } 621 if (divider < 65536) { 622 *nanosec = divider * base; 623 return (prescale << 16) | (divider); 624 } 625 } 626 627 prescale = 15; 628 base = timer_base * (1 << prescale); 629 divider = 65535; 630 *nanosec = divider * base; 631 return (prescale << 16) | (divider); 632} 633 634static int dt3k_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 635{ 636 struct comedi_cmd *cmd = &s->async->cmd; 637 int i; 638 unsigned int chan, range, aref; 639 unsigned int divider; 640 unsigned int tscandiv; 641 int ret; 642 unsigned int mode; 643 644 dev_dbg(dev->hw_dev, "dt3k_ai_cmd:\n"); 645 for (i = 0; i < cmd->chanlist_len; i++) { 646 chan = CR_CHAN(cmd->chanlist[i]); 647 range = CR_RANGE(cmd->chanlist[i]); 648 649 writew((range << 6) | chan, 650 devpriv->io_addr + DPR_ADC_buffer + i); 651 } 652 aref = CR_AREF(cmd->chanlist[0]); 653 654 writew(cmd->scan_end_arg, devpriv->io_addr + DPR_Params(0)); 655 dev_dbg(dev->hw_dev, "param[0]=0x%04x\n", cmd->scan_end_arg); 656 657 if (cmd->convert_src == TRIG_TIMER) { 658 divider = dt3k_ns_to_timer(50, &cmd->convert_arg, 659 cmd->flags & TRIG_ROUND_MASK); 660 writew((divider >> 16), devpriv->io_addr + DPR_Params(1)); 661 dev_dbg(dev->hw_dev, "param[1]=0x%04x\n", divider >> 16); 662 writew((divider & 0xffff), devpriv->io_addr + DPR_Params(2)); 663 dev_dbg(dev->hw_dev, "param[2]=0x%04x\n", divider & 0xffff); 664 } else { 665 /* not supported */ 666 } 667 668 if (cmd->scan_begin_src == TRIG_TIMER) { 669 tscandiv = dt3k_ns_to_timer(100, &cmd->scan_begin_arg, 670 cmd->flags & TRIG_ROUND_MASK); 671 writew((tscandiv >> 16), devpriv->io_addr + DPR_Params(3)); 672 printk("param[3]=0x%04x\n", tscandiv >> 16); 673 writew((tscandiv & 0xffff), devpriv->io_addr + DPR_Params(4)); 674 printk("param[4]=0x%04x\n", tscandiv & 0xffff); 675 } else { 676 /* not supported */ 677 } 678 679 mode = DT3000_AD_RETRIG_INTERNAL | 0 | 0; 680 writew(mode, devpriv->io_addr + DPR_Params(5)); 681 printk("param[5]=0x%04x\n", mode); 682 writew(aref == AREF_DIFF, devpriv->io_addr + DPR_Params(6)); 683 printk("param[6]=0x%04x\n", aref == AREF_DIFF); 684 685 writew(AI_FIFO_DEPTH / 2, devpriv->io_addr + DPR_Params(7)); 686 printk("param[7]=0x%04x\n", AI_FIFO_DEPTH / 2); 687 688 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 689 ret = dt3k_send_cmd(dev, CMD_CONFIG); 690 691 writew(DT3000_ADFULL | DT3000_ADSWERR | DT3000_ADHWERR, 692 devpriv->io_addr + DPR_Int_Mask); 693 694 debug_n_ints = 0; 695 696 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 697 ret = dt3k_send_cmd(dev, CMD_START); 698 699 return 0; 700} 701 702static int dt3k_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s) 703{ 704 int ret; 705 706 writew(SUBS_AI, devpriv->io_addr + DPR_SubSys); 707 ret = dt3k_send_cmd(dev, CMD_STOP); 708 709 writew(0, devpriv->io_addr + DPR_Int_Mask); 710 711 return 0; 712} 713 714static int dt3k_ai_insn(struct comedi_device *dev, struct comedi_subdevice *s, 715 struct comedi_insn *insn, unsigned int *data) 716{ 717 int i; 718 unsigned int chan, gain, aref; 719 720 chan = CR_CHAN(insn->chanspec); 721 gain = CR_RANGE(insn->chanspec); 722 /* XXX docs don't explain how to select aref */ 723 aref = CR_AREF(insn->chanspec); 724 725 for (i = 0; i < insn->n; i++) 726 data[i] = dt3k_readsingle(dev, SUBS_AI, chan, gain); 727 728 return i; 729} 730 731static int dt3k_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s, 732 struct comedi_insn *insn, unsigned int *data) 733{ 734 int i; 735 unsigned int chan; 736 737 chan = CR_CHAN(insn->chanspec); 738 for (i = 0; i < insn->n; i++) { 739 dt3k_writesingle(dev, SUBS_AO, chan, data[i]); 740 devpriv->ao_readback[chan] = data[i]; 741 } 742 743 return i; 744} 745 746static int dt3k_ao_insn_read(struct comedi_device *dev, 747 struct comedi_subdevice *s, 748 struct comedi_insn *insn, unsigned int *data) 749{ 750 int i; 751 unsigned int chan; 752 753 chan = CR_CHAN(insn->chanspec); 754 for (i = 0; i < insn->n; i++) 755 data[i] = devpriv->ao_readback[chan]; 756 757 return i; 758} 759 760static void dt3k_dio_config(struct comedi_device *dev, int bits) 761{ 762 /* XXX */ 763 writew(SUBS_DOUT, devpriv->io_addr + DPR_SubSys); 764 765 writew(bits, devpriv->io_addr + DPR_Params(0)); 766#if 0 767 /* don't know */ 768 writew(0, devpriv->io_addr + DPR_Params(1)); 769 writew(0, devpriv->io_addr + DPR_Params(2)); 770#endif 771 772 dt3k_send_cmd(dev, CMD_CONFIG); 773} 774 775static int dt3k_dio_insn_config(struct comedi_device *dev, 776 struct comedi_subdevice *s, 777 struct comedi_insn *insn, unsigned int *data) 778{ 779 int mask; 780 781 mask = (CR_CHAN(insn->chanspec) < 4) ? 0x0f : 0xf0; 782 783 switch (data[0]) { 784 case INSN_CONFIG_DIO_OUTPUT: 785 s->io_bits |= mask; 786 break; 787 case INSN_CONFIG_DIO_INPUT: 788 s->io_bits &= ~mask; 789 break; 790 case INSN_CONFIG_DIO_QUERY: 791 data[1] = 792 (s-> 793 io_bits & (1 << CR_CHAN(insn->chanspec))) ? COMEDI_OUTPUT : 794 COMEDI_INPUT; 795 return insn->n; 796 break; 797 default: 798 return -EINVAL; 799 break; 800 } 801 mask = (s->io_bits & 0x01) | ((s->io_bits & 0x10) >> 3); 802 dt3k_dio_config(dev, mask); 803 804 return insn->n; 805} 806 807static int dt3k_dio_insn_bits(struct comedi_device *dev, 808 struct comedi_subdevice *s, 809 struct comedi_insn *insn, unsigned int *data) 810{ 811 if (insn->n != 2) 812 return -EINVAL; 813 814 if (data[0]) { 815 s->state &= ~data[0]; 816 s->state |= data[1] & data[0]; 817 dt3k_writesingle(dev, SUBS_DOUT, 0, s->state); 818 } 819 data[1] = dt3k_readsingle(dev, SUBS_DIN, 0, 0); 820 821 return 2; 822} 823 824static int dt3k_mem_insn_read(struct comedi_device *dev, 825 struct comedi_subdevice *s, 826 struct comedi_insn *insn, unsigned int *data) 827{ 828 unsigned int addr = CR_CHAN(insn->chanspec); 829 int i; 830 831 for (i = 0; i < insn->n; i++) { 832 writew(SUBS_MEM, devpriv->io_addr + DPR_SubSys); 833 writew(addr, devpriv->io_addr + DPR_Params(0)); 834 writew(1, devpriv->io_addr + DPR_Params(1)); 835 836 dt3k_send_cmd(dev, CMD_READCODE); 837 838 data[i] = readw(devpriv->io_addr + DPR_Params(2)); 839 } 840 841 return i; 842} 843 844static int dt_pci_probe(struct comedi_device *dev, int bus, int slot); 845 846static int dt3000_attach(struct comedi_device *dev, struct comedi_devconfig *it) 847{ 848 struct comedi_subdevice *s; 849 int bus, slot; 850 int ret = 0; 851 852 dev_dbg(dev->hw_dev, "dt3000:\n"); 853 bus = it->options[0]; 854 slot = it->options[1]; 855 856 ret = alloc_private(dev, sizeof(struct dt3k_private)); 857 if (ret < 0) 858 return ret; 859 860 ret = dt_pci_probe(dev, bus, slot); 861 if (ret < 0) 862 return ret; 863 if (ret == 0) { 864 dev_warn(dev->hw_dev, "no DT board found\n"); 865 return -ENODEV; 866 } 867 868 dev->board_name = this_board->name; 869 870 if (request_irq(devpriv->pci_dev->irq, dt3k_interrupt, IRQF_SHARED, 871 "dt3000", dev)) { 872 dev_err(dev->hw_dev, "unable to allocate IRQ %u\n", 873 devpriv->pci_dev->irq); 874 return -EINVAL; 875 } 876 dev->irq = devpriv->pci_dev->irq; 877 878 ret = alloc_subdevices(dev, 4); 879 if (ret < 0) 880 return ret; 881 882 s = dev->subdevices; 883 dev->read_subdev = s; 884 885 /* ai subdevice */ 886 s->type = COMEDI_SUBD_AI; 887 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ; 888 s->n_chan = this_board->adchan; 889 s->insn_read = dt3k_ai_insn; 890 s->maxdata = (1 << this_board->adbits) - 1; 891 s->len_chanlist = 512; 892 s->range_table = &range_dt3000_ai; /* XXX */ 893 s->do_cmd = dt3k_ai_cmd; 894 s->do_cmdtest = dt3k_ai_cmdtest; 895 s->cancel = dt3k_ai_cancel; 896 897 s++; 898 /* ao subsystem */ 899 s->type = COMEDI_SUBD_AO; 900 s->subdev_flags = SDF_WRITABLE; 901 s->n_chan = 2; 902 s->insn_read = dt3k_ao_insn_read; 903 s->insn_write = dt3k_ao_insn; 904 s->maxdata = (1 << this_board->dabits) - 1; 905 s->len_chanlist = 1; 906 s->range_table = &range_bipolar10; 907 908 s++; 909 /* dio subsystem */ 910 s->type = COMEDI_SUBD_DIO; 911 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 912 s->n_chan = 8; 913 s->insn_config = dt3k_dio_insn_config; 914 s->insn_bits = dt3k_dio_insn_bits; 915 s->maxdata = 1; 916 s->len_chanlist = 8; 917 s->range_table = &range_digital; 918 919 s++; 920 /* mem subsystem */ 921 s->type = COMEDI_SUBD_MEMORY; 922 s->subdev_flags = SDF_READABLE; 923 s->n_chan = 0x1000; 924 s->insn_read = dt3k_mem_insn_read; 925 s->maxdata = 0xff; 926 s->len_chanlist = 1; 927 s->range_table = &range_unknown; 928 929#if 0 930 s++; 931 /* proc subsystem */ 932 s->type = COMEDI_SUBD_PROC; 933#endif 934 935 return 0; 936} 937 938static int dt3000_detach(struct comedi_device *dev) 939{ 940 if (dev->irq) 941 free_irq(dev->irq, dev); 942 943 if (devpriv) { 944 if (devpriv->pci_dev) { 945 if (devpriv->phys_addr) 946 comedi_pci_disable(devpriv->pci_dev); 947 pci_dev_put(devpriv->pci_dev); 948 } 949 if (devpriv->io_addr) 950 iounmap(devpriv->io_addr); 951 } 952 /* XXX */ 953 954 return 0; 955} 956 957static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board); 958static int setup_pci(struct comedi_device *dev); 959 960static int dt_pci_probe(struct comedi_device *dev, int bus, int slot) 961{ 962 int board; 963 int ret; 964 struct pci_dev *pcidev; 965 966 pcidev = NULL; 967 while ((pcidev = dt_pci_find_device(pcidev, &board)) != NULL) { 968 if ((bus == 0 && slot == 0) || 969 (pcidev->bus->number == bus && 970 PCI_SLOT(pcidev->devfn) == slot)) { 971 break; 972 } 973 } 974 devpriv->pci_dev = pcidev; 975 976 if (board >= 0) 977 dev->board_ptr = dt3k_boardtypes + board; 978 979 if (!devpriv->pci_dev) 980 return 0; 981 982 ret = setup_pci(dev); 983 if (ret < 0) 984 return ret; 985 986 return 1; 987} 988 989static int setup_pci(struct comedi_device *dev) 990{ 991 resource_size_t addr; 992 int ret; 993 994 ret = comedi_pci_enable(devpriv->pci_dev, "dt3000"); 995 if (ret < 0) 996 return ret; 997 998 addr = pci_resource_start(devpriv->pci_dev, 0); 999 devpriv->phys_addr = addr; 1000 devpriv->io_addr = ioremap(devpriv->phys_addr, DT3000_SIZE); 1001 if (!devpriv->io_addr) 1002 return -ENOMEM; 1003#if DEBUG 1004 printk("0x%08llx mapped to %p, ", 1005 (unsigned long long)devpriv->phys_addr, devpriv->io_addr); 1006#endif 1007 1008 return 0; 1009} 1010 1011static struct pci_dev *dt_pci_find_device(struct pci_dev *from, int *board) 1012{ 1013 int i; 1014 1015 for (from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from); 1016 from != NULL; 1017 from = pci_get_device(PCI_VENDOR_ID_DT, PCI_ANY_ID, from)) { 1018 for (i = 0; i < n_dt3k_boards; i++) { 1019 if (from->device == dt3k_boardtypes[i].device_id) { 1020 *board = i; 1021 return from; 1022 } 1023 } 1024 printk 1025 ("unknown Data Translation PCI device found with device_id=0x%04x\n", 1026 from->device); 1027 } 1028 *board = -1; 1029 return from; 1030} 1031 1032MODULE_AUTHOR("Comedi http://www.comedi.org"); 1033MODULE_DESCRIPTION("Comedi low-level driver"); 1034MODULE_LICENSE("GPL"); 1035