adl_pci9111.c revision 5993f3a2692eed3c74c86882155b8703a0060ad5
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 <linux/pci.h> 72#include <linux/delay.h> 73#include <linux/interrupt.h> 74 75#include "../comedidev.h" 76 77#include "8253.h" 78#include "comedi_fc.h" 79 80#define PCI9111_DRIVER_NAME "adl_pci9111" 81#define PCI9111_HR_DEVICE_ID 0x9111 82 83#define PCI9111_FIFO_HALF_SIZE 512 84 85#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 86 87#define PCI9111_RANGE_SETTING_DELAY 10 88#define PCI9111_AI_INSTANT_READ_UDELAY_US 2 89#define PCI9111_AI_INSTANT_READ_TIMEOUT 100 90 91#define PCI9111_8254_CLOCK_PERIOD_NS 500 92 93/* 94 * IO address map and bit defines 95 */ 96#define PCI9111_AI_FIFO_REG 0x00 97#define PCI9111_AO_REG 0x00 98#define PCI9111_DIO_REG 0x02 99#define PCI9111_EDIO_REG 0x04 100#define PCI9111_AI_CHANNEL_REG 0x06 101#define PCI9111_AI_RANGE_STAT_REG 0x08 102#define PCI9111_AI_STAT_AD_BUSY (1 << 7) 103#define PCI9111_AI_STAT_FF_FF (1 << 6) 104#define PCI9111_AI_STAT_FF_HF (1 << 5) 105#define PCI9111_AI_STAT_FF_EF (1 << 4) 106#define PCI9111_AI_RANGE_MASK (7 << 0) 107#define PCI9111_AI_TRIG_CTRL_REG 0x0a 108#define PCI9111_AI_TRIG_CTRL_TRGEVENT (1 << 5) 109#define PCI9111_AI_TRIG_CTRL_POTRG (1 << 4) 110#define PCI9111_AI_TRIG_CTRL_PTRG (1 << 3) 111#define PCI9111_AI_TRIG_CTRL_ETIS (1 << 2) 112#define PCI9111_AI_TRIG_CTRL_TPST (1 << 1) 113#define PCI9111_AI_TRIG_CTRL_ASCAN (1 << 0) 114#define PCI9111_INT_CTRL_REG 0x0c 115#define PCI9111_INT_CTRL_ISC2 (1 << 3) 116#define PCI9111_INT_CTRL_FFEN (1 << 2) 117#define PCI9111_INT_CTRL_ISC1 (1 << 1) 118#define PCI9111_INT_CTRL_ISC0 (1 << 0) 119#define PCI9111_SOFT_TRIG_REG 0x0e 120#define PCI9111_8254_BASE_REG 0x40 121#define PCI9111_INT_CLR_REG 0x48 122 123static const struct comedi_lrange pci9111_ai_range = { 124 5, 125 { 126 BIP_RANGE(10), 127 BIP_RANGE(5), 128 BIP_RANGE(2.5), 129 BIP_RANGE(1.25), 130 BIP_RANGE(0.625) 131 } 132}; 133 134struct pci9111_private_data { 135 unsigned long lcr_io_base; 136 137 int stop_counter; 138 int stop_is_none; 139 140 unsigned int scan_delay; 141 unsigned int chanlist_len; 142 unsigned int chunk_counter; 143 unsigned int chunk_num_samples; 144 145 int ao_readback; 146 147 unsigned int div1; 148 unsigned int div2; 149 150 short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; 151}; 152 153#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c 154 155#define PLX9050_LINTI1_ENABLE (1 << 0) 156#define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1) 157#define PLX9050_LINTI1_STATUS (1 << 2) 158#define PLX9050_LINTI2_ENABLE (1 << 3) 159#define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4) 160#define PLX9050_LINTI2_STATUS (1 << 5) 161#define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6) 162#define PLX9050_SOFTWARE_INTERRUPT (1 << 7) 163 164static void plx9050_interrupt_control(unsigned long io_base, 165 bool LINTi1_enable, 166 bool LINTi1_active_high, 167 bool LINTi2_enable, 168 bool LINTi2_active_high, 169 bool interrupt_enable) 170{ 171 int flags = 0; 172 173 if (LINTi1_enable) 174 flags |= PLX9050_LINTI1_ENABLE; 175 if (LINTi1_active_high) 176 flags |= PLX9050_LINTI1_ACTIVE_HIGH; 177 if (LINTi2_enable) 178 flags |= PLX9050_LINTI2_ENABLE; 179 if (LINTi2_active_high) 180 flags |= PLX9050_LINTI2_ACTIVE_HIGH; 181 182 if (interrupt_enable) 183 flags |= PLX9050_PCI_INTERRUPT_ENABLE; 184 185 outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); 186} 187 188static void pci9111_timer_set(struct comedi_device *dev) 189{ 190 struct pci9111_private_data *dev_private = dev->private; 191 unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG; 192 193 i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY); 194 i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY); 195 i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY); 196 197 udelay(1); 198 199 i8254_write(timer_base, 1, 2, dev_private->div2); 200 i8254_write(timer_base, 1, 1, dev_private->div1); 201} 202 203enum pci9111_trigger_sources { 204 software, 205 timer_pacer, 206 external 207}; 208 209static void pci9111_trigger_source_set(struct comedi_device *dev, 210 enum pci9111_trigger_sources source) 211{ 212 int flags; 213 214 /* Read the current trigger mode control bits */ 215 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 216 /* Mask off the EITS and TPST bits */ 217 flags &= 0x9; 218 219 switch (source) { 220 case software: 221 break; 222 223 case timer_pacer: 224 flags |= PCI9111_AI_TRIG_CTRL_TPST; 225 break; 226 227 case external: 228 flags |= PCI9111_AI_TRIG_CTRL_ETIS; 229 break; 230 } 231 232 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 233} 234 235static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger) 236{ 237 int flags; 238 239 /* Read the current trigger mode control bits */ 240 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 241 /* Mask off the PTRG bit */ 242 flags &= 0x7; 243 244 if (pretrigger) 245 flags |= PCI9111_AI_TRIG_CTRL_PTRG; 246 247 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 248} 249 250static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan) 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 ASCAN bit */ 257 flags &= 0xe; 258 259 if (autoscan) 260 flags |= PCI9111_AI_TRIG_CTRL_ASCAN; 261 262 outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 263} 264 265enum pci9111_ISC0_sources { 266 irq_on_eoc, 267 irq_on_fifo_half_full 268}; 269 270enum pci9111_ISC1_sources { 271 irq_on_timer_tick, 272 irq_on_external_trigger 273}; 274 275static void pci9111_interrupt_source_set(struct comedi_device *dev, 276 enum pci9111_ISC0_sources irq_0_source, 277 enum pci9111_ISC1_sources irq_1_source) 278{ 279 int flags; 280 281 /* Read the current interrupt control bits */ 282 flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG); 283 /* Shift the bits so they are compatible with the write register */ 284 flags >>= 4; 285 /* Mask off the ISCx bits */ 286 flags &= 0xc0; 287 288 /* Now set the new ISCx bits */ 289 if (irq_0_source == irq_on_fifo_half_full) 290 flags |= PCI9111_INT_CTRL_ISC0; 291 292 if (irq_1_source == irq_on_external_trigger) 293 flags |= PCI9111_INT_CTRL_ISC1; 294 295 outb(flags, dev->iobase + PCI9111_INT_CTRL_REG); 296} 297 298static void pci9111_fifo_reset(struct comedi_device *dev) 299{ 300 unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG; 301 302 /* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */ 303 outb(0, int_ctrl_reg); 304 outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg); 305 outb(0, int_ctrl_reg); 306} 307 308static int pci9111_ai_cancel(struct comedi_device *dev, 309 struct comedi_subdevice *s) 310{ 311 struct pci9111_private_data *dev_private = dev->private; 312 313 /* Disable interrupts */ 314 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 315 true, false); 316 317 pci9111_trigger_source_set(dev, software); 318 319 pci9111_autoscan_set(dev, false); 320 321 pci9111_fifo_reset(dev); 322 323 return 0; 324} 325 326static int pci9111_ai_do_cmd_test(struct comedi_device *dev, 327 struct comedi_subdevice *s, 328 struct comedi_cmd *cmd) 329{ 330 struct pci9111_private_data *dev_private = dev->private; 331 int tmp; 332 int error = 0; 333 int range, reference; 334 int i; 335 336 /* Step 1 : check if triggers are trivially valid */ 337 338 error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW); 339 error |= cfc_check_trigger_src(&cmd->scan_begin_src, 340 TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); 341 error |= cfc_check_trigger_src(&cmd->convert_src, 342 TRIG_TIMER | TRIG_EXT); 343 error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); 344 error |= cfc_check_trigger_src(&cmd->stop_src, 345 TRIG_COUNT | TRIG_NONE); 346 347 if (error) 348 return 1; 349 350 /* Step 2a : make sure trigger sources are unique */ 351 352 error |= cfc_check_trigger_is_unique(cmd->scan_begin_src); 353 error |= cfc_check_trigger_is_unique(cmd->convert_src); 354 error |= cfc_check_trigger_is_unique(cmd->stop_src); 355 356 /* Step 2b : and mutually compatible */ 357 358 if ((cmd->convert_src == TRIG_TIMER) && 359 !((cmd->scan_begin_src == TRIG_TIMER) || 360 (cmd->scan_begin_src == TRIG_FOLLOW))) 361 error |= -EINVAL; 362 if ((cmd->convert_src == TRIG_EXT) && 363 !((cmd->scan_begin_src == TRIG_EXT) || 364 (cmd->scan_begin_src == TRIG_FOLLOW))) 365 error |= -EINVAL; 366 367 if (error) 368 return 2; 369 370 /* Step 3: check if arguments are trivially valid */ 371 372 error |= cfc_check_trigger_arg_is(&cmd->start_arg, 0); 373 374 if (cmd->convert_src == TRIG_TIMER) 375 error |= cfc_check_trigger_arg_min(&cmd->convert_arg, 376 PCI9111_AI_ACQUISITION_PERIOD_MIN_NS); 377 else /* TRIG_EXT */ 378 error |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0); 379 380 if (cmd->scan_begin_src == TRIG_TIMER) 381 error |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 382 PCI9111_AI_ACQUISITION_PERIOD_MIN_NS); 383 else /* TRIG_FOLLOW || TRIG_EXT */ 384 error |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0); 385 386 error |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 387 cmd->chanlist_len); 388 389 if (cmd->stop_src == TRIG_COUNT) 390 error |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1); 391 else /* TRIG_NONE */ 392 error |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0); 393 394 if (error) 395 return 3; 396 397 /* Step 4 : fix up any arguments */ 398 399 if (cmd->convert_src == TRIG_TIMER) { 400 tmp = cmd->convert_arg; 401 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, 402 &dev_private->div1, 403 &dev_private->div2, 404 &cmd->convert_arg, 405 cmd->flags & TRIG_ROUND_MASK); 406 if (tmp != cmd->convert_arg) 407 error++; 408 } 409 /* There's only one timer on this card, so the scan_begin timer must */ 410 /* be a multiple of chanlist_len*convert_arg */ 411 412 if (cmd->scan_begin_src == TRIG_TIMER) { 413 414 unsigned int scan_begin_min; 415 unsigned int scan_begin_arg; 416 unsigned int scan_factor; 417 418 scan_begin_min = cmd->chanlist_len * cmd->convert_arg; 419 420 if (cmd->scan_begin_arg != scan_begin_min) { 421 if (scan_begin_min < cmd->scan_begin_arg) { 422 scan_factor = 423 cmd->scan_begin_arg / scan_begin_min; 424 scan_begin_arg = scan_factor * scan_begin_min; 425 if (cmd->scan_begin_arg != scan_begin_arg) { 426 cmd->scan_begin_arg = scan_begin_arg; 427 error++; 428 } 429 } else { 430 cmd->scan_begin_arg = scan_begin_min; 431 error++; 432 } 433 } 434 } 435 436 if (error) 437 return 4; 438 439 /* Step 5 : check channel list */ 440 441 if (cmd->chanlist) { 442 443 range = CR_RANGE(cmd->chanlist[0]); 444 reference = CR_AREF(cmd->chanlist[0]); 445 446 if (cmd->chanlist_len > 1) { 447 for (i = 0; i < cmd->chanlist_len; i++) { 448 if (CR_CHAN(cmd->chanlist[i]) != i) { 449 comedi_error(dev, 450 "entries in chanlist must be consecutive " 451 "channels,counting upwards from 0\n"); 452 error++; 453 } 454 if (CR_RANGE(cmd->chanlist[i]) != range) { 455 comedi_error(dev, 456 "entries in chanlist must all have the same gain\n"); 457 error++; 458 } 459 if (CR_AREF(cmd->chanlist[i]) != reference) { 460 comedi_error(dev, 461 "entries in chanlist must all have the same reference\n"); 462 error++; 463 } 464 } 465 } 466 } 467 468 if (error) 469 return 5; 470 471 return 0; 472 473} 474 475static int pci9111_ai_do_cmd(struct comedi_device *dev, 476 struct comedi_subdevice *s) 477{ 478 struct pci9111_private_data *dev_private = dev->private; 479 struct comedi_cmd *async_cmd = &s->async->cmd; 480 481 if (!dev->irq) { 482 comedi_error(dev, 483 "no irq assigned for PCI9111, cannot do hardware conversion"); 484 return -1; 485 } 486 /* Set channel scan limit */ 487 /* PCI9111 allows only scanning from channel 0 to channel n */ 488 /* TODO: handle the case of an external multiplexer */ 489 490 if (async_cmd->chanlist_len > 1) { 491 outb(async_cmd->chanlist_len - 1, 492 dev->iobase + PCI9111_AI_CHANNEL_REG); 493 pci9111_autoscan_set(dev, true); 494 } else { 495 outb(CR_CHAN(async_cmd->chanlist[0]), 496 dev->iobase + PCI9111_AI_CHANNEL_REG); 497 pci9111_autoscan_set(dev, false); 498 } 499 500 /* Set gain */ 501 /* This is the same gain on every channel */ 502 503 outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK, 504 dev->iobase + PCI9111_AI_RANGE_STAT_REG); 505 506 /* Set counter */ 507 508 switch (async_cmd->stop_src) { 509 case TRIG_COUNT: 510 dev_private->stop_counter = 511 async_cmd->stop_arg * async_cmd->chanlist_len; 512 dev_private->stop_is_none = 0; 513 break; 514 515 case TRIG_NONE: 516 dev_private->stop_counter = 0; 517 dev_private->stop_is_none = 1; 518 break; 519 520 default: 521 comedi_error(dev, "Invalid stop trigger"); 522 return -1; 523 } 524 525 /* Set timer pacer */ 526 527 dev_private->scan_delay = 0; 528 switch (async_cmd->convert_src) { 529 case TRIG_TIMER: 530 pci9111_trigger_source_set(dev, software); 531 pci9111_timer_set(dev); 532 pci9111_fifo_reset(dev); 533 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 534 irq_on_timer_tick); 535 pci9111_trigger_source_set(dev, timer_pacer); 536 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 537 false, true, true); 538 539 if (async_cmd->scan_begin_src == TRIG_TIMER) { 540 dev_private->scan_delay = 541 (async_cmd->scan_begin_arg / 542 (async_cmd->convert_arg * 543 async_cmd->chanlist_len)) - 1; 544 } 545 546 break; 547 548 case TRIG_EXT: 549 550 pci9111_trigger_source_set(dev, external); 551 pci9111_fifo_reset(dev); 552 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 553 irq_on_timer_tick); 554 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 555 false, true, true); 556 557 break; 558 559 default: 560 comedi_error(dev, "Invalid convert trigger"); 561 return -1; 562 } 563 564 dev_private->stop_counter *= (1 + dev_private->scan_delay); 565 dev_private->chanlist_len = async_cmd->chanlist_len; 566 dev_private->chunk_counter = 0; 567 dev_private->chunk_num_samples = 568 dev_private->chanlist_len * (1 + dev_private->scan_delay); 569 570 return 0; 571} 572 573static void pci9111_ai_munge(struct comedi_device *dev, 574 struct comedi_subdevice *s, void *data, 575 unsigned int num_bytes, 576 unsigned int start_chan_index) 577{ 578 short *array = data; 579 unsigned int maxdata = s->maxdata; 580 unsigned int invert = (maxdata + 1) >> 1; 581 unsigned int shift = (maxdata == 0xffff) ? 0 : 4; 582 unsigned int num_samples = num_bytes / sizeof(short); 583 unsigned int i; 584 585 for (i = 0; i < num_samples; i++) 586 array[i] = ((array[i] >> shift) & maxdata) ^ invert; 587} 588 589static irqreturn_t pci9111_interrupt(int irq, void *p_device) 590{ 591 struct comedi_device *dev = p_device; 592 struct pci9111_private_data *dev_private = dev->private; 593 struct comedi_subdevice *s = dev->read_subdev; 594 struct comedi_async *async; 595 unsigned int status; 596 unsigned long irq_flags; 597 unsigned char intcsr; 598 599 if (!dev->attached) { 600 /* Ignore interrupt before device fully attached. */ 601 /* Might not even have allocated subdevices yet! */ 602 return IRQ_NONE; 603 } 604 605 async = s->async; 606 607 spin_lock_irqsave(&dev->spinlock, irq_flags); 608 609 /* Check if we are source of interrupt */ 610 intcsr = inb(dev_private->lcr_io_base + 611 PLX9050_REGISTER_INTERRUPT_CONTROL); 612 if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0) 613 && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 614 == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 615 || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS)) 616 == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) { 617 /* Not the source of the interrupt. */ 618 /* (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */ 619 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 620 return IRQ_NONE; 621 } 622 623 if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) == 624 (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { 625 /* Interrupt comes from fifo_half-full signal */ 626 627 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 628 629 /* '0' means FIFO is full, data may have been lost */ 630 if (!(status & PCI9111_AI_STAT_FF_FF)) { 631 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 632 comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); 633 outb(0, dev->iobase + PCI9111_INT_CLR_REG); 634 pci9111_ai_cancel(dev, s); 635 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 636 comedi_event(dev, s); 637 638 return IRQ_HANDLED; 639 } 640 641 /* '0' means FIFO is half-full */ 642 if (!(status & PCI9111_AI_STAT_FF_HF)) { 643 unsigned int num_samples; 644 unsigned int bytes_written = 0; 645 646 num_samples = 647 PCI9111_FIFO_HALF_SIZE > 648 dev_private->stop_counter 649 && !dev_private-> 650 stop_is_none ? dev_private->stop_counter : 651 PCI9111_FIFO_HALF_SIZE; 652 insw(dev->iobase + PCI9111_AI_FIFO_REG, 653 dev_private->ai_bounce_buffer, num_samples); 654 655 if (dev_private->scan_delay < 1) { 656 bytes_written = 657 cfc_write_array_to_buffer(s, 658 dev_private-> 659 ai_bounce_buffer, 660 num_samples * 661 sizeof(short)); 662 } else { 663 int position = 0; 664 int to_read; 665 666 while (position < num_samples) { 667 if (dev_private->chunk_counter < 668 dev_private->chanlist_len) { 669 to_read = 670 dev_private->chanlist_len - 671 dev_private->chunk_counter; 672 673 if (to_read > 674 num_samples - position) 675 to_read = 676 num_samples - 677 position; 678 679 bytes_written += 680 cfc_write_array_to_buffer 681 (s, 682 dev_private->ai_bounce_buffer 683 + position, 684 to_read * sizeof(short)); 685 } else { 686 to_read = 687 dev_private->chunk_num_samples 688 - 689 dev_private->chunk_counter; 690 if (to_read > 691 num_samples - position) 692 to_read = 693 num_samples - 694 position; 695 696 bytes_written += 697 sizeof(short) * to_read; 698 } 699 700 position += to_read; 701 dev_private->chunk_counter += to_read; 702 703 if (dev_private->chunk_counter >= 704 dev_private->chunk_num_samples) 705 dev_private->chunk_counter = 0; 706 } 707 } 708 709 dev_private->stop_counter -= 710 bytes_written / sizeof(short); 711 } 712 } 713 714 if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) { 715 async->events |= COMEDI_CB_EOA; 716 pci9111_ai_cancel(dev, s); 717 } 718 719 outb(0, dev->iobase + PCI9111_INT_CLR_REG); 720 721 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 722 723 comedi_event(dev, s); 724 725 return IRQ_HANDLED; 726} 727 728static int pci9111_ai_insn_read(struct comedi_device *dev, 729 struct comedi_subdevice *s, 730 struct comedi_insn *insn, unsigned int *data) 731{ 732 unsigned int chan = CR_CHAN(insn->chanspec); 733 unsigned int range = CR_RANGE(insn->chanspec); 734 unsigned int maxdata = s->maxdata; 735 unsigned int invert = (maxdata + 1) >> 1; 736 unsigned int shift = (maxdata == 0xffff) ? 0 : 4; 737 unsigned int status; 738 int timeout; 739 int i; 740 741 outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG); 742 743 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 744 if ((status & PCI9111_AI_RANGE_MASK) != range) { 745 outb(range & PCI9111_AI_RANGE_MASK, 746 dev->iobase + PCI9111_AI_RANGE_STAT_REG); 747 } 748 749 pci9111_fifo_reset(dev); 750 751 for (i = 0; i < insn->n; i++) { 752 /* Generate a software trigger */ 753 outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG); 754 755 timeout = PCI9111_AI_INSTANT_READ_TIMEOUT; 756 757 while (timeout--) { 758 status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG); 759 /* '1' means FIFO is not empty */ 760 if (status & PCI9111_AI_STAT_FF_EF) 761 goto conversion_done; 762 } 763 764 comedi_error(dev, "A/D read timeout"); 765 data[i] = 0; 766 pci9111_fifo_reset(dev); 767 return -ETIME; 768 769conversion_done: 770 771 data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG); 772 data[i] = ((data[i] >> shift) & maxdata) ^ invert; 773 } 774 775 return i; 776} 777 778static int pci9111_ao_insn_write(struct comedi_device *dev, 779 struct comedi_subdevice *s, 780 struct comedi_insn *insn, 781 unsigned int *data) 782{ 783 struct pci9111_private_data *dev_private = dev->private; 784 unsigned int val = 0; 785 int i; 786 787 for (i = 0; i < insn->n; i++) { 788 val = data[i]; 789 outw(val, dev->iobase + PCI9111_AO_REG); 790 } 791 dev_private->ao_readback = val; 792 793 return insn->n; 794} 795 796static int pci9111_ao_insn_read(struct comedi_device *dev, 797 struct comedi_subdevice *s, 798 struct comedi_insn *insn, 799 unsigned int *data) 800{ 801 struct pci9111_private_data *dev_private = dev->private; 802 int i; 803 804 for (i = 0; i < insn->n; i++) 805 data[i] = dev_private->ao_readback; 806 807 return insn->n; 808} 809 810static int pci9111_di_insn_bits(struct comedi_device *dev, 811 struct comedi_subdevice *s, 812 struct comedi_insn *insn, 813 unsigned int *data) 814{ 815 data[1] = inw(dev->iobase + PCI9111_DIO_REG); 816 817 return insn->n; 818} 819 820static int pci9111_do_insn_bits(struct comedi_device *dev, 821 struct comedi_subdevice *s, 822 struct comedi_insn *insn, 823 unsigned int *data) 824{ 825 unsigned int mask = data[0]; 826 unsigned int bits = data[1]; 827 828 if (mask) { 829 s->state &= ~mask; 830 s->state |= (bits & mask); 831 832 outw(s->state, dev->iobase + PCI9111_DIO_REG); 833 } 834 835 data[1] = s->state; 836 837 return insn->n; 838} 839 840static int pci9111_reset(struct comedi_device *dev) 841{ 842 struct pci9111_private_data *dev_private = dev->private; 843 844 /* Set trigger source to software */ 845 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 846 true, false); 847 848 pci9111_trigger_source_set(dev, software); 849 pci9111_pretrigger_set(dev, false); 850 pci9111_autoscan_set(dev, false); 851 852 /* Reset 8254 chip */ 853 dev_private->div1 = 0; 854 dev_private->div2 = 0; 855 pci9111_timer_set(dev); 856 857 return 0; 858} 859 860static int pci9111_auto_attach(struct comedi_device *dev, 861 unsigned long context_unused) 862{ 863 struct pci_dev *pcidev = comedi_to_pci_dev(dev); 864 struct pci9111_private_data *dev_private; 865 struct comedi_subdevice *s; 866 int ret; 867 868 dev_private = kzalloc(sizeof(*dev_private), GFP_KERNEL); 869 if (!dev_private) 870 return -ENOMEM; 871 dev->private = dev_private; 872 873 ret = comedi_pci_enable(dev); 874 if (ret) 875 return ret; 876 dev_private->lcr_io_base = pci_resource_start(pcidev, 1); 877 dev->iobase = pci_resource_start(pcidev, 2); 878 879 pci9111_reset(dev); 880 881 if (pcidev->irq > 0) { 882 ret = request_irq(dev->irq, pci9111_interrupt, 883 IRQF_SHARED, dev->board_name, dev); 884 if (ret) 885 return ret; 886 dev->irq = pcidev->irq; 887 } 888 889 ret = comedi_alloc_subdevices(dev, 4); 890 if (ret) 891 return ret; 892 893 s = &dev->subdevices[0]; 894 dev->read_subdev = s; 895 s->type = COMEDI_SUBD_AI; 896 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; 897 s->n_chan = 16; 898 s->maxdata = 0xffff; 899 s->len_chanlist = 16; 900 s->range_table = &pci9111_ai_range; 901 s->cancel = pci9111_ai_cancel; 902 s->insn_read = pci9111_ai_insn_read; 903 s->do_cmdtest = pci9111_ai_do_cmd_test; 904 s->do_cmd = pci9111_ai_do_cmd; 905 s->munge = pci9111_ai_munge; 906 907 s = &dev->subdevices[1]; 908 s->type = COMEDI_SUBD_AO; 909 s->subdev_flags = SDF_WRITABLE | SDF_COMMON; 910 s->n_chan = 1; 911 s->maxdata = 0x0fff; 912 s->len_chanlist = 1; 913 s->range_table = &range_bipolar10; 914 s->insn_write = pci9111_ao_insn_write; 915 s->insn_read = pci9111_ao_insn_read; 916 917 s = &dev->subdevices[2]; 918 s->type = COMEDI_SUBD_DI; 919 s->subdev_flags = SDF_READABLE; 920 s->n_chan = 16; 921 s->maxdata = 1; 922 s->range_table = &range_digital; 923 s->insn_bits = pci9111_di_insn_bits; 924 925 s = &dev->subdevices[3]; 926 s->type = COMEDI_SUBD_DO; 927 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 928 s->n_chan = 16; 929 s->maxdata = 1; 930 s->range_table = &range_digital; 931 s->insn_bits = pci9111_do_insn_bits; 932 933 dev_info(dev->class_dev, "%s attached\n", dev->board_name); 934 935 return 0; 936} 937 938static void pci9111_detach(struct comedi_device *dev) 939{ 940 if (dev->iobase) 941 pci9111_reset(dev); 942 if (dev->irq != 0) 943 free_irq(dev->irq, dev); 944 comedi_pci_disable(dev); 945} 946 947static struct comedi_driver adl_pci9111_driver = { 948 .driver_name = "adl_pci9111", 949 .module = THIS_MODULE, 950 .auto_attach = pci9111_auto_attach, 951 .detach = pci9111_detach, 952}; 953 954static int pci9111_pci_probe(struct pci_dev *dev, 955 const struct pci_device_id *id) 956{ 957 return comedi_pci_auto_config(dev, &adl_pci9111_driver, 958 id->driver_data); 959} 960 961static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { 962 { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) }, 963 /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */ 964 { 0 } 965}; 966MODULE_DEVICE_TABLE(pci, pci9111_pci_table); 967 968static struct pci_driver adl_pci9111_pci_driver = { 969 .name = "adl_pci9111", 970 .id_table = pci9111_pci_table, 971 .probe = pci9111_pci_probe, 972 .remove = comedi_pci_auto_unconfig, 973}; 974module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver); 975 976MODULE_AUTHOR("Comedi http://www.comedi.org"); 977MODULE_DESCRIPTION("Comedi low-level driver"); 978MODULE_LICENSE("GPL"); 979