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