adl_pci9111.c revision 8c7524e6f0b7d3ca70b957e032ee4f761c7deddf
1/* 2 3comedi/drivers/adl_pci9111.c 4 5Hardware driver for PCI9111 ADLink cards: 6 7PCI-9111HR 8 9Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> 10 11This program is free software; you can redistribute it and/or modify 12it under the terms of the GNU General Public License as published by 13the Free Software Foundation; either version 2 of the License, or 14(at your option) any later version. 15 16This program is distributed in the hope that it will be useful, 17but WITHOUT ANY WARRANTY; without even the implied warranty of 18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19GNU General Public License for more details. 20 21You should have received a copy of the GNU General Public License 22along with this program; if not, write to the Free Software 23Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 24*/ 25 26/* 27Driver: adl_pci9111 28Description: Adlink PCI-9111HR 29Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> 30Devices: [ADLink] PCI-9111HR (adl_pci9111) 31Status: experimental 32 33Supports: 34 35 - ai_insn read 36 - ao_insn read/write 37 - di_insn read 38 - do_insn read/write 39 - ai_do_cmd mode with the following sources: 40 41 - start_src TRIG_NOW 42 - scan_begin_src TRIG_FOLLOW TRIG_TIMER TRIG_EXT 43 - convert_src TRIG_TIMER TRIG_EXT 44 - scan_end_src TRIG_COUNT 45 - stop_src TRIG_COUNT TRIG_NONE 46 47The scanned channels must be consecutive and start from 0. They must 48all have the same range and aref. 49 50Configuration options: not applicable, uses PCI auto config 51*/ 52 53/* 54CHANGELOG: 55 562005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be 57a multiple of chanlist_len*convert_arg. 582002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data. 592002/02/18 Added external trigger support for analog input. 60 61TODO: 62 63 - Really test implemented functionality. 64 - Add support for the PCI-9111DG with a probe routine to identify 65 the card type (perhaps with the help of the channel number readback 66 of the A/D Data register). 67 - Add external multiplexer support. 68 69*/ 70 71#include "../comedidev.h" 72 73#include <linux/delay.h> 74#include <linux/interrupt.h> 75 76#include "8253.h" 77#include "comedi_fc.h" 78 79#define PCI9111_DRIVER_NAME "adl_pci9111" 80#define PCI9111_HR_DEVICE_ID 0x9111 81 82#define PCI9111_FIFO_HALF_SIZE 512 83 84#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 85 86#define PCI9111_RANGE_SETTING_DELAY 10 87#define PCI9111_AI_INSTANT_READ_UDELAY_US 2 88#define PCI9111_AI_INSTANT_READ_TIMEOUT 100 89 90#define PCI9111_8254_CLOCK_PERIOD_NS 500 91 92/* 93 * IO address map and bit defines 94 */ 95#define PCI9111_AI_FIFO_REG 0x00 96#define PCI9111_AO_REG 0x00 97#define PCI9111_DIO_REG 0x02 98#define PCI9111_EDIO_REG 0x04 99#define PCI9111_AI_CHANNEL_REG 0x06 100#define PCI9111_AI_RANGE_STAT_REG 0x08 101#define PCI9111_AI_STAT_AD_BUSY (1 << 7) 102#define PCI9111_AI_STAT_FF_FF (1 << 6) 103#define PCI9111_AI_STAT_FF_HF (1 << 5) 104#define PCI9111_AI_STAT_FF_EF (1 << 4) 105#define PCI9111_AI_RANGE_MASK (7 << 0) 106#define PCI9111_AI_TRIG_CTRL_REG 0x0a 107#define PCI9111_AI_TRIG_CTRL_TRGEVENT (1 << 5) 108#define PCI9111_AI_TRIG_CTRL_POTRG (1 << 4) 109#define PCI9111_AI_TRIG_CTRL_PTRG (1 << 3) 110#define PCI9111_AI_TRIG_CTRL_ETIS (1 << 2) 111#define PCI9111_AI_TRIG_CTRL_TPST (1 << 1) 112#define PCI9111_AI_TRIG_CTRL_ASCAN (1 << 0) 113#define PCI9111_INT_CTRL_REG 0x0c 114#define PCI9111_INT_CTRL_ISC2 (1 << 3) 115#define PCI9111_INT_CTRL_FFEN (1 << 2) 116#define PCI9111_INT_CTRL_ISC1 (1 << 1) 117#define PCI9111_INT_CTRL_ISC0 (1 << 0) 118#define PCI9111_SOFT_TRIG_REG 0x0e 119#define PCI9111_8254_BASE_REG 0x40 120#define PCI9111_INT_CLR_REG 0x48 121 122static const struct comedi_lrange pci9111_hr_ai_range = { 123 5, 124 { 125 BIP_RANGE(10), 126 BIP_RANGE(5), 127 BIP_RANGE(2.5), 128 BIP_RANGE(1.25), 129 BIP_RANGE(0.625) 130 } 131}; 132 133/* Private data structure */ 134 135struct pci9111_private_data { 136 unsigned long lcr_io_base; /* Local configuration register base 137 * address */ 138 139 int stop_counter; 140 int stop_is_none; 141 142 unsigned int scan_delay; 143 unsigned int chanlist_len; 144 unsigned int chunk_counter; 145 unsigned int chunk_num_samples; 146 147 int ao_readback; /* Last written analog output data */ 148 149 unsigned int timer_divisor_1; /* Divisor values for the 8254 timer 150 * pacer */ 151 unsigned int timer_divisor_2; 152 153 int is_valid; /* Is device valid */ 154 155 short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; 156}; 157 158/* ------------------------------------------------------------------ */ 159/* PLX9050 SECTION */ 160/* ------------------------------------------------------------------ */ 161 162#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c 163 164#define PLX9050_LINTI1_ENABLE (1 << 0) 165#define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1) 166#define PLX9050_LINTI1_STATUS (1 << 2) 167#define PLX9050_LINTI2_ENABLE (1 << 3) 168#define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4) 169#define PLX9050_LINTI2_STATUS (1 << 5) 170#define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6) 171#define PLX9050_SOFTWARE_INTERRUPT (1 << 7) 172 173static void plx9050_interrupt_control(unsigned long io_base, 174 bool LINTi1_enable, 175 bool LINTi1_active_high, 176 bool LINTi2_enable, 177 bool LINTi2_active_high, 178 bool interrupt_enable) 179{ 180 int flags = 0; 181 182 if (LINTi1_enable) 183 flags |= PLX9050_LINTI1_ENABLE; 184 if (LINTi1_active_high) 185 flags |= PLX9050_LINTI1_ACTIVE_HIGH; 186 if (LINTi2_enable) 187 flags |= PLX9050_LINTI2_ENABLE; 188 if (LINTi2_active_high) 189 flags |= PLX9050_LINTI2_ACTIVE_HIGH; 190 191 if (interrupt_enable) 192 flags |= PLX9050_PCI_INTERRUPT_ENABLE; 193 194 outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); 195} 196 197/* ------------------------------------------------------------------ */ 198/* MISCELLANEOUS SECTION */ 199/* ------------------------------------------------------------------ */ 200 201/* 8254 timer */ 202 203static void pci9111_timer_set(struct comedi_device *dev) 204{ 205 struct pci9111_private_data *dev_private = dev->private; 206 unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG; 207 208 i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY); 209 i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY); 210 i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY); 211 212 udelay(1); 213 214 i8254_write(timer_base, 1, 2, dev_private->timer_divisor_2); 215 i8254_write(timer_base, 1, 1, dev_private->timer_divisor_1); 216} 217 218enum pci9111_trigger_sources { 219 software, 220 timer_pacer, 221 external 222}; 223 224static void pci9111_trigger_source_set(struct comedi_device *dev, 225 enum pci9111_trigger_sources source) 226{ 227 int flags; 228 229 /* Read the current trigger mode control bits */ 230 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 231 /* Mask off the EITS and TPST bits */ 232 flags &= 0x9; 233 234 switch (source) { 235 case software: 236 break; 237 238 case timer_pacer: 239 flags |= PCI9111_AI_TRIG_CTRL_TPST; 240 break; 241 242 case external: 243 flags |= PCI9111_AI_TRIG_CTRL_ETIS; 244 break; 245 } 246 247 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 248} 249 250static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger) 251{ 252 int flags; 253 254 /* Read the current trigger mode control bits */ 255 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 256 /* Mask off the PTRG bit */ 257 flags &= 0x7; 258 259 if (pretrigger) 260 flags |= PCI9111_AI_TRIG_CTRL_PTRG; 261 262 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 263} 264 265static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan) 266{ 267 int flags; 268 269 /* Read the current trigger mode control bits */ 270 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 271 /* Mask off the ASCAN bit */ 272 flags &= 0xe; 273 274 if (autoscan) 275 flags |= PCI9111_AI_TRIG_CTRL_ASCAN; 276 277 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 278} 279 280enum pci9111_ISC0_sources { 281 irq_on_eoc, 282 irq_on_fifo_half_full 283}; 284 285enum pci9111_ISC1_sources { 286 irq_on_timer_tick, 287 irq_on_external_trigger 288}; 289 290static void pci9111_interrupt_source_set(struct comedi_device *dev, 291 enum pci9111_ISC0_sources irq_0_source, 292 enum pci9111_ISC1_sources irq_1_source) 293{ 294 int flags; 295 296 /* Read the current interrupt control bits */ 297 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 298 /* Shift the bits so they are compatible with the write register */ 299 flags >>= 4; 300 /* Mask off the ISCx bits */ 301 flags &= 0xc0; 302 303 /* Now set the new ISCx bits */ 304 if (irq_0_source == irq_on_fifo_half_full) 305 flags |= PCI9111_INT_CTRL_ISC0; 306 307 if (irq_1_source == irq_on_external_trigger) 308 flags |= PCI9111_INT_CTRL_ISC1; 309 310 outb(flags, dev->iobase + PCI9111_INT_CTRL_REG); 311} 312 313static void pci9111_fifo_reset(struct comedi_device *dev) 314{ 315 unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG; 316 317 /* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */ 318 outb(0, int_ctrl_reg); 319 outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg); 320 outb(0, int_ctrl_reg); 321} 322 323/* ------------------------------------------------------------------ */ 324/* HARDWARE TRIGGERED ANALOG INPUT SECTION */ 325/* ------------------------------------------------------------------ */ 326 327/* Cancel analog input autoscan */ 328 329static int pci9111_ai_cancel(struct comedi_device *dev, 330 struct comedi_subdevice *s) 331{ 332 struct pci9111_private_data *dev_private = dev->private; 333 334 /* Disable interrupts */ 335 336 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 337 true, false); 338 339 pci9111_trigger_source_set(dev, software); 340 341 pci9111_autoscan_set(dev, false); 342 343 pci9111_fifo_reset(dev); 344 345 return 0; 346} 347 348/* Test analog input command */ 349 350#define pci9111_check_trigger_src(src, flags) do { \ 351 tmp = src; \ 352 src &= flags; \ 353 if (!src || tmp != src) \ 354 error++; \ 355 } while (false); 356 357static int 358pci9111_ai_do_cmd_test(struct comedi_device *dev, 359 struct comedi_subdevice *s, struct comedi_cmd *cmd) 360{ 361 struct pci9111_private_data *dev_private = dev->private; 362 int tmp; 363 int error = 0; 364 int range, reference; 365 int i; 366 367 /* Step 1 : check if trigger are trivialy valid */ 368 369 pci9111_check_trigger_src(cmd->start_src, TRIG_NOW); 370 pci9111_check_trigger_src(cmd->scan_begin_src, 371 TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); 372 pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT); 373 pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT); 374 pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE); 375 376 if (error) 377 return 1; 378 379 /* step 2 : make sure trigger sources are unique and mutually 380 * compatible */ 381 382 if (cmd->start_src != TRIG_NOW) 383 error++; 384 385 if ((cmd->scan_begin_src != TRIG_TIMER) && 386 (cmd->scan_begin_src != TRIG_FOLLOW) && 387 (cmd->scan_begin_src != TRIG_EXT)) 388 error++; 389 390 if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) 391 error++; 392 if ((cmd->convert_src == TRIG_TIMER) && 393 !((cmd->scan_begin_src == TRIG_TIMER) || 394 (cmd->scan_begin_src == TRIG_FOLLOW))) 395 error++; 396 if ((cmd->convert_src == TRIG_EXT) && 397 !((cmd->scan_begin_src == TRIG_EXT) || 398 (cmd->scan_begin_src == TRIG_FOLLOW))) 399 error++; 400 401 402 if (cmd->scan_end_src != TRIG_COUNT) 403 error++; 404 if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE)) 405 error++; 406 407 if (error) 408 return 2; 409 410 /* Step 3 : make sure arguments are trivialy compatible */ 411 412 if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) { 413 cmd->start_arg = 0; 414 error++; 415 } 416 417 if ((cmd->convert_src == TRIG_TIMER) && 418 (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) { 419 cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS; 420 error++; 421 } 422 if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) { 423 cmd->convert_arg = 0; 424 error++; 425 } 426 427 if ((cmd->scan_begin_src == TRIG_TIMER) && 428 (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) { 429 cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS; 430 error++; 431 } 432 if ((cmd->scan_begin_src == TRIG_FOLLOW) 433 && (cmd->scan_begin_arg != 0)) { 434 cmd->scan_begin_arg = 0; 435 error++; 436 } 437 if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) { 438 cmd->scan_begin_arg = 0; 439 error++; 440 } 441 442 if ((cmd->scan_end_src == TRIG_COUNT) && 443 (cmd->scan_end_arg != cmd->chanlist_len)) { 444 cmd->scan_end_arg = cmd->chanlist_len; 445 error++; 446 } 447 448 if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) { 449 cmd->stop_arg = 1; 450 error++; 451 } 452 if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) { 453 cmd->stop_arg = 0; 454 error++; 455 } 456 457 if (error) 458 return 3; 459 460 /* Step 4 : fix up any arguments */ 461 462 if (cmd->convert_src == TRIG_TIMER) { 463 tmp = cmd->convert_arg; 464 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, 465 &(dev_private->timer_divisor_1), 466 &(dev_private->timer_divisor_2), 467 &(cmd->convert_arg), 468 cmd->flags & TRIG_ROUND_MASK); 469 if (tmp != cmd->convert_arg) 470 error++; 471 } 472 /* There's only one timer on this card, so the scan_begin timer must */ 473 /* be a multiple of chanlist_len*convert_arg */ 474 475 if (cmd->scan_begin_src == TRIG_TIMER) { 476 477 unsigned int scan_begin_min; 478 unsigned int scan_begin_arg; 479 unsigned int scan_factor; 480 481 scan_begin_min = cmd->chanlist_len * cmd->convert_arg; 482 483 if (cmd->scan_begin_arg != scan_begin_min) { 484 if (scan_begin_min < cmd->scan_begin_arg) { 485 scan_factor = 486 cmd->scan_begin_arg / scan_begin_min; 487 scan_begin_arg = scan_factor * scan_begin_min; 488 if (cmd->scan_begin_arg != scan_begin_arg) { 489 cmd->scan_begin_arg = scan_begin_arg; 490 error++; 491 } 492 } else { 493 cmd->scan_begin_arg = scan_begin_min; 494 error++; 495 } 496 } 497 } 498 499 if (error) 500 return 4; 501 502 /* Step 5 : check channel list */ 503 504 if (cmd->chanlist) { 505 506 range = CR_RANGE(cmd->chanlist[0]); 507 reference = CR_AREF(cmd->chanlist[0]); 508 509 if (cmd->chanlist_len > 1) { 510 for (i = 0; i < cmd->chanlist_len; i++) { 511 if (CR_CHAN(cmd->chanlist[i]) != i) { 512 comedi_error(dev, 513 "entries in chanlist must be consecutive " 514 "channels,counting upwards from 0\n"); 515 error++; 516 } 517 if (CR_RANGE(cmd->chanlist[i]) != range) { 518 comedi_error(dev, 519 "entries in chanlist must all have the same gain\n"); 520 error++; 521 } 522 if (CR_AREF(cmd->chanlist[i]) != reference) { 523 comedi_error(dev, 524 "entries in chanlist must all have the same reference\n"); 525 error++; 526 } 527 } 528 } 529 } 530 531 if (error) 532 return 5; 533 534 return 0; 535 536} 537 538/* Analog input command */ 539 540static int pci9111_ai_do_cmd(struct comedi_device *dev, 541 struct comedi_subdevice *s) 542{ 543 struct pci9111_private_data *dev_private = dev->private; 544 struct comedi_cmd *async_cmd = &s->async->cmd; 545 546 if (!dev->irq) { 547 comedi_error(dev, 548 "no irq assigned for PCI9111, cannot do hardware conversion"); 549 return -1; 550 } 551 /* Set channel scan limit */ 552 /* PCI9111 allows only scanning from channel 0 to channel n */ 553 /* TODO: handle the case of an external multiplexer */ 554 555 if (async_cmd->chanlist_len > 1) { 556 outb(async_cmd->chanlist_len - 1, 557 dev->iobase + PCI9111_AI_CHANNEL_REG); 558 pci9111_autoscan_set(dev, true); 559 } else { 560 outb(CR_CHAN(async_cmd->chanlist[0]), 561 dev->iobase + PCI9111_AI_CHANNEL_REG); 562 pci9111_autoscan_set(dev, false); 563 } 564 565 /* Set gain */ 566 /* This is the same gain on every channel */ 567 568 outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, 569 dev->iobase + PCI9111_AI_RANGE_STAT_REG); 570 571 /* Set counter */ 572 573 switch (async_cmd->stop_src) { 574 case TRIG_COUNT: 575 dev_private->stop_counter = 576 async_cmd->stop_arg * async_cmd->chanlist_len; 577 dev_private->stop_is_none = 0; 578 break; 579 580 case TRIG_NONE: 581 dev_private->stop_counter = 0; 582 dev_private->stop_is_none = 1; 583 break; 584 585 default: 586 comedi_error(dev, "Invalid stop trigger"); 587 return -1; 588 } 589 590 /* Set timer pacer */ 591 592 dev_private->scan_delay = 0; 593 switch (async_cmd->convert_src) { 594 case TRIG_TIMER: 595 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, 596 &(dev_private->timer_divisor_1), 597 &(dev_private->timer_divisor_2), 598 &(async_cmd->convert_arg), 599 async_cmd-> 600 flags & TRIG_ROUND_MASK); 601 602 pci9111_trigger_source_set(dev, software); 603 pci9111_timer_set(dev); 604 pci9111_fifo_reset(dev); 605 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 606 irq_on_timer_tick); 607 pci9111_trigger_source_set(dev, timer_pacer); 608 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 609 false, true, true); 610 611 if (async_cmd->scan_begin_src == TRIG_TIMER) { 612 dev_private->scan_delay = 613 (async_cmd->scan_begin_arg / 614 (async_cmd->convert_arg * 615 async_cmd->chanlist_len)) - 1; 616 } 617 618 break; 619 620 case TRIG_EXT: 621 622 pci9111_trigger_source_set(dev, external); 623 pci9111_fifo_reset(dev); 624 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 625 irq_on_timer_tick); 626 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 627 false, true, true); 628 629 break; 630 631 default: 632 comedi_error(dev, "Invalid convert trigger"); 633 return -1; 634 } 635 636 dev_private->stop_counter *= (1 + dev_private->scan_delay); 637 dev_private->chanlist_len = async_cmd->chanlist_len; 638 dev_private->chunk_counter = 0; 639 dev_private->chunk_num_samples = 640 dev_private->chanlist_len * (1 + dev_private->scan_delay); 641 642 return 0; 643} 644 645static void pci9111_ai_munge(struct comedi_device *dev, 646 struct comedi_subdevice *s, void *data, 647 unsigned int num_bytes, 648 unsigned int start_chan_index) 649{ 650 short *array = data; 651 unsigned int maxdata = s->maxdata; 652 unsigned int invert = (maxdata + 1) >> 1; 653 unsigned int shift = (maxdata == 0xffff) ? 0 : 4; 654 unsigned int num_samples = num_bytes / sizeof(short); 655 unsigned int i; 656 657 for (i = 0; i < num_samples; i++) 658 array[i] = ((array[i] >> shift) & maxdata) ^ invert; 659} 660 661/* ------------------------------------------------------------------ */ 662/* INTERRUPT SECTION */ 663/* ------------------------------------------------------------------ */ 664 665static irqreturn_t pci9111_interrupt(int irq, void *p_device) 666{ 667 struct comedi_device *dev = p_device; 668 struct pci9111_private_data *dev_private = dev->private; 669 struct comedi_subdevice *s = dev->read_subdev; 670 struct comedi_async *async; 671 unsigned int status; 672 unsigned long irq_flags; 673 unsigned char intcsr; 674 675 if (!dev->attached) { 676 /* Ignore interrupt before device fully attached. */ 677 /* Might not even have allocated subdevices yet! */ 678 return IRQ_NONE; 679 } 680 681 async = s->async; 682 683 spin_lock_irqsave(&dev->spinlock, irq_flags); 684 685 /* Check if we are source of interrupt */ 686 intcsr = inb(dev_private->lcr_io_base + 687 PLX9050_REGISTER_INTERRUPT_CONTROL); 688 if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0) 689 && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 690 == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 691 || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS)) 692 == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) { 693 /* Not the source of the interrupt. */ 694 /* (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */ 695 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 696 return IRQ_NONE; 697 } 698 699 if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) == 700 (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { 701 /* Interrupt comes from fifo_half-full signal */ 702 703 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 704 705 /* '0' means FIFO is full, data may have been lost */ 706 if (!(status & PCI9111_AI_STAT_FF_FF)) { 707 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 708 comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); 709 outb(0, dev->iobase + PCI9111_INT_CLR_REG); 710 pci9111_ai_cancel(dev, s); 711 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 712 comedi_event(dev, s); 713 714 return IRQ_HANDLED; 715 } 716 717 /* '0' means FIFO is half-full */ 718 if (!(status & PCI9111_AI_STAT_FF_HF)) { 719 unsigned int num_samples; 720 unsigned int bytes_written = 0; 721 722 num_samples = 723 PCI9111_FIFO_HALF_SIZE > 724 dev_private->stop_counter 725 && !dev_private-> 726 stop_is_none ? dev_private->stop_counter : 727 PCI9111_FIFO_HALF_SIZE; 728 insw(dev->iobase + PCI9111_AI_FIFO_REG, 729 dev_private->ai_bounce_buffer, num_samples); 730 731 if (dev_private->scan_delay < 1) { 732 bytes_written = 733 cfc_write_array_to_buffer(s, 734 dev_private-> 735 ai_bounce_buffer, 736 num_samples * 737 sizeof(short)); 738 } else { 739 int position = 0; 740 int to_read; 741 742 while (position < num_samples) { 743 if (dev_private->chunk_counter < 744 dev_private->chanlist_len) { 745 to_read = 746 dev_private->chanlist_len - 747 dev_private->chunk_counter; 748 749 if (to_read > 750 num_samples - position) 751 to_read = 752 num_samples - 753 position; 754 755 bytes_written += 756 cfc_write_array_to_buffer 757 (s, 758 dev_private->ai_bounce_buffer 759 + position, 760 to_read * sizeof(short)); 761 } else { 762 to_read = 763 dev_private->chunk_num_samples 764 - 765 dev_private->chunk_counter; 766 if (to_read > 767 num_samples - position) 768 to_read = 769 num_samples - 770 position; 771 772 bytes_written += 773 sizeof(short) * to_read; 774 } 775 776 position += to_read; 777 dev_private->chunk_counter += to_read; 778 779 if (dev_private->chunk_counter >= 780 dev_private->chunk_num_samples) 781 dev_private->chunk_counter = 0; 782 } 783 } 784 785 dev_private->stop_counter -= 786 bytes_written / sizeof(short); 787 } 788 } 789 790 if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) { 791 async->events |= COMEDI_CB_EOA; 792 pci9111_ai_cancel(dev, s); 793 } 794 795 outb(0, dev->iobase + PCI9111_INT_CLR_REG); 796 797 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 798 799 comedi_event(dev, s); 800 801 return IRQ_HANDLED; 802} 803 804/* ------------------------------------------------------------------ */ 805/* INSTANT ANALOG INPUT OUTPUT SECTION */ 806/* ------------------------------------------------------------------ */ 807 808/* analog instant input */ 809 810static int pci9111_ai_insn_read(struct comedi_device *dev, 811 struct comedi_subdevice *s, 812 struct comedi_insn *insn, unsigned int *data) 813{ 814 unsigned int chan = CR_CHAN(insn->chanspec); 815 unsigned int range = CR_RANGE(insn->chanspec); 816 unsigned int maxdata = s->maxdata; 817 unsigned int invert = (maxdata + 1) >> 1; 818 unsigned int shift = (maxdata == 0xffff) ? 0 : 4; 819 unsigned int status; 820 int timeout; 821 int i; 822 823 outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG); 824 825 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 826 if ((status & PCI9111_AI_RANGE_MASK) != range) { 827 outb(range & PCI9111_AI_RANGE_MASK, 828 dev->iobase + PCI9111_AI_RANGE_STAT_REG); 829 } 830 831 pci9111_fifo_reset(dev); 832 833 for (i = 0; i < insn->n; i++) { 834 /* Generate a software trigger */ 835 outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG); 836 837 timeout = PCI9111_AI_INSTANT_READ_TIMEOUT; 838 839 while (timeout--) { 840 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 841 /* '1' means FIFO is not empty */ 842 if (status & PCI9111_AI_STAT_FF_EF) 843 goto conversion_done; 844 } 845 846 comedi_error(dev, "A/D read timeout"); 847 data[i] = 0; 848 pci9111_fifo_reset(dev); 849 return -ETIME; 850 851conversion_done: 852 853 data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG); 854 data[i] = ((data[i] >> shift) & maxdata) ^ invert; 855 } 856 857 return i; 858} 859 860static int pci9111_ao_insn_write(struct comedi_device *dev, 861 struct comedi_subdevice *s, 862 struct comedi_insn *insn, 863 unsigned int *data) 864{ 865 struct pci9111_private_data *dev_private = dev->private; 866 unsigned int val = 0; 867 int i; 868 869 for (i = 0; i < insn->n; i++) { 870 val = data[i]; 871 outw(val, dev->iobase + PCI9111_AO_REG); 872 } 873 dev_private->ao_readback = val; 874 875 return insn->n; 876} 877 878static int pci9111_ao_insn_read(struct comedi_device *dev, 879 struct comedi_subdevice *s, 880 struct comedi_insn *insn, 881 unsigned int *data) 882{ 883 struct pci9111_private_data *dev_private = dev->private; 884 int i; 885 886 for (i = 0; i < insn->n; i++) 887 data[i] = dev_private->ao_readback; 888 889 return insn->n; 890} 891 892static int pci9111_di_insn_bits(struct comedi_device *dev, 893 struct comedi_subdevice *s, 894 struct comedi_insn *insn, 895 unsigned int *data) 896{ 897 data[1] = inw(dev->iobase + PCI9111_DIO_REG); 898 899 return insn->n; 900} 901 902static int pci9111_do_insn_bits(struct comedi_device *dev, 903 struct comedi_subdevice *s, 904 struct comedi_insn *insn, 905 unsigned int *data) 906{ 907 unsigned int mask = data[0]; 908 unsigned int bits = data[1]; 909 910 if (mask) { 911 s->state &= ~mask; 912 s->state |= (bits & mask); 913 914 outw(s->state, dev->iobase + PCI9111_DIO_REG); 915 } 916 917 data[1] = s->state; 918 919 return insn->n; 920} 921 922/* ------------------------------------------------------------------ */ 923/* INITIALISATION SECTION */ 924/* ------------------------------------------------------------------ */ 925 926/* Reset device */ 927 928static int pci9111_reset(struct comedi_device *dev) 929{ 930 struct pci9111_private_data *dev_private = dev->private; 931 932 /* Set trigger source to software */ 933 934 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 935 true, false); 936 937 pci9111_trigger_source_set(dev, software); 938 pci9111_pretrigger_set(dev, false); 939 pci9111_autoscan_set(dev, false); 940 941 /* Reset 8254 chip */ 942 943 dev_private->timer_divisor_1 = 0; 944 dev_private->timer_divisor_2 = 0; 945 946 pci9111_timer_set(dev); 947 948 return 0; 949} 950 951static int pci9111_attach_pci(struct comedi_device *dev, 952 struct pci_dev *pcidev) 953{ 954 struct pci9111_private_data *dev_private; 955 struct comedi_subdevice *s; 956 int ret; 957 958 comedi_set_hw_dev(dev, &pcidev->dev); 959 dev->board_name = dev->driver->driver_name; 960 961 ret = alloc_private(dev, sizeof(*dev_private)); 962 if (ret) 963 return ret; 964 dev_private = dev->private; 965 966 ret = comedi_pci_enable(pcidev, dev->board_name); 967 if (ret) 968 return ret; 969 dev_private->lcr_io_base = pci_resource_start(pcidev, 1); 970 dev->iobase = pci_resource_start(pcidev, 2); 971 972 pci9111_reset(dev); 973 974 if (pcidev->irq > 0) { 975 ret = request_irq(dev->irq, pci9111_interrupt, 976 IRQF_SHARED, dev->board_name, dev); 977 if (ret) 978 return ret; 979 dev->irq = pcidev->irq; 980 } 981 982 ret = comedi_alloc_subdevices(dev, 4); 983 if (ret) 984 return ret; 985 986 s = &dev->subdevices[0]; 987 dev->read_subdev = s; 988 s->type = COMEDI_SUBD_AI; 989 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; 990 s->n_chan = 16; 991 s->maxdata = 0xffff; 992 s->len_chanlist = 16; 993 s->range_table = &pci9111_hr_ai_range; 994 s->cancel = pci9111_ai_cancel; 995 s->insn_read = pci9111_ai_insn_read; 996 s->do_cmdtest = pci9111_ai_do_cmd_test; 997 s->do_cmd = pci9111_ai_do_cmd; 998 s->munge = pci9111_ai_munge; 999 1000 s = &dev->subdevices[1]; 1001 s->type = COMEDI_SUBD_AO; 1002 s->subdev_flags = SDF_WRITABLE | SDF_COMMON; 1003 s->n_chan = 1; 1004 s->maxdata = 0x0fff; 1005 s->len_chanlist = 1; 1006 s->range_table = &range_bipolar10; 1007 s->insn_write = pci9111_ao_insn_write; 1008 s->insn_read = pci9111_ao_insn_read; 1009 1010 s = &dev->subdevices[2]; 1011 s->type = COMEDI_SUBD_DI; 1012 s->subdev_flags = SDF_READABLE; 1013 s->n_chan = 16; 1014 s->maxdata = 1; 1015 s->range_table = &range_digital; 1016 s->insn_bits = pci9111_di_insn_bits; 1017 1018 s = &dev->subdevices[3]; 1019 s->type = COMEDI_SUBD_DO; 1020 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 1021 s->n_chan = 16; 1022 s->maxdata = 1; 1023 s->range_table = &range_digital; 1024 s->insn_bits = pci9111_do_insn_bits; 1025 1026 dev_private->is_valid = 1; 1027 1028 dev_info(dev->class_dev, "%s attached\n", dev->board_name); 1029 1030 return 0; 1031} 1032 1033static void pci9111_detach(struct comedi_device *dev) 1034{ 1035 struct pci_dev *pcidev = comedi_to_pci_dev(dev); 1036 struct pci9111_private_data *dev_private = dev->private; 1037 1038 if (dev_private) { 1039 if (dev_private->is_valid) 1040 pci9111_reset(dev); 1041 } 1042 if (dev->irq != 0) 1043 free_irq(dev->irq, dev); 1044 if (pcidev) { 1045 if (dev->iobase) 1046 comedi_pci_disable(pcidev); 1047 pci_dev_put(pcidev); 1048 } 1049} 1050 1051static struct comedi_driver adl_pci9111_driver = { 1052 .driver_name = "adl_pci9111", 1053 .module = THIS_MODULE, 1054 .attach_pci = pci9111_attach_pci, 1055 .detach = pci9111_detach, 1056}; 1057 1058static int __devinit pci9111_pci_probe(struct pci_dev *dev, 1059 const struct pci_device_id *ent) 1060{ 1061 return comedi_pci_auto_config(dev, &adl_pci9111_driver); 1062} 1063 1064static void __devexit pci9111_pci_remove(struct pci_dev *dev) 1065{ 1066 comedi_pci_auto_unconfig(dev); 1067} 1068 1069static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { 1070 { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) }, 1071 /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */ 1072 { 0 } 1073}; 1074MODULE_DEVICE_TABLE(pci, pci9111_pci_table); 1075 1076static struct pci_driver adl_pci9111_pci_driver = { 1077 .name = "adl_pci9111", 1078 .id_table = pci9111_pci_table, 1079 .probe = pci9111_pci_probe, 1080 .remove = __devexit_p(pci9111_pci_remove), 1081}; 1082module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver); 1083 1084MODULE_AUTHOR("Comedi http://www.comedi.org"); 1085MODULE_DESCRIPTION("Comedi low-level driver"); 1086MODULE_LICENSE("GPL"); 1087