adl_pci9111.c revision 727b286b44ea359d66f47d241cc2cdad36ed7bdc
1/* 2 3 comedi/drivers/adl_pci9111.c 4 5 Hardware driver for PCI9111 ADLink cards: 6 7 PCI-9111HR 8 9 Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr> 10 11 This program is free software; you can redistribute it and/or modify 12 it under the terms of the GNU General Public License as published by 13 the Free Software Foundation; either version 2 of the License, or 14 (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, 17 but WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 GNU General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software 23 Foundation, 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 47 The scanned channels must be consecutive and start from 0. They must 48 all have the same range and aref. 49 50Configuration options: 51 52 [0] - PCI bus number (optional) 53 [1] - PCI slot number (optional) 54 55 If bus/slot is not specified, the first available PCI 56 device will be used. 57 58*/ 59 60/* 61CHANGELOG: 62 63 2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be 64 a multiple of chanlist_len*convert_arg. 65 2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data. 66 2002/02/18 Added external trigger support for analog input. 67 68TODO: 69 70 - Really test implemented functionality. 71 - Add support for the PCI-9111DG with a probe routine to identify the card 72 type (perhaps with the help of the channel number readback of the A/D Data 73 register). 74 - Add external multiplexer support. 75 76*/ 77 78#include "../comedidev.h" 79 80#include <linux/delay.h> 81#include <linux/interrupt.h> 82 83#include "8253.h" 84#include "comedi_pci.h" 85#include "comedi_fc.h" 86 87#define PCI9111_DRIVER_NAME "adl_pci9111" 88#define PCI9111_HR_DEVICE_ID 0x9111 89 90/* TODO: Add other pci9111 board id */ 91 92#define PCI9111_IO_RANGE 0x0100 93 94#define PCI9111_FIFO_HALF_SIZE 512 95 96#define PCI9111_AI_CHANNEL_NBR 16 97 98#define PCI9111_AI_RESOLUTION 12 99#define PCI9111_AI_RESOLUTION_MASK 0x0FFF 100#define PCI9111_AI_RESOLUTION_2_CMP_BIT 0x0800 101 102#define PCI9111_HR_AI_RESOLUTION 16 103#define PCI9111_HR_AI_RESOLUTION_MASK 0xFFFF 104#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT 0x8000 105 106#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS 10000 107#define PCI9111_AO_CHANNEL_NBR 1 108#define PCI9111_AO_RESOLUTION 12 109#define PCI9111_AO_RESOLUTION_MASK 0x0FFF 110#define PCI9111_DI_CHANNEL_NBR 16 111#define PCI9111_DO_CHANNEL_NBR 16 112#define PCI9111_DO_MASK 0xFFFF 113 114#define PCI9111_RANGE_SETTING_DELAY 10 115#define PCI9111_AI_INSTANT_READ_UDELAY_US 2 116#define PCI9111_AI_INSTANT_READ_TIMEOUT 100 117 118#define PCI9111_8254_CLOCK_PERIOD_NS 500 119 120#define PCI9111_8254_COUNTER_0 0x00 121#define PCI9111_8254_COUNTER_1 0x40 122#define PCI9111_8254_COUNTER_2 0x80 123#define PCI9111_8254_COUNTER_LATCH 0x00 124#define PCI9111_8254_READ_LOAD_LSB_ONLY 0x10 125#define PCI9111_8254_READ_LOAD_MSB_ONLY 0x20 126#define PCI9111_8254_READ_LOAD_LSB_MSB 0x30 127#define PCI9111_8254_MODE_0 0x00 128#define PCI9111_8254_MODE_1 0x02 129#define PCI9111_8254_MODE_2 0x04 130#define PCI9111_8254_MODE_3 0x06 131#define PCI9111_8254_MODE_4 0x08 132#define PCI9111_8254_MODE_5 0x0A 133#define PCI9111_8254_BINARY_COUNTER 0x00 134#define PCI9111_8254_BCD_COUNTER 0x01 135 136/* IO address map */ 137 138#define PCI9111_REGISTER_AD_FIFO_VALUE 0x00 /* AD Data stored 139 in FIFO */ 140#define PCI9111_REGISTER_DA_OUTPUT 0x00 141#define PCI9111_REGISTER_DIGITAL_IO 0x02 142#define PCI9111_REGISTER_EXTENDED_IO_PORTS 0x04 143#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 0x06 /* Channel 144 selection */ 145#define PCI9111_REGISTER_AD_CHANNEL_READBACK 0x06 146#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 0x08 147#define PCI9111_REGISTER_RANGE_STATUS_READBACK 0x08 148#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 0x0A 149#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 0x0A 150#define PCI9111_REGISTER_SOFTWARE_TRIGGER 0x0E 151#define PCI9111_REGISTER_INTERRUPT_CONTROL 0x0C 152#define PCI9111_REGISTER_8254_COUNTER_0 0x40 153#define PCI9111_REGISTER_8254_COUNTER_1 0x42 154#define PCI9111_REGISTER_8254_COUNTER_2 0X44 155#define PCI9111_REGISTER_8254_CONTROL 0x46 156#define PCI9111_REGISTER_INTERRUPT_CLEAR 0x48 157 158#define PCI9111_TRIGGER_MASK 0x0F 159#define PCI9111_PTRG_OFF (0 << 3) 160#define PCI9111_PTRG_ON (1 << 3) 161#define PCI9111_EITS_EXTERNAL (1 << 2) 162#define PCI9111_EITS_INTERNAL (0 << 2) 163#define PCI9111_TPST_SOFTWARE_TRIGGER (0 << 1) 164#define PCI9111_TPST_TIMER_PACER (1 << 1) 165#define PCI9111_ASCAN_ON (1 << 0) 166#define PCI9111_ASCAN_OFF (0 << 0) 167 168#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0) 169#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL (1 << 0) 170#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK (0 << 1) 171#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG (1 << 1) 172#define PCI9111_FFEN_SET_FIFO_ENABLE (0 << 2) 173#define PCI9111_FFEN_SET_FIFO_DISABLE (1 << 2) 174 175#define PCI9111_CHANNEL_MASK 0x0F 176 177#define PCI9111_RANGE_MASK 0x07 178#define PCI9111_FIFO_EMPTY_MASK 0x10 179#define PCI9111_FIFO_HALF_FULL_MASK 0x20 180#define PCI9111_FIFO_FULL_MASK 0x40 181#define PCI9111_AD_BUSY_MASK 0x80 182 183#define PCI9111_IO_BASE (dev->iobase) 184 185/* 186 * Define inlined function 187 */ 188 189#define pci9111_trigger_and_autoscan_get() \ 190 (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F) 191 192#define pci9111_trigger_and_autoscan_set(flags) \ 193 outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL) 194 195#define pci9111_interrupt_and_fifo_get() \ 196 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \ 197 &0x03) 198 199#define pci9111_interrupt_and_fifo_set(flags) \ 200 outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL) 201 202#define pci9111_interrupt_clear() \ 203 outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR) 204 205#define pci9111_software_trigger() \ 206 outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER) 207 208#define pci9111_fifo_reset() do { \ 209 outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ 210 PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ 211 outb(PCI9111_FFEN_SET_FIFO_DISABLE, \ 212 PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ 213 outb(PCI9111_FFEN_SET_FIFO_ENABLE, \ 214 PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \ 215 } while (0) 216 217#define pci9111_is_fifo_full() \ 218 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ 219 PCI9111_FIFO_FULL_MASK) == 0) 220 221#define pci9111_is_fifo_half_full() \ 222 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ 223 PCI9111_FIFO_HALF_FULL_MASK) == 0) 224 225#define pci9111_is_fifo_empty() \ 226 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \ 227 PCI9111_FIFO_EMPTY_MASK) == 0) 228 229#define pci9111_ai_channel_set(channel) \ 230 outb((channel)&PCI9111_CHANNEL_MASK, \ 231 PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL) 232 233#define pci9111_ai_channel_get() \ 234 (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \ 235 &PCI9111_CHANNEL_MASK) 236 237#define pci9111_ai_range_set(range) \ 238 outb((range)&PCI9111_RANGE_MASK, \ 239 PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE) 240 241#define pci9111_ai_range_get() \ 242 (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \ 243 &PCI9111_RANGE_MASK) 244 245#define pci9111_ai_get_data() \ 246 (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \ 247 &PCI9111_AI_RESOLUTION_MASK) \ 248 ^ PCI9111_AI_RESOLUTION_2_CMP_BIT) 249 250#define pci9111_hr_ai_get_data() \ 251 (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \ 252 ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT 253 254#define pci9111_ao_set_data(data) \ 255 outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT) 256 257#define pci9111_di_get_bits() \ 258 inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) 259 260#define pci9111_do_set_bits(bits) \ 261 outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO) 262 263#define pci9111_8254_control_set(flags) \ 264 outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL) 265 266#define pci9111_8254_counter_0_set(data) \ 267 outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \ 268 outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0) 269 270#define pci9111_8254_counter_1_set(data) \ 271 outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \ 272 outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1) 273 274#define pci9111_8254_counter_2_set(data) \ 275 outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \ 276 outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2) 277 278/* Function prototypes */ 279 280static int pci9111_attach(struct comedi_device *dev, 281 struct comedi_devconfig *it); 282static int pci9111_detach(struct comedi_device *dev); 283static void pci9111_ai_munge(struct comedi_device *dev, 284 struct comedi_subdevice *s, void *data, 285 unsigned int num_bytes, 286 unsigned int start_chan_index); 287 288static const struct comedi_lrange pci9111_hr_ai_range = { 289 5, 290 { 291 BIP_RANGE(10), 292 BIP_RANGE(5), 293 BIP_RANGE(2.5), 294 BIP_RANGE(1.25), 295 BIP_RANGE(0.625) 296 } 297}; 298 299static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = { 300 { 301 PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, 302 PCI_ANY_ID, 0, 0, 0}, 303 /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */ 304 { 305 0} 306}; 307 308MODULE_DEVICE_TABLE(pci, pci9111_pci_table); 309 310/* */ 311/* Board specification structure */ 312/* */ 313 314struct pci9111_board { 315 const char *name; /* driver name */ 316 int device_id; 317 int ai_channel_nbr; /* num of A/D chans */ 318 int ao_channel_nbr; /* num of D/A chans */ 319 int ai_resolution; /* resolution of A/D */ 320 int ai_resolution_mask; 321 int ao_resolution; /* resolution of D/A */ 322 int ao_resolution_mask; 323 const struct comedi_lrange *ai_range_list; /* rangelist for A/D */ 324 const struct comedi_lrange *ao_range_list; /* rangelist for D/A */ 325 unsigned int ai_acquisition_period_min_ns; 326}; 327 328static const struct pci9111_board pci9111_boards[] = { 329 { 330 .name = "pci9111_hr", 331 .device_id = PCI9111_HR_DEVICE_ID, 332 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR, 333 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR, 334 .ai_resolution = PCI9111_HR_AI_RESOLUTION, 335 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK, 336 .ao_resolution = PCI9111_AO_RESOLUTION, 337 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK, 338 .ai_range_list = &pci9111_hr_ai_range, 339 .ao_range_list = &range_bipolar10, 340 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS} 341}; 342 343#define pci9111_board_nbr \ 344 (sizeof(pci9111_boards)/sizeof(struct pci9111_board)) 345 346static struct comedi_driver pci9111_driver = { 347 .driver_name = PCI9111_DRIVER_NAME, 348 .module = THIS_MODULE, 349 .attach = pci9111_attach, 350 .detach = pci9111_detach, 351}; 352 353static int __devinit pci9111_driver_pci_probe(struct pci_dev *dev, 354 const struct pci_device_id *ent) 355{ 356 return comedi_pci_auto_config(dev, pci9111_driver.driver_name); 357} 358 359static void __devexit pci9111_driver_pci_remove(struct pci_dev *dev) 360{ 361 comedi_pci_auto_unconfig(dev); 362} 363 364static struct pci_driver pci9111_driver_pci_driver = { 365 .id_table = pci9111_pci_table, 366 .probe = &pci9111_driver_pci_probe, 367 .remove = __devexit_p(&pci9111_driver_pci_remove) 368}; 369 370static int __init pci9111_driver_init_module(void) 371{ 372 int retval; 373 374 retval = comedi_driver_register(&pci9111_driver); 375 if (retval < 0) 376 return retval; 377 378 pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name; 379 return pci_register_driver(&pci9111_driver_pci_driver); 380} 381 382static void __exit pci9111_driver_cleanup_module(void) 383{ 384 pci_unregister_driver(&pci9111_driver_pci_driver); 385 comedi_driver_unregister(&pci9111_driver); 386} 387 388module_init(pci9111_driver_init_module); 389module_exit(pci9111_driver_cleanup_module); 390 391/* Private data structure */ 392 393struct pci9111_private_data { 394 struct pci_dev *pci_device; 395 unsigned long io_range; /* PCI6503 io range */ 396 397 unsigned long lcr_io_base; /* Local configuration register base address */ 398 unsigned long lcr_io_range; 399 400 int stop_counter; 401 int stop_is_none; 402 403 unsigned int scan_delay; 404 unsigned int chanlist_len; 405 unsigned int chunk_counter; 406 unsigned int chunk_num_samples; 407 408 int ao_readback; /* Last written analog output data */ 409 410 unsigned int timer_divisor_1; /* Divisor values for the 8254 timer pacer */ 411 unsigned int timer_divisor_2; 412 413 int is_valid; /* Is device valid */ 414 415 short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE]; 416}; 417 418#define dev_private ((struct pci9111_private_data *)dev->private) 419 420/* ------------------------------------------------------------------ */ 421/* PLX9050 SECTION */ 422/* ------------------------------------------------------------------ */ 423 424#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c 425 426#define PLX9050_LINTI1_ENABLE (1 << 0) 427#define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1) 428#define PLX9050_LINTI1_STATUS (1 << 2) 429#define PLX9050_LINTI2_ENABLE (1 << 3) 430#define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4) 431#define PLX9050_LINTI2_STATUS (1 << 5) 432#define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6) 433#define PLX9050_SOFTWARE_INTERRUPT (1 << 7) 434 435static void plx9050_interrupt_control(unsigned long io_base, 436 bool LINTi1_enable, 437 bool LINTi1_active_high, 438 bool LINTi2_enable, 439 bool LINTi2_active_high, 440 bool interrupt_enable) 441{ 442 int flags = 0; 443 444 if (LINTi1_enable) 445 flags |= PLX9050_LINTI1_ENABLE; 446 if (LINTi1_active_high) 447 flags |= PLX9050_LINTI1_ACTIVE_HIGH; 448 if (LINTi2_enable) 449 flags |= PLX9050_LINTI2_ENABLE; 450 if (LINTi2_active_high) 451 flags |= PLX9050_LINTI2_ACTIVE_HIGH; 452 453 if (interrupt_enable) 454 flags |= PLX9050_PCI_INTERRUPT_ENABLE; 455 456 outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL); 457} 458 459/* ------------------------------------------------------------------ */ 460/* MISCELLANEOUS SECTION */ 461/* ------------------------------------------------------------------ */ 462 463/* 8254 timer */ 464 465static void pci9111_timer_set(struct comedi_device *dev) 466{ 467 pci9111_8254_control_set(PCI9111_8254_COUNTER_0 | 468 PCI9111_8254_READ_LOAD_LSB_MSB | 469 PCI9111_8254_MODE_0 | 470 PCI9111_8254_BINARY_COUNTER); 471 472 pci9111_8254_control_set(PCI9111_8254_COUNTER_1 | 473 PCI9111_8254_READ_LOAD_LSB_MSB | 474 PCI9111_8254_MODE_2 | 475 PCI9111_8254_BINARY_COUNTER); 476 477 pci9111_8254_control_set(PCI9111_8254_COUNTER_2 | 478 PCI9111_8254_READ_LOAD_LSB_MSB | 479 PCI9111_8254_MODE_2 | 480 PCI9111_8254_BINARY_COUNTER); 481 482 udelay(1); 483 484 pci9111_8254_counter_2_set(dev_private->timer_divisor_2); 485 pci9111_8254_counter_1_set(dev_private->timer_divisor_1); 486} 487 488enum pci9111_trigger_sources { 489 software, 490 timer_pacer, 491 external 492}; 493 494static void pci9111_trigger_source_set(struct comedi_device *dev, 495 enum pci9111_trigger_sources source) 496{ 497 int flags; 498 499 flags = pci9111_trigger_and_autoscan_get() & 0x09; 500 501 switch (source) { 502 case software: 503 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER; 504 break; 505 506 case timer_pacer: 507 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER; 508 break; 509 510 case external: 511 flags |= PCI9111_EITS_EXTERNAL; 512 break; 513 } 514 515 pci9111_trigger_and_autoscan_set(flags); 516} 517 518static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger) 519{ 520 int flags; 521 522 flags = pci9111_trigger_and_autoscan_get() & 0x07; 523 524 if (pretrigger) 525 flags |= PCI9111_PTRG_ON; 526 527 pci9111_trigger_and_autoscan_set(flags); 528} 529 530static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan) 531{ 532 int flags; 533 534 flags = pci9111_trigger_and_autoscan_get() & 0x0e; 535 536 if (autoscan) 537 flags |= PCI9111_ASCAN_ON; 538 539 pci9111_trigger_and_autoscan_set(flags); 540} 541 542enum pci9111_ISC0_sources { 543 irq_on_eoc, 544 irq_on_fifo_half_full 545}; 546 547enum pci9111_ISC1_sources { 548 irq_on_timer_tick, 549 irq_on_external_trigger 550}; 551 552static void pci9111_interrupt_source_set(struct comedi_device *dev, 553 enum pci9111_ISC0_sources irq_0_source, 554 enum pci9111_ISC1_sources irq_1_source) 555{ 556 int flags; 557 558 flags = pci9111_interrupt_and_fifo_get() & 0x04; 559 560 if (irq_0_source == irq_on_fifo_half_full) 561 flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL; 562 563 if (irq_1_source == irq_on_external_trigger) 564 flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG; 565 566 pci9111_interrupt_and_fifo_set(flags); 567} 568 569/* ------------------------------------------------------------------ */ 570/* HARDWARE TRIGGERED ANALOG INPUT SECTION */ 571/* ------------------------------------------------------------------ */ 572 573/* Cancel analog input autoscan */ 574 575#undef AI_DO_CMD_DEBUG 576 577static int pci9111_ai_cancel(struct comedi_device *dev, 578 struct comedi_subdevice *s) 579{ 580 /* Disable interrupts */ 581 582 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 583 true, false); 584 585 pci9111_trigger_source_set(dev, software); 586 587 pci9111_autoscan_set(dev, false); 588 589 pci9111_fifo_reset(); 590 591#ifdef AI_DO_CMD_DEBUG 592 printk(PCI9111_DRIVER_NAME ": ai_cancel\n"); 593#endif 594 595 return 0; 596} 597 598/* Test analog input command */ 599 600#define pci9111_check_trigger_src(src, flags) \ 601 tmp = src; \ 602 src &= flags; \ 603 if (!src || tmp != src) error++ 604 605static int 606pci9111_ai_do_cmd_test(struct comedi_device *dev, 607 struct comedi_subdevice *s, struct comedi_cmd *cmd) 608{ 609 int tmp; 610 int error = 0; 611 int range, reference; 612 int i; 613 struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr; 614 615 /* Step 1 : check if trigger are trivialy valid */ 616 617 pci9111_check_trigger_src(cmd->start_src, TRIG_NOW); 618 pci9111_check_trigger_src(cmd->scan_begin_src, 619 TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT); 620 pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT); 621 pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT); 622 pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE); 623 624 if (error) 625 return 1; 626 627 /* step 2 : make sure trigger sources are unique and mutually compatible */ 628 629 if (cmd->start_src != TRIG_NOW) 630 error++; 631 632 if ((cmd->scan_begin_src != TRIG_TIMER) && 633 (cmd->scan_begin_src != TRIG_FOLLOW) && 634 (cmd->scan_begin_src != TRIG_EXT)) 635 error++; 636 637 if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) 638 error++; 639 if ((cmd->convert_src == TRIG_TIMER) && 640 !((cmd->scan_begin_src == TRIG_TIMER) || 641 (cmd->scan_begin_src == TRIG_FOLLOW))) 642 error++; 643 if ((cmd->convert_src == TRIG_EXT) && 644 !((cmd->scan_begin_src == TRIG_EXT) || 645 (cmd->scan_begin_src == TRIG_FOLLOW))) 646 error++; 647 648 649 if (cmd->scan_end_src != TRIG_COUNT) 650 error++; 651 if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE)) 652 error++; 653 654 if (error) 655 return 2; 656 657 /* Step 3 : make sure arguments are trivialy compatible */ 658 659 if (cmd->chanlist_len < 1) { 660 cmd->chanlist_len = 1; 661 error++; 662 } 663 664 if (cmd->chanlist_len > board->ai_channel_nbr) { 665 cmd->chanlist_len = board->ai_channel_nbr; 666 error++; 667 } 668 669 if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) { 670 cmd->start_arg = 0; 671 error++; 672 } 673 674 if ((cmd->convert_src == TRIG_TIMER) && 675 (cmd->convert_arg < board->ai_acquisition_period_min_ns)) { 676 cmd->convert_arg = board->ai_acquisition_period_min_ns; 677 error++; 678 } 679 if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) { 680 cmd->convert_arg = 0; 681 error++; 682 } 683 684 if ((cmd->scan_begin_src == TRIG_TIMER) && 685 (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) { 686 cmd->scan_begin_arg = board->ai_acquisition_period_min_ns; 687 error++; 688 } 689 if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) { 690 cmd->scan_begin_arg = 0; 691 error++; 692 } 693 if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) { 694 cmd->scan_begin_arg = 0; 695 error++; 696 } 697 698 if ((cmd->scan_end_src == TRIG_COUNT) && 699 (cmd->scan_end_arg != cmd->chanlist_len)) { 700 cmd->scan_end_arg = cmd->chanlist_len; 701 error++; 702 } 703 704 if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) { 705 cmd->stop_arg = 1; 706 error++; 707 } 708 if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) { 709 cmd->stop_arg = 0; 710 error++; 711 } 712 713 if (error) 714 return 3; 715 716 /* Step 4 : fix up any arguments */ 717 718 if (cmd->convert_src == TRIG_TIMER) { 719 tmp = cmd->convert_arg; 720 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, 721 &(dev_private->timer_divisor_1), 722 &(dev_private->timer_divisor_2), 723 &(cmd->convert_arg), 724 cmd->flags & TRIG_ROUND_MASK); 725 if (tmp != cmd->convert_arg) 726 error++; 727 } 728 /* There's only one timer on this card, so the scan_begin timer must */ 729 /* be a multiple of chanlist_len*convert_arg */ 730 731 if (cmd->scan_begin_src == TRIG_TIMER) { 732 733 unsigned int scan_begin_min; 734 unsigned int scan_begin_arg; 735 unsigned int scan_factor; 736 737 scan_begin_min = cmd->chanlist_len * cmd->convert_arg; 738 739 if (cmd->scan_begin_arg != scan_begin_min) { 740 if (scan_begin_min < cmd->scan_begin_arg) { 741 scan_factor = 742 cmd->scan_begin_arg / scan_begin_min; 743 scan_begin_arg = scan_factor * scan_begin_min; 744 if (cmd->scan_begin_arg != scan_begin_arg) { 745 cmd->scan_begin_arg = scan_begin_arg; 746 error++; 747 } 748 } else { 749 cmd->scan_begin_arg = scan_begin_min; 750 error++; 751 } 752 } 753 } 754 755 if (error) 756 return 4; 757 758 /* Step 5 : check channel list */ 759 760 if (cmd->chanlist) { 761 762 range = CR_RANGE(cmd->chanlist[0]); 763 reference = CR_AREF(cmd->chanlist[0]); 764 765 if (cmd->chanlist_len > 1) { 766 for (i = 0; i < cmd->chanlist_len; i++) { 767 if (CR_CHAN(cmd->chanlist[i]) != i) { 768 comedi_error(dev, 769 "entries in chanlist must be consecutive " 770 "channels,counting upwards from 0\n"); 771 error++; 772 } 773 if (CR_RANGE(cmd->chanlist[i]) != range) { 774 comedi_error(dev, 775 "entries in chanlist must all have the same gain\n"); 776 error++; 777 } 778 if (CR_AREF(cmd->chanlist[i]) != reference) { 779 comedi_error(dev, 780 "entries in chanlist must all have the same reference\n"); 781 error++; 782 } 783 } 784 } else { 785 if ((CR_CHAN(cmd->chanlist[0]) > 786 (board->ai_channel_nbr - 1)) 787 || (CR_CHAN(cmd->chanlist[0]) < 0)) { 788 comedi_error(dev, 789 "channel number is out of limits\n"); 790 error++; 791 } 792 } 793 } 794 795 if (error) 796 return 5; 797 798 return 0; 799 800} 801 802/* Analog input command */ 803 804static int pci9111_ai_do_cmd(struct comedi_device *dev, 805 struct comedi_subdevice *subdevice) 806{ 807 struct comedi_cmd *async_cmd = &subdevice->async->cmd; 808 809 if (!dev->irq) { 810 comedi_error(dev, 811 "no irq assigned for PCI9111, cannot do hardware conversion"); 812 return -1; 813 } 814 /* Set channel scan limit */ 815 /* PCI9111 allows only scanning from channel 0 to channel n */ 816 /* TODO: handle the case of an external multiplexer */ 817 818 if (async_cmd->chanlist_len > 1) { 819 pci9111_ai_channel_set((async_cmd->chanlist_len) - 1); 820 pci9111_autoscan_set(dev, true); 821 } else { 822 pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0])); 823 pci9111_autoscan_set(dev, false); 824 } 825 826 /* Set gain */ 827 /* This is the same gain on every channel */ 828 829 pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0])); 830 831 /* Set counter */ 832 833 switch (async_cmd->stop_src) { 834 case TRIG_COUNT: 835 dev_private->stop_counter = 836 async_cmd->stop_arg * async_cmd->chanlist_len; 837 dev_private->stop_is_none = 0; 838 break; 839 840 case TRIG_NONE: 841 dev_private->stop_counter = 0; 842 dev_private->stop_is_none = 1; 843 break; 844 845 default: 846 comedi_error(dev, "Invalid stop trigger"); 847 return -1; 848 } 849 850 /* Set timer pacer */ 851 852 dev_private->scan_delay = 0; 853 switch (async_cmd->convert_src) { 854 case TRIG_TIMER: 855 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS, 856 &(dev_private->timer_divisor_1), 857 &(dev_private->timer_divisor_2), 858 &(async_cmd->convert_arg), 859 async_cmd-> 860 flags & TRIG_ROUND_MASK); 861#ifdef AI_DO_CMD_DEBUG 862 printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n", 863 dev_private->timer_divisor_1, 864 dev_private->timer_divisor_2); 865#endif 866 867 pci9111_trigger_source_set(dev, software); 868 pci9111_timer_set(dev); 869 pci9111_fifo_reset(); 870 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 871 irq_on_timer_tick); 872 pci9111_trigger_source_set(dev, timer_pacer); 873 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 874 false, true, true); 875 876 dev_private->scan_delay = 877 (async_cmd->scan_begin_arg / (async_cmd->convert_arg * 878 async_cmd->chanlist_len)) - 1; 879 880 break; 881 882 case TRIG_EXT: 883 884 pci9111_trigger_source_set(dev, external); 885 pci9111_fifo_reset(); 886 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full, 887 irq_on_timer_tick); 888 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, 889 false, true, true); 890 891 break; 892 893 default: 894 comedi_error(dev, "Invalid convert trigger"); 895 return -1; 896 } 897 898 dev_private->stop_counter *= (1 + dev_private->scan_delay); 899 dev_private->chanlist_len = async_cmd->chanlist_len; 900 dev_private->chunk_counter = 0; 901 dev_private->chunk_num_samples = 902 dev_private->chanlist_len * (1 + dev_private->scan_delay); 903 904#ifdef AI_DO_CMD_DEBUG 905 printk(PCI9111_DRIVER_NAME ": start interruptions!\n"); 906 printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n", 907 pci9111_trigger_and_autoscan_get()); 908 printk(PCI9111_DRIVER_NAME ": irq source = %2x\n", 909 pci9111_interrupt_and_fifo_get()); 910 printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n"); 911 printk(PCI9111_DRIVER_NAME ": stop counter = %d\n", 912 dev_private->stop_counter); 913 printk(PCI9111_DRIVER_NAME ": scan delay = %d\n", 914 dev_private->scan_delay); 915 printk(PCI9111_DRIVER_NAME ": chanlist_len = %d\n", 916 dev_private->chanlist_len); 917 printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n", 918 dev_private->chunk_num_samples); 919#endif 920 921 return 0; 922} 923 924static void pci9111_ai_munge(struct comedi_device *dev, 925 struct comedi_subdevice *s, void *data, 926 unsigned int num_bytes, 927 unsigned int start_chan_index) 928{ 929 unsigned int i, num_samples = num_bytes / sizeof(short); 930 short *array = data; 931 int resolution = 932 ((struct pci9111_board *)dev->board_ptr)->ai_resolution; 933 934 for (i = 0; i < num_samples; i++) { 935 if (resolution == PCI9111_HR_AI_RESOLUTION) 936 array[i] = 937 (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^ 938 PCI9111_HR_AI_RESOLUTION_2_CMP_BIT; 939 else 940 array[i] = 941 ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^ 942 PCI9111_AI_RESOLUTION_2_CMP_BIT; 943 } 944} 945 946/* ------------------------------------------------------------------ */ 947/* INTERRUPT SECTION */ 948/* ------------------------------------------------------------------ */ 949 950#undef INTERRUPT_DEBUG 951 952static irqreturn_t pci9111_interrupt(int irq, void *p_device) 953{ 954 struct comedi_device *dev = p_device; 955 struct comedi_subdevice *subdevice = dev->read_subdev; 956 struct comedi_async *async; 957 unsigned long irq_flags; 958 unsigned char intcsr; 959 960 if (!dev->attached) { 961 /* Ignore interrupt before device fully attached. */ 962 /* Might not even have allocated subdevices yet! */ 963 return IRQ_NONE; 964 } 965 966 async = subdevice->async; 967 968 spin_lock_irqsave(&dev->spinlock, irq_flags); 969 970 /* Check if we are source of interrupt */ 971 intcsr = inb(dev_private->lcr_io_base + 972 PLX9050_REGISTER_INTERRUPT_CONTROL); 973 if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0) 974 && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 975 == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) 976 || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS)) 977 == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) { 978 /* Not the source of the interrupt. */ 979 /* (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */ 980 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 981 return IRQ_NONE; 982 } 983 984 if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) == 985 (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) { 986 /* Interrupt comes from fifo_half-full signal */ 987 988 if (pci9111_is_fifo_full()) { 989 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 990 comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow"); 991 pci9111_interrupt_clear(); 992 pci9111_ai_cancel(dev, subdevice); 993 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; 994 comedi_event(dev, subdevice); 995 996 return IRQ_HANDLED; 997 } 998 999 if (pci9111_is_fifo_half_full()) { 1000 unsigned int num_samples; 1001 unsigned int bytes_written = 0; 1002 1003#ifdef INTERRUPT_DEBUG 1004 printk(PCI9111_DRIVER_NAME ": fifo is half full\n"); 1005#endif 1006 1007 num_samples = 1008 PCI9111_FIFO_HALF_SIZE > 1009 dev_private->stop_counter 1010 && !dev_private-> 1011 stop_is_none ? dev_private->stop_counter : 1012 PCI9111_FIFO_HALF_SIZE; 1013 insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE, 1014 dev_private->ai_bounce_buffer, num_samples); 1015 1016 if (dev_private->scan_delay < 1) { 1017 bytes_written = 1018 cfc_write_array_to_buffer(subdevice, 1019 dev_private-> 1020 ai_bounce_buffer, 1021 num_samples * 1022 sizeof(short)); 1023 } else { 1024 int position = 0; 1025 int to_read; 1026 1027 while (position < num_samples) { 1028 if (dev_private->chunk_counter < 1029 dev_private->chanlist_len) { 1030 to_read = 1031 dev_private->chanlist_len - 1032 dev_private->chunk_counter; 1033 1034 if (to_read > 1035 num_samples - position) 1036 to_read = 1037 num_samples - 1038 position; 1039 1040 bytes_written += 1041 cfc_write_array_to_buffer 1042 (subdevice, 1043 dev_private->ai_bounce_buffer 1044 + position, 1045 to_read * sizeof(short)); 1046 } else { 1047 to_read = 1048 dev_private->chunk_num_samples 1049 - 1050 dev_private->chunk_counter; 1051 if (to_read > 1052 num_samples - position) 1053 to_read = 1054 num_samples - 1055 position; 1056 1057 bytes_written += 1058 sizeof(short) * to_read; 1059 } 1060 1061 position += to_read; 1062 dev_private->chunk_counter += to_read; 1063 1064 if (dev_private->chunk_counter >= 1065 dev_private->chunk_num_samples) 1066 dev_private->chunk_counter = 0; 1067 } 1068 } 1069 1070 dev_private->stop_counter -= 1071 bytes_written / sizeof(short); 1072 } 1073 } 1074 1075 if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) { 1076 async->events |= COMEDI_CB_EOA; 1077 pci9111_ai_cancel(dev, subdevice); 1078 } 1079 1080 /* Very important, otherwise another interrupt request will be inserted 1081 * and will cause driver hangs on processing interrupt event. */ 1082 1083 pci9111_interrupt_clear(); 1084 1085 spin_unlock_irqrestore(&dev->spinlock, irq_flags); 1086 1087 comedi_event(dev, subdevice); 1088 1089 return IRQ_HANDLED; 1090} 1091 1092/* ------------------------------------------------------------------ */ 1093/* INSTANT ANALOG INPUT OUTPUT SECTION */ 1094/* ------------------------------------------------------------------ */ 1095 1096/* analog instant input */ 1097 1098#undef AI_INSN_DEBUG 1099 1100static int pci9111_ai_insn_read(struct comedi_device *dev, 1101 struct comedi_subdevice *subdevice, 1102 struct comedi_insn *insn, unsigned int *data) 1103{ 1104 int resolution = 1105 ((struct pci9111_board *)dev->board_ptr)->ai_resolution; 1106 1107 int timeout, i; 1108 1109#ifdef AI_INSN_DEBUG 1110 printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n", 1111 CR_CHAN((&insn->chanspec)[0]), 1112 CR_RANGE((&insn->chanspec)[0]), insn->n); 1113#endif 1114 1115 pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0])); 1116 1117 if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) 1118 pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0])); 1119 1120 pci9111_fifo_reset(); 1121 1122 for (i = 0; i < insn->n; i++) { 1123 pci9111_software_trigger(); 1124 1125 timeout = PCI9111_AI_INSTANT_READ_TIMEOUT; 1126 1127 while (timeout--) { 1128 if (!pci9111_is_fifo_empty()) 1129 goto conversion_done; 1130 } 1131 1132 comedi_error(dev, "A/D read timeout"); 1133 data[i] = 0; 1134 pci9111_fifo_reset(); 1135 return -ETIME; 1136 1137conversion_done: 1138 1139 if (resolution == PCI9111_HR_AI_RESOLUTION) 1140 data[i] = pci9111_hr_ai_get_data(); 1141 else 1142 data[i] = pci9111_ai_get_data(); 1143 } 1144 1145#ifdef AI_INSN_DEBUG 1146 printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n", 1147 pci9111_ai_channel_get(), 1148 pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get()); 1149#endif 1150 1151 return i; 1152} 1153 1154/* Analog instant output */ 1155 1156static int 1157pci9111_ao_insn_write(struct comedi_device *dev, 1158 struct comedi_subdevice *s, struct comedi_insn *insn, 1159 unsigned int *data) 1160{ 1161 int i; 1162 1163 for (i = 0; i < insn->n; i++) { 1164 pci9111_ao_set_data(data[i]); 1165 dev_private->ao_readback = data[i]; 1166 } 1167 1168 return i; 1169} 1170 1171/* Analog output readback */ 1172 1173static int pci9111_ao_insn_read(struct comedi_device *dev, 1174 struct comedi_subdevice *s, 1175 struct comedi_insn *insn, unsigned int *data) 1176{ 1177 int i; 1178 1179 for (i = 0; i < insn->n; i++) 1180 data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK; 1181 1182 return i; 1183} 1184 1185/* ------------------------------------------------------------------ */ 1186/* DIGITAL INPUT OUTPUT SECTION */ 1187/* ------------------------------------------------------------------ */ 1188 1189/* Digital inputs */ 1190 1191static int pci9111_di_insn_bits(struct comedi_device *dev, 1192 struct comedi_subdevice *subdevice, 1193 struct comedi_insn *insn, unsigned int *data) 1194{ 1195 unsigned int bits; 1196 1197 bits = pci9111_di_get_bits(); 1198 data[1] = bits; 1199 1200 return 2; 1201} 1202 1203/* Digital outputs */ 1204 1205static int pci9111_do_insn_bits(struct comedi_device *dev, 1206 struct comedi_subdevice *subdevice, 1207 struct comedi_insn *insn, unsigned int *data) 1208{ 1209 unsigned int bits; 1210 1211 /* Only set bits that have been masked */ 1212 /* data[0] = mask */ 1213 /* data[1] = bit state */ 1214 1215 data[0] &= PCI9111_DO_MASK; 1216 1217 bits = subdevice->state; 1218 bits &= ~data[0]; 1219 bits |= data[0] & data[1]; 1220 subdevice->state = bits; 1221 1222 pci9111_do_set_bits(bits); 1223 1224 data[1] = bits; 1225 1226 return 2; 1227} 1228 1229/* ------------------------------------------------------------------ */ 1230/* INITIALISATION SECTION */ 1231/* ------------------------------------------------------------------ */ 1232 1233/* Reset device */ 1234 1235static int pci9111_reset(struct comedi_device *dev) 1236{ 1237 /* Set trigger source to software */ 1238 1239 plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true, 1240 true, false); 1241 1242 pci9111_trigger_source_set(dev, software); 1243 pci9111_pretrigger_set(dev, false); 1244 pci9111_autoscan_set(dev, false); 1245 1246 /* Reset 8254 chip */ 1247 1248 dev_private->timer_divisor_1 = 0; 1249 dev_private->timer_divisor_2 = 0; 1250 1251 pci9111_timer_set(dev); 1252 1253 return 0; 1254} 1255 1256/* Attach */ 1257/* - Register PCI device */ 1258/* - Declare device driver capability */ 1259 1260static int pci9111_attach(struct comedi_device *dev, 1261 struct comedi_devconfig *it) 1262{ 1263 struct comedi_subdevice *subdevice; 1264 unsigned long io_base, io_range, lcr_io_base, lcr_io_range; 1265 struct pci_dev *pci_device; 1266 int error, i; 1267 const struct pci9111_board *board; 1268 1269 if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) 1270 return -ENOMEM; 1271 /* Probe the device to determine what device in the series it is. */ 1272 1273 printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor); 1274 1275 for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); 1276 pci_device != NULL; 1277 pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) { 1278 if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) { 1279 for (i = 0; i < pci9111_board_nbr; i++) { 1280 if (pci9111_boards[i].device_id == 1281 pci_device->device) { 1282 /* was a particular bus/slot requested? */ 1283 if ((it->options[0] != 0) 1284 || (it->options[1] != 0)) { 1285 /* are we on the wrong bus/slot? */ 1286 if (pci_device->bus->number != 1287 it->options[0] 1288 || 1289 PCI_SLOT(pci_device->devfn) 1290 != it->options[1]) { 1291 continue; 1292 } 1293 } 1294 1295 dev->board_ptr = pci9111_boards + i; 1296 board = 1297 (struct pci9111_board *) 1298 dev->board_ptr; 1299 dev_private->pci_device = pci_device; 1300 goto found; 1301 } 1302 } 1303 } 1304 } 1305 1306 printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n", 1307 dev->minor, it->options[0], it->options[1]); 1308 return -EIO; 1309 1310found: 1311 1312 printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n", 1313 dev->minor, 1314 pci9111_boards[i].name, 1315 pci_device->bus->number, 1316 PCI_SLOT(pci_device->devfn), 1317 PCI_FUNC(pci_device->devfn), pci_device->irq); 1318 1319 /* TODO: Warn about non-tested boards. */ 1320 1321 /* Read local configuration register base address [PCI_BASE_ADDRESS #1]. */ 1322 1323 lcr_io_base = pci_resource_start(pci_device, 1); 1324 lcr_io_range = pci_resource_len(pci_device, 1); 1325 1326 printk 1327 ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", 1328 dev->minor, lcr_io_base, lcr_io_range); 1329 1330 /* Enable PCI device and request regions */ 1331 if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) { 1332 printk 1333 ("comedi%d: Failed to enable PCI device and request regions\n", 1334 dev->minor); 1335 return -EIO; 1336 } 1337 /* Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */ 1338 1339 io_base = pci_resource_start(pci_device, 2); 1340 io_range = pci_resource_len(pci_device, 2); 1341 1342 printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n", 1343 dev->minor, io_base, io_range); 1344 1345 dev->iobase = io_base; 1346 dev->board_name = board->name; 1347 dev_private->io_range = io_range; 1348 dev_private->is_valid = 0; 1349 dev_private->lcr_io_base = lcr_io_base; 1350 dev_private->lcr_io_range = lcr_io_range; 1351 1352 pci9111_reset(dev); 1353 1354 /* Irq setup */ 1355 1356 dev->irq = 0; 1357 if (pci_device->irq > 0) { 1358 if (request_irq(pci_device->irq, pci9111_interrupt, 1359 IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) { 1360 printk("comedi%d: unable to allocate irq %u\n", 1361 dev->minor, pci_device->irq); 1362 return -EINVAL; 1363 } 1364 } 1365 dev->irq = pci_device->irq; 1366 1367 /* TODO: Add external multiplexer setup (according to option[2]). */ 1368 1369 error = alloc_subdevices(dev, 4); 1370 if (error < 0) 1371 return error; 1372 1373 subdevice = dev->subdevices + 0; 1374 dev->read_subdev = subdevice; 1375 1376 subdevice->type = COMEDI_SUBD_AI; 1377 subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ; 1378 1379 /* TODO: Add external multiplexer data */ 1380 /* if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */ 1381 /* else { subdevice->n_chan = this_board->n_aichan; } */ 1382 1383 subdevice->n_chan = board->ai_channel_nbr; 1384 subdevice->maxdata = board->ai_resolution_mask; 1385 subdevice->len_chanlist = board->ai_channel_nbr; 1386 subdevice->range_table = board->ai_range_list; 1387 subdevice->cancel = pci9111_ai_cancel; 1388 subdevice->insn_read = pci9111_ai_insn_read; 1389 subdevice->do_cmdtest = pci9111_ai_do_cmd_test; 1390 subdevice->do_cmd = pci9111_ai_do_cmd; 1391 subdevice->munge = pci9111_ai_munge; 1392 1393 subdevice = dev->subdevices + 1; 1394 subdevice->type = COMEDI_SUBD_AO; 1395 subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON; 1396 subdevice->n_chan = board->ao_channel_nbr; 1397 subdevice->maxdata = board->ao_resolution_mask; 1398 subdevice->len_chanlist = board->ao_channel_nbr; 1399 subdevice->range_table = board->ao_range_list; 1400 subdevice->insn_write = pci9111_ao_insn_write; 1401 subdevice->insn_read = pci9111_ao_insn_read; 1402 1403 subdevice = dev->subdevices + 2; 1404 subdevice->type = COMEDI_SUBD_DI; 1405 subdevice->subdev_flags = SDF_READABLE; 1406 subdevice->n_chan = PCI9111_DI_CHANNEL_NBR; 1407 subdevice->maxdata = 1; 1408 subdevice->range_table = &range_digital; 1409 subdevice->insn_bits = pci9111_di_insn_bits; 1410 1411 subdevice = dev->subdevices + 3; 1412 subdevice->type = COMEDI_SUBD_DO; 1413 subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE; 1414 subdevice->n_chan = PCI9111_DO_CHANNEL_NBR; 1415 subdevice->maxdata = 1; 1416 subdevice->range_table = &range_digital; 1417 subdevice->insn_bits = pci9111_do_insn_bits; 1418 1419 dev_private->is_valid = 1; 1420 1421 return 0; 1422} 1423 1424/* Detach */ 1425 1426static int pci9111_detach(struct comedi_device *dev) 1427{ 1428 /* Reset device */ 1429 1430 if (dev->private != NULL) { 1431 if (dev_private->is_valid) 1432 pci9111_reset(dev); 1433 1434 } 1435 /* Release previously allocated irq */ 1436 1437 if (dev->irq != 0) 1438 free_irq(dev->irq, dev); 1439 1440 if (dev_private != NULL && dev_private->pci_device != NULL) { 1441 if (dev->iobase) 1442 comedi_pci_disable(dev_private->pci_device); 1443 pci_dev_put(dev_private->pci_device); 1444 } 1445 1446 return 0; 1447} 1448 1449MODULE_AUTHOR("Comedi http://www.comedi.org"); 1450MODULE_DESCRIPTION("Comedi low-level driver"); 1451MODULE_LICENSE("GPL"); 1452