amplc_dio200.c revision 669c930c8fe266917865f923db51c3b654ab78a3
1/* 2 comedi/drivers/amplc_dio200.c 3 Driver for Amplicon PC272E and PCI272 DIO boards. 4 (Support for other boards in Amplicon 200 series may be added at 5 a later date, e.g. PCI215.) 6 7 Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/> 8 9 COMEDI - Linux Control and Measurement Device Interface 10 Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org> 11 12 This program is free software; you can redistribute it and/or modify 13 it under the terms of the GNU General Public License as published by 14 the Free Software Foundation; either version 2 of the License, or 15 (at your option) any later version. 16 17 This program is distributed in the hope that it will be useful, 18 but WITHOUT ANY WARRANTY; without even the implied warranty of 19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 GNU General Public License for more details. 21 22 You should have received a copy of the GNU General Public License 23 along with this program; if not, write to the Free Software 24 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 25 26*/ 27/* 28Driver: amplc_dio200 29Description: Amplicon 200 Series Digital I/O 30Author: Ian Abbott <abbotti@mev.co.uk> 31Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e), 32 PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e), 33 PCI272 (pci272 or amplc_dio200) 34Updated: Wed, 22 Oct 2008 13:36:02 +0100 35Status: works 36 37Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E: 38 [0] - I/O port base address 39 [1] - IRQ (optional, but commands won't work without it) 40 41Configuration options - PCI215, PCI272: 42 [0] - PCI bus of device (optional) 43 [1] - PCI slot of device (optional) 44 If bus/slot is not specified, the first available PCI device will 45 be used. 46 47Passing a zero for an option is the same as leaving it unspecified. 48 49SUBDEVICES 50 51 PC218E PC212E PC215E/PCI215 52 ------------- ------------- ------------- 53 Subdevices 7 6 5 54 0 CTR-X1 PPI-X PPI-X 55 1 CTR-X2 CTR-Y1 PPI-Y 56 2 CTR-Y1 CTR-Y2 CTR-Z1 57 3 CTR-Y2 CTR-Z1 CTR-Z2 58 4 CTR-Z1 CTR-Z2 INTERRUPT 59 5 CTR-Z2 INTERRUPT 60 6 INTERRUPT 61 62 PC214E PC272E/PCI272 63 ------------- ------------- 64 Subdevices 4 4 65 0 PPI-X PPI-X 66 1 PPI-Y PPI-Y 67 2 CTR-Z1* PPI-Z 68 3 INTERRUPT* INTERRUPT 69 70Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels 71are configurable as inputs or outputs in four groups: 72 73 Port A - channels 0 to 7 74 Port B - channels 8 to 15 75 Port CL - channels 16 to 19 76 Port CH - channels 20 to 23 77 78Only mode 0 of the 8255 chips is supported. 79 80Each CTR is a 8254 chip providing 3 16-bit counter channels. Each 81channel is configured individually with INSN_CONFIG instructions. The 82specific type of configuration instruction is specified in data[0]. 83Some configuration instructions expect an additional parameter in 84data[1]; others return a value in data[1]. The following configuration 85instructions are supported: 86 87 INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and 88 BCD/binary setting specified in data[1]. 89 90 INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the 91 counter channel into data[1]. 92 93 INSN_CONFIG_SET_CLOCK_SRC. Sets the counter channel's clock source as 94 specified in data[1] (this is a hardware-specific value). Not 95 supported on PC214E. For the other boards, valid clock sources are 96 0 to 7 as follows: 97 98 0. CLK n, the counter channel's dedicated CLK input from the SK1 99 connector. (N.B. for other values, the counter channel's CLKn 100 pin on the SK1 connector is an output!) 101 1. Internal 10 MHz clock. 102 2. Internal 1 MHz clock. 103 3. Internal 100 kHz clock. 104 4. Internal 10 kHz clock. 105 5. Internal 1 kHz clock. 106 6. OUT n-1, the output of counter channel n-1 (see note 1 below). 107 7. Ext Clock, the counter chip's dedicated Ext Clock input from 108 the SK1 connector. This pin is shared by all three counter 109 channels on the chip. 110 111 INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current 112 clock source in data[1]. For internal clock sources, data[2] is set 113 to the period in ns. 114 115 INSN_CONFIG_SET_GATE_SRC. Sets the counter channel's gate source as 116 specified in data[2] (this is a hardware-specific value). Not 117 supported on PC214E. For the other boards, valid gate sources are 0 118 to 7 as follows: 119 120 0. VCC (internal +5V d.c.), i.e. gate permanently enabled. 121 1. GND (internal 0V d.c.), i.e. gate permanently disabled. 122 2. GAT n, the counter channel's dedicated GAT input from the SK1 123 connector. (N.B. for other values, the counter channel's GATn 124 pin on the SK1 connector is an output!) 125 3. /OUT n-2, the inverted output of counter channel n-2 (see note 126 2 below). 127 4. Reserved. 128 5. Reserved. 129 6. Reserved. 130 7. Reserved. 131 132 INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate 133 source in data[2]. 134 135Clock and gate interconnection notes: 136 137 1. Clock source OUT n-1 is the output of the preceding channel on the 138 same counter subdevice if n > 0, or the output of channel 2 on the 139 preceding counter subdevice (see note 3) if n = 0. 140 141 2. Gate source /OUT n-2 is the inverted output of channel 0 on the 142 same counter subdevice if n = 2, or the inverted output of channel n+1 143 on the preceding counter subdevice (see note 3) if n < 2. 144 145 3. The counter subdevices are connected in a ring, so the highest 146 counter subdevice precedes the lowest. 147 148The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The 149digital inputs come from the interrupt status register. The number of 150channels matches the number of interrupt sources. The PC214E does not 151have an interrupt status register; see notes on 'INTERRUPT SOURCES' 152below. 153 154INTERRUPT SOURCES 155 156 PC218E PC212E PC215E/PCI215 157 ------------- ------------- ------------- 158 Sources 6 6 6 159 0 CTR-X1-OUT PPI-X-C0 PPI-X-C0 160 1 CTR-X2-OUT PPI-X-C3 PPI-X-C3 161 2 CTR-Y1-OUT CTR-Y1-OUT PPI-Y-C0 162 3 CTR-Y2-OUT CTR-Y2-OUT PPI-Y-C3 163 4 CTR-Z1-OUT CTR-Z1-OUT CTR-Z1-OUT 164 5 CTR-Z2-OUT CTR-Z2-OUT CTR-Z2-OUT 165 166 PC214E PC272E/PCI272 167 ------------- ------------- 168 Sources 1 6 169 0 JUMPER-J5 PPI-X-C0 170 1 PPI-X-C3 171 2 PPI-Y-C0 172 3 PPI-Y-C3 173 4 PPI-Z-C0 174 5 PPI-Z-C3 175 176When an interrupt source is enabled in the interrupt source enable 177register, a rising edge on the source signal latches the corresponding 178bit to 1 in the interrupt status register. 179 180When the interrupt status register value as a whole (actually, just the 1816 least significant bits) goes from zero to non-zero, the board will 182generate an interrupt. For level-triggered hardware interrupts (PCI 183card), the interrupt will remain asserted until the interrupt status 184register is cleared to zero. For edge-triggered hardware interrupts 185(ISA card), no further interrupts will occur until the interrupt status 186register is cleared to zero. To clear a bit to zero in the interrupt 187status register, the corresponding interrupt source must be disabled 188in the interrupt source enable register (there is no separate interrupt 189clear register). 190 191The PC214E does not have an interrupt source enable register or an 192interrupt status register; its 'INTERRUPT' subdevice has a single 193channel and its interrupt source is selected by the position of jumper 194J5. 195 196COMMANDS 197 198The driver supports a read streaming acquisition command on the 199'INTERRUPT' subdevice. The channel list selects the interrupt sources 200to be enabled. All channels will be sampled together (convert_src == 201TRIG_NOW). The scan begins a short time after the hardware interrupt 202occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT, 203scan_begin_arg == 0). The value read from the interrupt status register 204is packed into a short value, one bit per requested channel, in the 205order they appear in the channel list. 206*/ 207 208#include <linux/interrupt.h> 209 210#include "../comedidev.h" 211 212#include "comedi_pci.h" 213 214#include "8255.h" 215#include "8253.h" 216 217#define DIO200_DRIVER_NAME "amplc_dio200" 218 219/* PCI IDs */ 220/* #define PCI_VENDOR_ID_AMPLICON 0x14dc */ 221#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a 222#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b 223#define PCI_DEVICE_ID_INVALID 0xffff 224 225/* 200 series registers */ 226#define DIO200_IO_SIZE 0x20 227#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */ 228#define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */ 229#define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */ 230#define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */ 231#define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */ 232#define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */ 233#define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */ 234 235/* 236 * Macros for constructing value for DIO_200_?CLK_SCE and 237 * DIO_200_?GAT_SCE registers: 238 * 239 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2. 240 * 'chan' is the channel: 0, 1 or 2. 241 * 'source' is the signal source: 0 to 7. 242 */ 243#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source)) 244#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source)) 245 246/* 247 * Periods of the internal clock sources in nanoseconds. 248 */ 249static const unsigned clock_period[8] = { 250 0, /* dedicated clock input/output pin */ 251 100, /* 10 MHz */ 252 1000, /* 1 MHz */ 253 10000, /* 100 kHz */ 254 100000, /* 10 kHz */ 255 1000000, /* 1 kHz */ 256 0, /* OUT N-1 */ 257 0 /* group clock input pin */ 258}; 259 260/* 261 * Board descriptions. 262 */ 263 264enum dio200_bustype { isa_bustype, pci_bustype }; 265 266enum dio200_model { 267 pc212e_model, 268 pc214e_model, 269 pc215e_model, pci215_model, 270 pc218e_model, 271 pc272e_model, pci272_model, 272 anypci_model 273}; 274 275enum dio200_layout { 276 pc212_layout, 277 pc214_layout, 278 pc215_layout, 279 pc218_layout, 280 pc272_layout 281}; 282 283struct dio200_board { 284 const char *name; 285 unsigned short devid; 286 enum dio200_bustype bustype; 287 enum dio200_model model; 288 enum dio200_layout layout; 289}; 290 291static const struct dio200_board dio200_boards[] = { 292 { 293 .name = "pc212e", 294 .bustype = isa_bustype, 295 .model = pc212e_model, 296 .layout = pc212_layout, 297 }, 298 { 299 .name = "pc214e", 300 .bustype = isa_bustype, 301 .model = pc214e_model, 302 .layout = pc214_layout, 303 }, 304 { 305 .name = "pc215e", 306 .bustype = isa_bustype, 307 .model = pc215e_model, 308 .layout = pc215_layout, 309 }, 310#ifdef CONFIG_COMEDI_PCI 311 { 312 .name = "pci215", 313 .devid = PCI_DEVICE_ID_AMPLICON_PCI215, 314 .bustype = pci_bustype, 315 .model = pci215_model, 316 .layout = pc215_layout, 317 }, 318#endif 319 { 320 .name = "pc218e", 321 .bustype = isa_bustype, 322 .model = pc218e_model, 323 .layout = pc218_layout, 324 }, 325 { 326 .name = "pc272e", 327 .bustype = isa_bustype, 328 .model = pc272e_model, 329 .layout = pc272_layout, 330 }, 331#ifdef CONFIG_COMEDI_PCI 332 { 333 .name = "pci272", 334 .devid = PCI_DEVICE_ID_AMPLICON_PCI272, 335 .bustype = pci_bustype, 336 .model = pci272_model, 337 .layout = pc272_layout, 338 }, 339#endif 340#ifdef CONFIG_COMEDI_PCI 341 { 342 .name = DIO200_DRIVER_NAME, 343 .devid = PCI_DEVICE_ID_INVALID, 344 .bustype = pci_bustype, 345 .model = anypci_model, /* wildcard */ 346 }, 347#endif 348}; 349 350/* 351 * Layout descriptions - some ISA and PCI board descriptions share the same 352 * layout. 353 */ 354 355enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 }; 356 357#define DIO200_MAX_SUBDEVS 7 358#define DIO200_MAX_ISNS 6 359 360struct dio200_layout_struct { 361 unsigned short n_subdevs; /* number of subdevices */ 362 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */ 363 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */ 364 char has_int_sce; /* has interrupt enable/status register */ 365 char has_clk_gat_sce; /* has clock/gate selection registers */ 366}; 367 368static const struct dio200_layout_struct dio200_layouts[] = { 369 [pc212_layout] = { 370 .n_subdevs = 6, 371 .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254, 372 sd_8254, 373 sd_intr}, 374 .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14, 375 0x3F}, 376 .has_int_sce = 1, 377 .has_clk_gat_sce = 1, 378 }, 379 [pc214_layout] = { 380 .n_subdevs = 4, 381 .sdtype = {sd_8255, sd_8255, sd_8254, 382 sd_intr}, 383 .sdinfo = {0x00, 0x08, 0x10, 0x01}, 384 .has_int_sce = 0, 385 .has_clk_gat_sce = 0, 386 }, 387 [pc215_layout] = { 388 .n_subdevs = 5, 389 .sdtype = {sd_8255, sd_8255, sd_8254, 390 sd_8254, 391 sd_intr}, 392 .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F}, 393 .has_int_sce = 1, 394 .has_clk_gat_sce = 1, 395 }, 396 [pc218_layout] = { 397 .n_subdevs = 7, 398 .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254, 399 sd_8254, 400 sd_intr}, 401 .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10, 402 0x14, 403 0x3F}, 404 .has_int_sce = 1, 405 .has_clk_gat_sce = 1, 406 }, 407 [pc272_layout] = { 408 .n_subdevs = 4, 409 .sdtype = {sd_8255, sd_8255, sd_8255, 410 sd_intr}, 411 .sdinfo = {0x00, 0x08, 0x10, 0x3F}, 412 .has_int_sce = 1, 413 .has_clk_gat_sce = 0, 414 }, 415}; 416 417/* 418 * PCI driver table. 419 */ 420 421#ifdef CONFIG_COMEDI_PCI 422static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = { 423 { 424 PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215, 425 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 426 PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272, 427 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, { 428 0} 429}; 430 431MODULE_DEVICE_TABLE(pci, dio200_pci_table); 432#endif /* CONFIG_COMEDI_PCI */ 433 434/* 435 * Useful for shorthand access to the particular board structure 436 */ 437#define thisboard ((const struct dio200_board *)dev->board_ptr) 438#define thislayout (&dio200_layouts[((struct dio200_board *) \ 439 dev->board_ptr)->layout]) 440 441/* this structure is for data unique to this hardware driver. If 442 several hardware drivers keep similar information in this structure, 443 feel free to suggest moving the variable to the struct comedi_device struct. 444 */ 445struct dio200_private { 446#ifdef CONFIG_COMEDI_PCI 447 struct pci_dev *pci_dev; /* PCI device */ 448#endif 449 int intr_sd; 450}; 451 452#define devpriv ((struct dio200_private *)dev->private) 453 454struct dio200_subdev_8254 { 455 unsigned long iobase; /* Counter base address */ 456 unsigned long clk_sce_iobase; /* CLK_SCE base address */ 457 unsigned long gat_sce_iobase; /* GAT_SCE base address */ 458 int which; /* Bit 5 of CLK_SCE or GAT_SCE */ 459 int has_clk_gat_sce; 460 unsigned clock_src[3]; /* Current clock sources */ 461 unsigned gate_src[3]; /* Current gate sources */ 462}; 463 464struct dio200_subdev_intr { 465 unsigned long iobase; 466 spinlock_t spinlock; 467 int active; 468 int has_int_sce; 469 unsigned int valid_isns; 470 unsigned int enabled_isns; 471 unsigned int stopcount; 472 int continuous; 473}; 474 475/* 476 * The struct comedi_driver structure tells the Comedi core module 477 * which functions to call to configure/deconfigure (attach/detach) 478 * the board, and also about the kernel module that contains 479 * the device code. 480 */ 481static int dio200_attach(struct comedi_device *dev, 482 struct comedi_devconfig *it); 483static int dio200_detach(struct comedi_device *dev); 484static struct comedi_driver driver_amplc_dio200 = { 485 .driver_name = DIO200_DRIVER_NAME, 486 .module = THIS_MODULE, 487 .attach = dio200_attach, 488 .detach = dio200_detach, 489 .board_name = &dio200_boards[0].name, 490 .offset = sizeof(struct dio200_board), 491 .num_names = ARRAY_SIZE(dio200_boards), 492}; 493 494#ifdef CONFIG_COMEDI_PCI 495COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table); 496#else 497COMEDI_INITCLEANUP(driver_amplc_dio200); 498#endif 499 500/* 501 * This function looks for a PCI device matching the requested board name, 502 * bus and slot. 503 */ 504#ifdef CONFIG_COMEDI_PCI 505static int 506dio200_find_pci(struct comedi_device *dev, int bus, int slot, 507 struct pci_dev **pci_dev_p) 508{ 509 struct pci_dev *pci_dev = NULL; 510 511 *pci_dev_p = NULL; 512 513 /* Look for matching PCI device. */ 514 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL); 515 pci_dev != NULL; 516 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, 517 PCI_ANY_ID, pci_dev)) { 518 /* If bus/slot specified, check them. */ 519 if (bus || slot) { 520 if (bus != pci_dev->bus->number 521 || slot != PCI_SLOT(pci_dev->devfn)) 522 continue; 523 } 524 if (thisboard->model == anypci_model) { 525 /* Match any supported model. */ 526 int i; 527 528 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) { 529 if (dio200_boards[i].bustype != pci_bustype) 530 continue; 531 if (pci_dev->device == dio200_boards[i].devid) { 532 /* Change board_ptr to matched board. */ 533 dev->board_ptr = &dio200_boards[i]; 534 break; 535 } 536 } 537 if (i == ARRAY_SIZE(dio200_boards)) 538 continue; 539 } else { 540 /* Match specific model name. */ 541 if (pci_dev->device != thisboard->devid) 542 continue; 543 } 544 545 /* Found a match. */ 546 *pci_dev_p = pci_dev; 547 return 0; 548 } 549 /* No match found. */ 550 if (bus || slot) { 551 printk(KERN_ERR 552 "comedi%d: error! no %s found at pci %02x:%02x!\n", 553 dev->minor, thisboard->name, bus, slot); 554 } else { 555 printk(KERN_ERR "comedi%d: error! no %s found!\n", 556 dev->minor, thisboard->name); 557 } 558 return -EIO; 559} 560#endif 561 562/* 563 * This function checks and requests an I/O region, reporting an error 564 * if there is a conflict. 565 */ 566static int 567dio200_request_region(unsigned minor, unsigned long from, unsigned long extent) 568{ 569 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) { 570 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n", 571 minor, from, extent); 572 return -EIO; 573 } 574 return 0; 575} 576 577/* 578 * 'insn_bits' function for an 'INTERRUPT' subdevice. 579 */ 580static int 581dio200_subdev_intr_insn_bits(struct comedi_device *dev, 582 struct comedi_subdevice *s, 583 struct comedi_insn *insn, unsigned int *data) 584{ 585 struct dio200_subdev_intr *subpriv = s->private; 586 587 if (subpriv->has_int_sce) { 588 /* Just read the interrupt status register. */ 589 data[1] = inb(subpriv->iobase) & subpriv->valid_isns; 590 } else { 591 /* No interrupt status register. */ 592 data[0] = 0; 593 } 594 595 return 2; 596} 597 598/* 599 * Called to stop acquisition for an 'INTERRUPT' subdevice. 600 */ 601static void dio200_stop_intr(struct comedi_device *dev, 602 struct comedi_subdevice *s) 603{ 604 struct dio200_subdev_intr *subpriv = s->private; 605 606 subpriv->active = 0; 607 subpriv->enabled_isns = 0; 608 if (subpriv->has_int_sce) 609 outb(0, subpriv->iobase); 610} 611 612/* 613 * Called to start acquisition for an 'INTERRUPT' subdevice. 614 */ 615static int dio200_start_intr(struct comedi_device *dev, 616 struct comedi_subdevice *s) 617{ 618 unsigned int n; 619 unsigned isn_bits; 620 struct dio200_subdev_intr *subpriv = s->private; 621 struct comedi_cmd *cmd = &s->async->cmd; 622 int retval = 0; 623 624 if (!subpriv->continuous && subpriv->stopcount == 0) { 625 /* An empty acquisition! */ 626 s->async->events |= COMEDI_CB_EOA; 627 subpriv->active = 0; 628 retval = 1; 629 } else { 630 /* Determine interrupt sources to enable. */ 631 isn_bits = 0; 632 if (cmd->chanlist) { 633 for (n = 0; n < cmd->chanlist_len; n++) 634 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n])); 635 } 636 isn_bits &= subpriv->valid_isns; 637 /* Enable interrupt sources. */ 638 subpriv->enabled_isns = isn_bits; 639 if (subpriv->has_int_sce) 640 outb(isn_bits, subpriv->iobase); 641 } 642 643 return retval; 644} 645 646/* 647 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice. 648 */ 649static int 650dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s, 651 unsigned int trignum) 652{ 653 struct dio200_subdev_intr *subpriv; 654 unsigned long flags; 655 int event = 0; 656 657 if (trignum != 0) 658 return -EINVAL; 659 660 subpriv = s->private; 661 662 spin_lock_irqsave(&subpriv->spinlock, flags); 663 s->async->inttrig = 0; 664 if (subpriv->active) 665 event = dio200_start_intr(dev, s); 666 667 spin_unlock_irqrestore(&subpriv->spinlock, flags); 668 669 if (event) 670 comedi_event(dev, s); 671 672 return 1; 673} 674 675/* 676 * This is called from the interrupt service routine to handle a read 677 * scan on an 'INTERRUPT' subdevice. 678 */ 679static int dio200_handle_read_intr(struct comedi_device *dev, 680 struct comedi_subdevice *s) 681{ 682 struct dio200_subdev_intr *subpriv = s->private; 683 unsigned triggered; 684 unsigned intstat; 685 unsigned cur_enabled; 686 unsigned int oldevents; 687 unsigned long flags; 688 689 triggered = 0; 690 691 spin_lock_irqsave(&subpriv->spinlock, flags); 692 oldevents = s->async->events; 693 if (subpriv->has_int_sce) { 694 /* 695 * Collect interrupt sources that have triggered and disable 696 * them temporarily. Loop around until no extra interrupt 697 * sources have triggered, at which point, the valid part of 698 * the interrupt status register will read zero, clearing the 699 * cause of the interrupt. 700 * 701 * Mask off interrupt sources already seen to avoid infinite 702 * loop in case of misconfiguration. 703 */ 704 cur_enabled = subpriv->enabled_isns; 705 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns 706 & ~triggered)) != 0) { 707 triggered |= intstat; 708 cur_enabled &= ~triggered; 709 outb(cur_enabled, subpriv->iobase); 710 } 711 } else { 712 /* 713 * No interrupt status register. Assume the single interrupt 714 * source has triggered. 715 */ 716 triggered = subpriv->enabled_isns; 717 } 718 719 if (triggered) { 720 /* 721 * Some interrupt sources have triggered and have been 722 * temporarily disabled to clear the cause of the interrupt. 723 * 724 * Reenable them NOW to minimize the time they are disabled. 725 */ 726 cur_enabled = subpriv->enabled_isns; 727 if (subpriv->has_int_sce) 728 outb(cur_enabled, subpriv->iobase); 729 730 if (subpriv->active) { 731 /* 732 * The command is still active. 733 * 734 * Ignore interrupt sources that the command isn't 735 * interested in (just in case there's a race 736 * condition). 737 */ 738 if (triggered & subpriv->enabled_isns) { 739 /* Collect scan data. */ 740 short val; 741 unsigned int n, ch, len; 742 743 val = 0; 744 len = s->async->cmd.chanlist_len; 745 for (n = 0; n < len; n++) { 746 ch = CR_CHAN(s->async->cmd.chanlist[n]); 747 if (triggered & (1U << ch)) 748 val |= (1U << n); 749 } 750 /* Write the scan to the buffer. */ 751 if (comedi_buf_put(s->async, val)) { 752 s->async->events |= (COMEDI_CB_BLOCK | 753 COMEDI_CB_EOS); 754 } else { 755 /* Error! Stop acquisition. */ 756 dio200_stop_intr(dev, s); 757 s->async->events |= COMEDI_CB_ERROR 758 | COMEDI_CB_OVERFLOW; 759 comedi_error(dev, "buffer overflow"); 760 } 761 762 /* Check for end of acquisition. */ 763 if (!subpriv->continuous) { 764 /* stop_src == TRIG_COUNT */ 765 if (subpriv->stopcount > 0) { 766 subpriv->stopcount--; 767 if (subpriv->stopcount == 0) { 768 s->async->events |= 769 COMEDI_CB_EOA; 770 dio200_stop_intr(dev, 771 s); 772 } 773 } 774 } 775 } 776 } 777 } 778 spin_unlock_irqrestore(&subpriv->spinlock, flags); 779 780 if (oldevents != s->async->events) 781 comedi_event(dev, s); 782 783 return (triggered != 0); 784} 785 786/* 787 * 'cancel' function for an 'INTERRUPT' subdevice. 788 */ 789static int dio200_subdev_intr_cancel(struct comedi_device *dev, 790 struct comedi_subdevice *s) 791{ 792 struct dio200_subdev_intr *subpriv = s->private; 793 unsigned long flags; 794 795 spin_lock_irqsave(&subpriv->spinlock, flags); 796 if (subpriv->active) 797 dio200_stop_intr(dev, s); 798 799 spin_unlock_irqrestore(&subpriv->spinlock, flags); 800 801 return 0; 802} 803 804/* 805 * 'do_cmdtest' function for an 'INTERRUPT' subdevice. 806 */ 807static int 808dio200_subdev_intr_cmdtest(struct comedi_device *dev, 809 struct comedi_subdevice *s, struct comedi_cmd *cmd) 810{ 811 int err = 0; 812 unsigned int tmp; 813 814 /* step 1: make sure trigger sources are trivially valid */ 815 816 tmp = cmd->start_src; 817 cmd->start_src &= (TRIG_NOW | TRIG_INT); 818 if (!cmd->start_src || tmp != cmd->start_src) 819 err++; 820 821 tmp = cmd->scan_begin_src; 822 cmd->scan_begin_src &= TRIG_EXT; 823 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 824 err++; 825 826 tmp = cmd->convert_src; 827 cmd->convert_src &= TRIG_NOW; 828 if (!cmd->convert_src || tmp != cmd->convert_src) 829 err++; 830 831 tmp = cmd->scan_end_src; 832 cmd->scan_end_src &= TRIG_COUNT; 833 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 834 err++; 835 836 tmp = cmd->stop_src; 837 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE); 838 if (!cmd->stop_src || tmp != cmd->stop_src) 839 err++; 840 841 if (err) 842 return 1; 843 844 /* step 2: make sure trigger sources are unique and mutually 845 compatible */ 846 847 /* these tests are true if more than one _src bit is set */ 848 if ((cmd->start_src & (cmd->start_src - 1)) != 0) 849 err++; 850 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0) 851 err++; 852 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0) 853 err++; 854 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0) 855 err++; 856 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0) 857 err++; 858 859 if (err) 860 return 2; 861 862 /* step 3: make sure arguments are trivially compatible */ 863 864 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */ 865 if (cmd->start_arg != 0) { 866 cmd->start_arg = 0; 867 err++; 868 } 869 870 /* cmd->scan_begin_src == TRIG_EXT */ 871 if (cmd->scan_begin_arg != 0) { 872 cmd->scan_begin_arg = 0; 873 err++; 874 } 875 876 /* cmd->convert_src == TRIG_NOW */ 877 if (cmd->convert_arg != 0) { 878 cmd->convert_arg = 0; 879 err++; 880 } 881 882 /* cmd->scan_end_src == TRIG_COUNT */ 883 if (cmd->scan_end_arg != cmd->chanlist_len) { 884 cmd->scan_end_arg = cmd->chanlist_len; 885 err++; 886 } 887 888 switch (cmd->stop_src) { 889 case TRIG_COUNT: 890 /* any count allowed */ 891 break; 892 case TRIG_NONE: 893 if (cmd->stop_arg != 0) { 894 cmd->stop_arg = 0; 895 err++; 896 } 897 break; 898 default: 899 break; 900 } 901 902 if (err) 903 return 3; 904 905 /* step 4: fix up any arguments */ 906 907 /* if (err) return 4; */ 908 909 return 0; 910} 911 912/* 913 * 'do_cmd' function for an 'INTERRUPT' subdevice. 914 */ 915static int dio200_subdev_intr_cmd(struct comedi_device *dev, 916 struct comedi_subdevice *s) 917{ 918 struct comedi_cmd *cmd = &s->async->cmd; 919 struct dio200_subdev_intr *subpriv = s->private; 920 unsigned long flags; 921 int event = 0; 922 923 spin_lock_irqsave(&subpriv->spinlock, flags); 924 subpriv->active = 1; 925 926 /* Set up end of acquisition. */ 927 switch (cmd->stop_src) { 928 case TRIG_COUNT: 929 subpriv->continuous = 0; 930 subpriv->stopcount = cmd->stop_arg; 931 break; 932 default: 933 /* TRIG_NONE */ 934 subpriv->continuous = 1; 935 subpriv->stopcount = 0; 936 break; 937 } 938 939 /* Set up start of acquisition. */ 940 switch (cmd->start_src) { 941 case TRIG_INT: 942 s->async->inttrig = dio200_inttrig_start_intr; 943 break; 944 default: 945 /* TRIG_NOW */ 946 event = dio200_start_intr(dev, s); 947 break; 948 } 949 spin_unlock_irqrestore(&subpriv->spinlock, flags); 950 951 if (event) 952 comedi_event(dev, s); 953 954 return 0; 955} 956 957/* 958 * This function initializes an 'INTERRUPT' subdevice. 959 */ 960static int 961dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s, 962 unsigned long iobase, unsigned valid_isns, 963 int has_int_sce) 964{ 965 struct dio200_subdev_intr *subpriv; 966 967 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); 968 if (!subpriv) { 969 printk(KERN_ERR "comedi%d: error! out of memory!\n", 970 dev->minor); 971 return -ENOMEM; 972 } 973 subpriv->iobase = iobase; 974 subpriv->has_int_sce = has_int_sce; 975 subpriv->valid_isns = valid_isns; 976 spin_lock_init(&subpriv->spinlock); 977 978 if (has_int_sce) 979 outb(0, subpriv->iobase); /* Disable interrupt sources. */ 980 981 s->private = subpriv; 982 s->type = COMEDI_SUBD_DI; 983 s->subdev_flags = SDF_READABLE | SDF_CMD_READ; 984 if (has_int_sce) { 985 s->n_chan = DIO200_MAX_ISNS; 986 s->len_chanlist = DIO200_MAX_ISNS; 987 } else { 988 /* No interrupt source register. Support single channel. */ 989 s->n_chan = 1; 990 s->len_chanlist = 1; 991 } 992 s->range_table = &range_digital; 993 s->maxdata = 1; 994 s->insn_bits = dio200_subdev_intr_insn_bits; 995 s->do_cmdtest = dio200_subdev_intr_cmdtest; 996 s->do_cmd = dio200_subdev_intr_cmd; 997 s->cancel = dio200_subdev_intr_cancel; 998 999 return 0; 1000} 1001 1002/* 1003 * This function cleans up an 'INTERRUPT' subdevice. 1004 */ 1005static void 1006dio200_subdev_intr_cleanup(struct comedi_device *dev, 1007 struct comedi_subdevice *s) 1008{ 1009 struct dio200_subdev_intr *subpriv = s->private; 1010 kfree(subpriv); 1011} 1012 1013/* 1014 * Interrupt service routine. 1015 */ 1016static irqreturn_t dio200_interrupt(int irq, void *d) 1017{ 1018 struct comedi_device *dev = d; 1019 int handled; 1020 1021 if (!dev->attached) 1022 return IRQ_NONE; 1023 1024 if (devpriv->intr_sd >= 0) { 1025 handled = dio200_handle_read_intr(dev, 1026 dev->subdevices + 1027 devpriv->intr_sd); 1028 } else { 1029 handled = 0; 1030 } 1031 1032 return IRQ_RETVAL(handled); 1033} 1034 1035/* 1036 * Handle 'insn_read' for an '8254' counter subdevice. 1037 */ 1038static int 1039dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s, 1040 struct comedi_insn *insn, unsigned int *data) 1041{ 1042 struct dio200_subdev_8254 *subpriv = s->private; 1043 int chan = CR_CHAN(insn->chanspec); 1044 1045 data[0] = i8254_read(subpriv->iobase, 0, chan); 1046 1047 return 1; 1048} 1049 1050/* 1051 * Handle 'insn_write' for an '8254' counter subdevice. 1052 */ 1053static int 1054dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s, 1055 struct comedi_insn *insn, unsigned int *data) 1056{ 1057 struct dio200_subdev_8254 *subpriv = s->private; 1058 int chan = CR_CHAN(insn->chanspec); 1059 1060 i8254_write(subpriv->iobase, 0, chan, data[0]); 1061 1062 return 1; 1063} 1064 1065/* 1066 * Set gate source for an '8254' counter subdevice channel. 1067 */ 1068static int 1069dio200_set_gate_src(struct dio200_subdev_8254 *subpriv, 1070 unsigned int counter_number, unsigned int gate_src) 1071{ 1072 unsigned char byte; 1073 1074 if (!subpriv->has_clk_gat_sce) 1075 return -1; 1076 if (counter_number > 2) 1077 return -1; 1078 if (gate_src > 7) 1079 return -1; 1080 1081 subpriv->gate_src[counter_number] = gate_src; 1082 byte = GAT_SCE(subpriv->which, counter_number, gate_src); 1083 outb(byte, subpriv->gat_sce_iobase); 1084 1085 return 0; 1086} 1087 1088/* 1089 * Get gate source for an '8254' counter subdevice channel. 1090 */ 1091static int 1092dio200_get_gate_src(struct dio200_subdev_8254 *subpriv, 1093 unsigned int counter_number) 1094{ 1095 if (!subpriv->has_clk_gat_sce) 1096 return -1; 1097 if (counter_number > 2) 1098 return -1; 1099 1100 return subpriv->gate_src[counter_number]; 1101} 1102 1103/* 1104 * Set clock source for an '8254' counter subdevice channel. 1105 */ 1106static int 1107dio200_set_clock_src(struct dio200_subdev_8254 *subpriv, 1108 unsigned int counter_number, unsigned int clock_src) 1109{ 1110 unsigned char byte; 1111 1112 if (!subpriv->has_clk_gat_sce) 1113 return -1; 1114 if (counter_number > 2) 1115 return -1; 1116 if (clock_src > 7) 1117 return -1; 1118 1119 subpriv->clock_src[counter_number] = clock_src; 1120 byte = CLK_SCE(subpriv->which, counter_number, clock_src); 1121 outb(byte, subpriv->clk_sce_iobase); 1122 1123 return 0; 1124} 1125 1126/* 1127 * Get clock source for an '8254' counter subdevice channel. 1128 */ 1129static int 1130dio200_get_clock_src(struct dio200_subdev_8254 *subpriv, 1131 unsigned int counter_number, unsigned int *period_ns) 1132{ 1133 unsigned clock_src; 1134 1135 if (!subpriv->has_clk_gat_sce) 1136 return -1; 1137 if (counter_number > 2) 1138 return -1; 1139 1140 clock_src = subpriv->clock_src[counter_number]; 1141 *period_ns = clock_period[clock_src]; 1142 return clock_src; 1143} 1144 1145/* 1146 * Handle 'insn_config' for an '8254' counter subdevice. 1147 */ 1148static int 1149dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s, 1150 struct comedi_insn *insn, unsigned int *data) 1151{ 1152 struct dio200_subdev_8254 *subpriv = s->private; 1153 int ret; 1154 int chan = CR_CHAN(insn->chanspec); 1155 1156 switch (data[0]) { 1157 case INSN_CONFIG_SET_COUNTER_MODE: 1158 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]); 1159 if (ret < 0) 1160 return -EINVAL; 1161 break; 1162 case INSN_CONFIG_8254_READ_STATUS: 1163 data[1] = i8254_status(subpriv->iobase, 0, chan); 1164 break; 1165 case INSN_CONFIG_SET_GATE_SRC: 1166 ret = dio200_set_gate_src(subpriv, chan, data[2]); 1167 if (ret < 0) 1168 return -EINVAL; 1169 break; 1170 case INSN_CONFIG_GET_GATE_SRC: 1171 ret = dio200_get_gate_src(subpriv, chan); 1172 if (ret < 0) 1173 return -EINVAL; 1174 data[2] = ret; 1175 break; 1176 case INSN_CONFIG_SET_CLOCK_SRC: 1177 ret = dio200_set_clock_src(subpriv, chan, data[1]); 1178 if (ret < 0) 1179 return -EINVAL; 1180 break; 1181 case INSN_CONFIG_GET_CLOCK_SRC: 1182 ret = dio200_get_clock_src(subpriv, chan, &data[2]); 1183 if (ret < 0) 1184 return -EINVAL; 1185 data[1] = ret; 1186 break; 1187 default: 1188 return -EINVAL; 1189 break; 1190 } 1191 return insn->n; 1192} 1193 1194/* 1195 * This function initializes an '8254' counter subdevice. 1196 * 1197 * Note: iobase is the base address of the board, not the subdevice; 1198 * offset is the offset to the 8254 chip. 1199 */ 1200static int 1201dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s, 1202 unsigned long iobase, unsigned offset, 1203 int has_clk_gat_sce) 1204{ 1205 struct dio200_subdev_8254 *subpriv; 1206 unsigned int chan; 1207 1208 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL); 1209 if (!subpriv) { 1210 printk(KERN_ERR "comedi%d: error! out of memory!\n", 1211 dev->minor); 1212 return -ENOMEM; 1213 } 1214 1215 s->private = subpriv; 1216 s->type = COMEDI_SUBD_COUNTER; 1217 s->subdev_flags = SDF_WRITABLE | SDF_READABLE; 1218 s->n_chan = 3; 1219 s->maxdata = 0xFFFF; 1220 s->insn_read = dio200_subdev_8254_read; 1221 s->insn_write = dio200_subdev_8254_write; 1222 s->insn_config = dio200_subdev_8254_config; 1223 1224 subpriv->iobase = offset + iobase; 1225 subpriv->has_clk_gat_sce = has_clk_gat_sce; 1226 if (has_clk_gat_sce) { 1227 /* Derive CLK_SCE and GAT_SCE register offsets from 1228 * 8254 offset. */ 1229 subpriv->clk_sce_iobase = 1230 DIO200_XCLK_SCE + (offset >> 3) + iobase; 1231 subpriv->gat_sce_iobase = 1232 DIO200_XGAT_SCE + (offset >> 3) + iobase; 1233 subpriv->which = (offset >> 2) & 1; 1234 } 1235 1236 /* Initialize channels. */ 1237 for (chan = 0; chan < 3; chan++) { 1238 i8254_set_mode(subpriv->iobase, 0, chan, 1239 I8254_MODE0 | I8254_BINARY); 1240 if (subpriv->has_clk_gat_sce) { 1241 /* Gate source 0 is VCC (logic 1). */ 1242 dio200_set_gate_src(subpriv, chan, 0); 1243 /* Clock source 0 is the dedicated clock input. */ 1244 dio200_set_clock_src(subpriv, chan, 0); 1245 } 1246 } 1247 1248 return 0; 1249} 1250 1251/* 1252 * This function cleans up an '8254' counter subdevice. 1253 */ 1254static void 1255dio200_subdev_8254_cleanup(struct comedi_device *dev, 1256 struct comedi_subdevice *s) 1257{ 1258 struct dio200_subdev_intr *subpriv = s->private; 1259 kfree(subpriv); 1260} 1261 1262/* 1263 * Attach is called by the Comedi core to configure the driver 1264 * for a particular board. If you specified a board_name array 1265 * in the driver structure, dev->board_ptr contains that 1266 * address. 1267 */ 1268static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it) 1269{ 1270 struct comedi_subdevice *s; 1271 unsigned long iobase = 0; 1272 unsigned int irq = 0; 1273#ifdef CONFIG_COMEDI_PCI 1274 struct pci_dev *pci_dev = NULL; 1275 int bus = 0, slot = 0; 1276#endif 1277 const struct dio200_layout_struct *layout; 1278 int share_irq = 0; 1279 int sdx; 1280 unsigned n; 1281 int ret; 1282 1283 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor, 1284 DIO200_DRIVER_NAME); 1285 1286 ret = alloc_private(dev, sizeof(struct dio200_private)); 1287 if (ret < 0) { 1288 printk(KERN_ERR "comedi%d: error! out of memory!\n", 1289 dev->minor); 1290 return ret; 1291 } 1292 1293 /* Process options. */ 1294 switch (thisboard->bustype) { 1295 case isa_bustype: 1296 iobase = it->options[0]; 1297 irq = it->options[1]; 1298 share_irq = 0; 1299 break; 1300#ifdef CONFIG_COMEDI_PCI 1301 case pci_bustype: 1302 bus = it->options[0]; 1303 slot = it->options[1]; 1304 share_irq = 1; 1305 1306 ret = dio200_find_pci(dev, bus, slot, &pci_dev); 1307 if (ret < 0) 1308 return ret; 1309 devpriv->pci_dev = pci_dev; 1310 break; 1311#endif 1312 default: 1313 printk(KERN_ERR 1314 "comedi%d: %s: BUG! cannot determine board type!\n", 1315 dev->minor, DIO200_DRIVER_NAME); 1316 return -EINVAL; 1317 break; 1318 } 1319 1320 devpriv->intr_sd = -1; 1321 1322 /* Enable device and reserve I/O spaces. */ 1323#ifdef CONFIG_COMEDI_PCI 1324 if (pci_dev) { 1325 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME); 1326 if (ret < 0) { 1327 printk(KERN_ERR 1328 "comedi%d: error! cannot enable PCI device and request regions!\n", 1329 dev->minor); 1330 return ret; 1331 } 1332 iobase = pci_resource_start(pci_dev, 2); 1333 irq = pci_dev->irq; 1334 } else 1335#endif 1336 { 1337 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE); 1338 if (ret < 0) 1339 return ret; 1340 } 1341 dev->iobase = iobase; 1342 1343 layout = thislayout; 1344 1345 ret = alloc_subdevices(dev, layout->n_subdevs); 1346 if (ret < 0) { 1347 printk(KERN_ERR "comedi%d: error! out of memory!\n", 1348 dev->minor); 1349 return ret; 1350 } 1351 1352 for (n = 0; n < dev->n_subdevices; n++) { 1353 s = &dev->subdevices[n]; 1354 switch (layout->sdtype[n]) { 1355 case sd_8254: 1356 /* counter subdevice (8254) */ 1357 ret = dio200_subdev_8254_init(dev, s, iobase, 1358 layout->sdinfo[n], 1359 layout->has_clk_gat_sce); 1360 if (ret < 0) 1361 return ret; 1362 1363 break; 1364 case sd_8255: 1365 /* digital i/o subdevice (8255) */ 1366 ret = subdev_8255_init(dev, s, 0, 1367 iobase + layout->sdinfo[n]); 1368 if (ret < 0) 1369 return ret; 1370 1371 break; 1372 case sd_intr: 1373 /* 'INTERRUPT' subdevice */ 1374 if (irq) { 1375 ret = dio200_subdev_intr_init(dev, s, 1376 iobase + 1377 DIO200_INT_SCE, 1378 layout->sdinfo[n], 1379 layout-> 1380 has_int_sce); 1381 if (ret < 0) 1382 return ret; 1383 1384 devpriv->intr_sd = n; 1385 } else { 1386 s->type = COMEDI_SUBD_UNUSED; 1387 } 1388 break; 1389 default: 1390 s->type = COMEDI_SUBD_UNUSED; 1391 break; 1392 } 1393 } 1394 1395 sdx = devpriv->intr_sd; 1396 if (sdx >= 0 && sdx < dev->n_subdevices) 1397 dev->read_subdev = &dev->subdevices[sdx]; 1398 1399 dev->board_name = thisboard->name; 1400 1401 if (irq) { 1402 unsigned long flags = share_irq ? IRQF_SHARED : 0; 1403 1404 if (request_irq(irq, dio200_interrupt, flags, 1405 DIO200_DRIVER_NAME, dev) >= 0) { 1406 dev->irq = irq; 1407 } else { 1408 printk(KERN_WARNING 1409 "comedi%d: warning! irq %u unavailable!\n", 1410 dev->minor, irq); 1411 } 1412 } 1413 1414 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name); 1415 if (thisboard->bustype == isa_bustype) { 1416 printk("(base %#lx) ", iobase); 1417 } else { 1418#ifdef CONFIG_COMEDI_PCI 1419 printk("(pci %s) ", pci_name(pci_dev)); 1420#endif 1421 } 1422 if (irq) 1423 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE")); 1424 else 1425 printk("(no irq) "); 1426 1427 printk("attached\n"); 1428 1429 return 1; 1430} 1431 1432/* 1433 * _detach is called to deconfigure a device. It should deallocate 1434 * resources. 1435 * This function is also called when _attach() fails, so it should be 1436 * careful not to release resources that were not necessarily 1437 * allocated by _attach(). dev->private and dev->subdevices are 1438 * deallocated automatically by the core. 1439 */ 1440static int dio200_detach(struct comedi_device *dev) 1441{ 1442 const struct dio200_layout_struct *layout; 1443 unsigned n; 1444 1445 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor, 1446 DIO200_DRIVER_NAME); 1447 1448 if (dev->irq) 1449 free_irq(dev->irq, dev); 1450 if (dev->subdevices) { 1451 layout = thislayout; 1452 for (n = 0; n < dev->n_subdevices; n++) { 1453 struct comedi_subdevice *s = &dev->subdevices[n]; 1454 switch (layout->sdtype[n]) { 1455 case sd_8254: 1456 dio200_subdev_8254_cleanup(dev, s); 1457 break; 1458 case sd_8255: 1459 subdev_8255_cleanup(dev, s); 1460 break; 1461 case sd_intr: 1462 dio200_subdev_intr_cleanup(dev, s); 1463 break; 1464 default: 1465 break; 1466 } 1467 } 1468 } 1469 if (devpriv) { 1470#ifdef CONFIG_COMEDI_PCI 1471 if (devpriv->pci_dev) { 1472 if (dev->iobase) 1473 comedi_pci_disable(devpriv->pci_dev); 1474 pci_dev_put(devpriv->pci_dev); 1475 } else 1476#endif 1477 { 1478 if (dev->iobase) 1479 release_region(dev->iobase, DIO200_IO_SIZE); 1480 } 1481 } 1482 if (dev->board_name) 1483 printk(KERN_INFO "comedi%d: %s removed\n", 1484 dev->minor, dev->board_name); 1485 1486 return 0; 1487} 1488