2 comedi/drivers/amplc_dio200.c
3 Driver for various Amplicon 200 series DIO boards.
4 (Support for other boards in Amplicon 200 series may be added at
5 a later date, e.g. PCI215.)
7 Copyright (C) 2005-2012 MEV Ltd. <http://www.mev.co.uk/>
9 COMEDI - Linux Control and Measurement Device Interface
10 Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
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.
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.
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.
29 Description: Amplicon 200 Series Digital I/O
30 Author: Ian Abbott <abbotti@mev.co.uk>
31 Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
32 PCI215 (pci215 or amplc_dio200), PCIe215 (pcie215 or amplc_dio200),
33 PC218E (pc218e), PCIe236 (pcie236 or amplc_dio200), PC272E (pc272e),
34 PCI272 (pci272 or amplc_dio200), PCIe296 (pcie296 or amplc_dio200)
35 Updated: Wed, 16 May 2012 13:57:58 +0100
38 Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
39 [0] - I/O port base address
40 [1] - IRQ (optional, but commands won't work without it)
42 Configuration options - PCI215, PCIe215, PCIe236, PCI272, PCIe296:
43 [0] - PCI bus of device (optional)
44 [1] - PCI slot of device (optional)
45 If bus/slot is not specified, the first available PCI device will
48 Passing a zero for an option is the same as leaving it unspecified.
52 PC212E PC214E PC215E/PCI215
53 ------------- ------------- -------------
57 2 CTR-Y2 CTR-Z1* CTR-Z1
58 3 CTR-Z1 INTERRUPT* CTR-Z2
62 PCIe215 PC218E PCIe236
63 ------------- ------------- -------------
66 1 UNUSED CTR-X2 UNUSED
68 3 UNUSED CTR-Y2 UNUSED
69 4 CTR-Z1 CTR-Z1 CTR-Z1
70 5 CTR-Z2 CTR-Z2 CTR-Z2
71 6 TIMER INTERRUPT TIMER
75 ------------- -------------
86 Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels
87 are configurable as inputs or outputs in four groups:
89 Port A - channels 0 to 7
90 Port B - channels 8 to 15
91 Port CL - channels 16 to 19
92 Port CH - channels 20 to 23
94 Only mode 0 of the 8255 chips is supported.
96 Each CTR is a 8254 chip providing 3 16-bit counter channels. Each
97 channel is configured individually with INSN_CONFIG instructions. The
98 specific type of configuration instruction is specified in data[0].
99 Some configuration instructions expect an additional parameter in
100 data[1]; others return a value in data[1]. The following configuration
101 instructions are supported:
103 INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and
104 BCD/binary setting specified in data[1].
106 INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the
107 counter channel into data[1].
109 INSN_CONFIG_SET_CLOCK_SRC. Sets the counter channel's clock source as
110 specified in data[1] (this is a hardware-specific value). Not
111 supported on PC214E. For the other boards, valid clock sources are
114 0. CLK n, the counter channel's dedicated CLK input from the SK1
115 connector. (N.B. for other values, the counter channel's CLKn
116 pin on the SK1 connector is an output!)
117 1. Internal 10 MHz clock.
118 2. Internal 1 MHz clock.
119 3. Internal 100 kHz clock.
120 4. Internal 10 kHz clock.
121 5. Internal 1 kHz clock.
122 6. OUT n-1, the output of counter channel n-1 (see note 1 below).
123 7. Ext Clock, the counter chip's dedicated Ext Clock input from
124 the SK1 connector. This pin is shared by all three counter
125 channels on the chip.
127 INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current
128 clock source in data[1]. For internal clock sources, data[2] is set
131 INSN_CONFIG_SET_GATE_SRC. Sets the counter channel's gate source as
132 specified in data[2] (this is a hardware-specific value). Not
133 supported on PC214E. For the other boards, valid gate sources are 0
136 0. VCC (internal +5V d.c.), i.e. gate permanently enabled.
137 1. GND (internal 0V d.c.), i.e. gate permanently disabled.
138 2. GAT n, the counter channel's dedicated GAT input from the SK1
139 connector. (N.B. for other values, the counter channel's GATn
140 pin on the SK1 connector is an output!)
141 3. /OUT n-2, the inverted output of counter channel n-2 (see note
148 INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate
151 Clock and gate interconnection notes:
153 1. Clock source OUT n-1 is the output of the preceding channel on the
154 same counter subdevice if n > 0, or the output of channel 2 on the
155 preceding counter subdevice (see note 3) if n = 0.
157 2. Gate source /OUT n-2 is the inverted output of channel 0 on the
158 same counter subdevice if n = 2, or the inverted output of channel n+1
159 on the preceding counter subdevice (see note 3) if n < 2.
161 3. The counter subdevices are connected in a ring, so the highest
162 counter subdevice precedes the lowest.
164 The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
166 The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The
167 digital inputs come from the interrupt status register. The number of
168 channels matches the number of interrupt sources. The PC214E does not
169 have an interrupt status register; see notes on 'INTERRUPT SOURCES'
174 PC212E PC214E PC215E/PCI215
175 ------------- ------------- -------------
177 0 PPI-X-C0 JUMPER-J5 PPI-X-C0
179 2 CTR-Y1-OUT PPI-Y-C0
180 3 CTR-Y2-OUT PPI-Y-C3
181 4 CTR-Z1-OUT CTR-Z1-OUT
182 5 CTR-Z2-OUT CTR-Z2-OUT
184 PCIe215 PC218E PCIe236
185 ------------- ------------- -------------
187 0 PPI-X-C0 CTR-X1-OUT PPI-X-C0
188 1 PPI-X-C3 CTR-X2-OUT PPI-X-C3
189 2 PPI-Y-C0 CTR-Y1-OUT unused
190 3 PPI-Y-C3 CTR-Y2-OUT unused
191 4 CTR-Z1-OUT CTR-Z1-OUT CTR-Z1-OUT
192 5 CTR-Z2-OUT CTR-Z2-OUT CTR-Z2-OUT
194 PC272E/PCI272 PCIe296
195 ------------- -------------
201 4 PPI-Z-C0 CTR-Z1-OUT
202 5 PPI-Z-C3 CTR-Z2-OUT
204 When an interrupt source is enabled in the interrupt source enable
205 register, a rising edge on the source signal latches the corresponding
206 bit to 1 in the interrupt status register.
208 When the interrupt status register value as a whole (actually, just the
209 6 least significant bits) goes from zero to non-zero, the board will
210 generate an interrupt. For level-triggered hardware interrupts (PCI
211 card), the interrupt will remain asserted until the interrupt status
212 register is cleared to zero. For edge-triggered hardware interrupts
213 (ISA card), no further interrupts will occur until the interrupt status
214 register is cleared to zero. To clear a bit to zero in the interrupt
215 status register, the corresponding interrupt source must be disabled
216 in the interrupt source enable register (there is no separate interrupt
219 The PC214E does not have an interrupt source enable register or an
220 interrupt status register; its 'INTERRUPT' subdevice has a single
221 channel and its interrupt source is selected by the position of jumper
226 The driver supports a read streaming acquisition command on the
227 'INTERRUPT' subdevice. The channel list selects the interrupt sources
228 to be enabled. All channels will be sampled together (convert_src ==
229 TRIG_NOW). The scan begins a short time after the hardware interrupt
230 occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
231 scan_begin_arg == 0). The value read from the interrupt status register
232 is packed into a sampl_t value, one bit per requested channel, in the
233 order they appear in the channel list.
236 #include <linux/comedidev.h>
238 #include "comedi_pci.h"
243 #define DIO200_DRIVER_NAME "amplc_dio200"
246 /* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
247 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
248 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
249 #define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
250 #define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
251 #define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
252 #define PCI_DEVICE_ID_INVALID 0xffff
254 /* 8255 control register bits */
255 #define CR_C_LO_IO 0x01
257 #define CR_B_MODE 0x04
258 #define CR_C_HI_IO 0x08
260 #define CR_A_MODE(a) ((a)<<5)
263 /* 200 series registers */
264 #define DIO200_IO_SIZE 0x20
265 #define DIO200_PCIE_IO_SIZE 0x4000
266 #define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
267 #define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
268 #define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
269 #define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
270 #define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
271 #define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
272 #define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
273 /* Extra registers for new PCIe boards */
274 #define DIO200_ENHANCE 0x20 /* 1 to enable enhanced features */
275 #define DIO200_VERSION 0x24 /* Hardware version */
278 * Macros for constructing value for DIO_200_?CLK_SCE and
279 * DIO_200_?GAT_SCE registers:
281 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
282 * 'chan' is the channel: 0, 1 or 2.
283 * 'source' is the signal source: 0 to 7.
285 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
286 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
289 * Periods of the internal clock sources in nanoseconds.
291 static const unsigned clock_period[8] = {
292 0, /* dedicated clock input/output pin */
299 0 /* group clock input pin */
305 enum dio200_regtype { no_regtype, io_regtype, mmio_regtype };
306 struct dio200_region {
308 unsigned long iobase; /* I/O base address */
309 unsigned char __iomem *membase; /* Mapped MMIO base address */
311 unsigned char regtype;
312 unsigned char regshift;
316 * Board descriptions.
319 enum dio200_bustype { isa_bustype, pci_bustype };
324 pc215e_model, pci215_model, pcie215_model,
327 pc272e_model, pci272_model,
338 #ifdef CONFIG_COMEDI_PCI
346 typedef struct dio200_board_struct {
348 unsigned short devid;
349 enum dio200_bustype bustype;
350 enum dio200_model model;
351 enum dio200_layout layout;
352 unsigned char mainbar;
353 unsigned char mainshift;
354 unsigned int mainsize;
357 static const dio200_board dio200_boards[] = {
360 bustype: isa_bustype,
362 layout: pc212_layout,
363 mainsize: DIO200_IO_SIZE,
367 bustype: isa_bustype,
369 layout: pc214_layout,
370 mainsize: DIO200_IO_SIZE,
374 bustype: isa_bustype,
376 layout: pc215_layout,
377 mainsize: DIO200_IO_SIZE,
379 #ifdef CONFIG_COMEDI_PCI
382 devid: PCI_DEVICE_ID_AMPLICON_PCI215,
383 bustype: pci_bustype,
385 layout: pc215_layout,
386 mainsize: DIO200_IO_SIZE,
390 #ifdef CONFIG_COMEDI_PCI
393 devid: PCI_DEVICE_ID_AMPLICON_PCIE215,
394 bustype: pci_bustype,
395 model: pcie215_model,
396 layout: pcie215_layout,
397 mainsize: DIO200_PCIE_IO_SIZE,
404 bustype: isa_bustype,
406 layout: pc218_layout,
407 mainsize: DIO200_IO_SIZE,
409 #ifdef CONFIG_COMEDI_PCI
412 devid: PCI_DEVICE_ID_AMPLICON_PCIE236,
413 bustype: pci_bustype,
414 model: pcie236_model,
415 layout: pcie236_layout,
416 mainsize: DIO200_PCIE_IO_SIZE,
423 bustype: isa_bustype,
425 layout: pc272_layout,
426 mainsize: DIO200_IO_SIZE,
428 #ifdef CONFIG_COMEDI_PCI
431 devid: PCI_DEVICE_ID_AMPLICON_PCI272,
432 bustype: pci_bustype,
434 layout: pc272_layout,
435 mainsize: DIO200_IO_SIZE,
439 #ifdef CONFIG_COMEDI_PCI
442 devid: PCI_DEVICE_ID_AMPLICON_PCIE296,
443 bustype: pci_bustype,
444 model: pcie296_model,
445 layout: pcie296_layout,
446 mainsize: DIO200_PCIE_IO_SIZE,
451 #ifdef CONFIG_COMEDI_PCI
453 name: DIO200_DRIVER_NAME,
454 devid: PCI_DEVICE_ID_INVALID,
455 bustype: pci_bustype,
456 model: anypci_model, /* wildcard */
462 * Layout descriptions - some ISA and PCI board descriptions share the same
466 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
468 #define DIO200_MAX_SUBDEVS 8
469 #define DIO200_MAX_ISNS 6
471 typedef struct dio200_layout_struct {
472 unsigned short n_subdevs; /* number of subdevices */
473 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */
474 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */
475 char has_int_sce; /* has interrupt enable/status register */
476 char has_clk_gat_sce; /* has clock/gate selection registers */
477 char has_enhancements; /* has enhanced features */
480 static const dio200_layout dio200_layouts[] = {
483 sdtype: {sd_8255, sd_8254, sd_8254, sd_8254,
486 sdinfo: {0x00, 0x08, 0x0C, 0x10, 0x14,
494 sdtype: {sd_8255, sd_8255, sd_8254,
496 sdinfo: {0x00, 0x08, 0x10, 0x01},
503 sdtype: {sd_8255, sd_8255, sd_8254,
506 sdinfo: {0x00, 0x08, 0x10, 0x14, 0x3F},
513 sdtype: {sd_8254, sd_8254, sd_8255, sd_8254,
516 sdinfo: {0x00, 0x04, 0x08, 0x0C, 0x10,
525 sdtype: {sd_8255, sd_8255, sd_8255,
527 sdinfo: {0x00, 0x08, 0x10, 0x3F},
532 #ifdef CONFIG_COMEDI_PCI
535 sdtype: {sd_8255, sd_none, sd_8255, sd_none, sd_8254, sd_8254,
537 sdinfo: {0x00, 0x00, 0x08, 0x00, 0x10, 0x14, 0x00, 0x3F},
544 sdtype: {sd_8255, sd_none, sd_none, sd_none, sd_8254, sd_8254,
546 sdinfo: {0x00, 0x00, 0x00, 0x00, 0x10, 0x14, 0x00, 0x3F},
553 sdtype: {sd_8255, sd_8255, sd_8255, sd_8255, sd_8254, sd_8254,
555 sdinfo: {0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x00, 0x3F},
567 #ifdef CONFIG_COMEDI_PCI
568 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
569 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
570 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
571 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
572 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
573 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236,
574 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
575 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215,
576 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
577 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296,
578 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
582 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
583 #endif /* CONFIG_COMEDI_PCI */
586 * Useful for shorthand access to the particular board structure
588 #define thisboard ((const dio200_board *)dev->board_ptr)
589 #define thislayout (&dio200_layouts[((dio200_board *)dev->board_ptr)->layout])
591 /* this structure is for data unique to this hardware driver. If
592 several hardware drivers keep similar information in this structure,
593 feel free to suggest moving the variable to the comedi_device struct. */
595 #ifdef CONFIG_COMEDI_PCI
596 struct pci_dev *pci_dev; /* PCI device */
598 struct dio200_region io; /* Register region */
602 #define devpriv ((dio200_private *)dev->private)
605 unsigned int ofs; /* Counter base offset */
606 unsigned int clk_sce_ofs; /* CLK_SCE base offset */
607 unsigned int gat_sce_ofs; /* GAT_SCE base offset */
608 int which; /* Bit 5 of CLK_SCE or GAT_SCE */
609 unsigned int clock_src[3]; /* Current clock sources */
610 unsigned int gate_src[3]; /* Current gate sources */
612 } dio200_subdev_8254;
615 unsigned int ofs; /* DIO base offset */
616 } dio200_subdev_8255;
622 unsigned int valid_isns;
623 unsigned int enabled_isns;
624 unsigned int stopcount;
626 } dio200_subdev_intr;
629 * The comedi_driver structure tells the Comedi core module
630 * which functions to call to configure/deconfigure (attach/detach)
631 * the board, and also about the kernel module that contains
634 static int dio200_attach(comedi_device * dev, comedi_devconfig * it);
635 static int dio200_detach(comedi_device * dev);
636 static comedi_driver driver_amplc_dio200 = {
637 driver_name:DIO200_DRIVER_NAME,
639 attach:dio200_attach,
640 detach:dio200_detach,
641 board_name:&dio200_boards[0].name,
642 offset:sizeof(dio200_board),
643 num_names:sizeof(dio200_boards) / sizeof(dio200_board),
646 #ifdef CONFIG_COMEDI_PCI
647 COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
649 COMEDI_INITCLEANUP(driver_amplc_dio200);
653 * Read 8-bit register.
655 static unsigned char dio200_read8(comedi_device * dev, unsigned int offset)
657 offset <<= devpriv->io.regshift;
658 if (devpriv->io.regtype == io_regtype)
659 return inb(devpriv->io.u.iobase + offset);
661 return readb(devpriv->io.u.membase + offset);
665 * Write 8-bit register.
667 static void dio200_write8(comedi_device * dev, unsigned int offset,
670 offset <<= devpriv->io.regshift;
671 if (devpriv->io.regtype == io_regtype)
672 outb(val, devpriv->io.u.iobase + offset);
674 writeb(val, devpriv->io.u.membase + offset);
678 * This function looks for a PCI device matching the requested board name,
681 #ifdef CONFIG_COMEDI_PCI
683 dio200_find_pci(comedi_device * dev, int bus, int slot,
684 struct pci_dev **pci_dev_p)
686 struct pci_dev *pci_dev = NULL;
690 /* Look for matching PCI device. */
691 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
693 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
694 PCI_ANY_ID, pci_dev)) {
695 /* If bus/slot specified, check them. */
697 if (bus != pci_dev->bus->number
698 || slot != PCI_SLOT(pci_dev->devfn))
701 if (thisboard->model == anypci_model) {
702 /* Match any supported model. */
705 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
706 if (dio200_boards[i].bustype != pci_bustype)
708 if (pci_dev->device == dio200_boards[i].devid) {
709 /* Change board_ptr to matched board. */
710 dev->board_ptr = &dio200_boards[i];
714 if (i == ARRAY_SIZE(dio200_boards))
717 /* Match specific model name. */
718 if (pci_dev->device != thisboard->devid)
723 *pci_dev_p = pci_dev;
726 /* No match found. */
729 "comedi%d: error! no %s found at pci %02x:%02x!\n",
730 dev->minor, thisboard->name, bus, slot);
732 printk(KERN_ERR "comedi%d: error! no %s found!\n",
733 dev->minor, thisboard->name);
740 * This function checks and requests an I/O region, reporting an error
741 * if there is a conflict.
744 dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
746 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
747 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
748 minor, from, extent);
755 * 'insn_bits' function for an 'INTERRUPT' subdevice.
758 dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
759 comedi_insn * insn, lsampl_t * data)
761 dio200_subdev_intr *subpriv = s->private;
763 if (thislayout->has_int_sce) {
764 /* Just read the interrupt status register. */
765 data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
767 /* No interrupt status register. */
775 * Called to stop acquisition for an 'INTERRUPT' subdevice.
777 static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
779 dio200_subdev_intr *subpriv = s->private;
782 subpriv->enabled_isns = 0;
783 if (thislayout->has_int_sce) {
784 dio200_write8(dev, subpriv->ofs, 0);
789 * Called to start acquisition for an 'INTERRUPT' subdevice.
791 static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
795 dio200_subdev_intr *subpriv = s->private;
796 comedi_cmd *cmd = &s->async->cmd;
799 if (!subpriv->continuous && subpriv->stopcount == 0) {
800 /* An empty acquisition! */
801 s->async->events |= COMEDI_CB_EOA;
805 /* Determine interrupt sources to enable. */
808 for (n = 0; n < cmd->chanlist_len; n++) {
809 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
812 isn_bits &= subpriv->valid_isns;
813 /* Enable interrupt sources. */
814 subpriv->enabled_isns = isn_bits;
815 if (thislayout->has_int_sce) {
816 dio200_write8(dev, subpriv->ofs, isn_bits);
824 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
827 dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
828 unsigned int trignum)
830 dio200_subdev_intr *subpriv;
837 subpriv = s->private;
839 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
840 s->async->inttrig = 0;
841 if (subpriv->active) {
842 event = dio200_start_intr(dev, s);
844 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
847 comedi_event(dev, s);
854 * This is called from the interrupt service routine to handle a read
855 * scan on an 'INTERRUPT' subdevice.
857 static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
859 dio200_subdev_intr *subpriv = s->private;
862 unsigned cur_enabled;
863 unsigned int oldevents;
865 unsigned int int_sce_ofs;
867 int_sce_ofs = subpriv->ofs;
870 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
871 oldevents = s->async->events;
872 if (thislayout->has_int_sce) {
874 * Collect interrupt sources that have triggered and disable
875 * them temporarily. Loop around until no extra interrupt
876 * sources have triggered, at which point, the valid part of
877 * the interrupt status register will read zero, clearing the
878 * cause of the interrupt.
880 * Mask off interrupt sources already seen to avoid infinite
881 * loop in case of misconfiguration.
883 cur_enabled = subpriv->enabled_isns;
884 while ((intstat = (dio200_read8(dev, int_sce_ofs)
885 & subpriv->valid_isns & ~triggered))
887 triggered |= intstat;
888 cur_enabled &= ~triggered;
889 dio200_write8(dev, int_sce_ofs, cur_enabled);
893 * No interrupt status register. Assume the single interrupt
894 * source has triggered.
896 triggered = subpriv->enabled_isns;
901 * Some interrupt sources have triggered and have been
902 * temporarily disabled to clear the cause of the interrupt.
904 * Reenable them NOW to minimize the time they are disabled.
906 cur_enabled = subpriv->enabled_isns;
907 if (thislayout->has_int_sce) {
908 dio200_write8(dev, int_sce_ofs, cur_enabled);
911 if (subpriv->active) {
913 * The command is still active.
915 * Ignore interrupt sources that the command isn't
916 * interested in (just in case there's a race
919 if (triggered & subpriv->enabled_isns) {
920 /* Collect scan data. */
922 unsigned int n, ch, len;
925 len = s->async->cmd.chanlist_len;
926 for (n = 0; n < len; n++) {
927 ch = CR_CHAN(s->async->cmd.chanlist[n]);
928 if (triggered & (1U << ch)) {
932 /* Write the scan to the buffer. */
933 if (comedi_buf_put(s->async, val)) {
934 s->async->events |= (COMEDI_CB_BLOCK |
937 /* Error! Stop acquisition. */
938 dio200_stop_intr(dev, s);
939 s->async->events |= COMEDI_CB_ERROR
940 | COMEDI_CB_OVERFLOW;
941 comedi_error(dev, "buffer overflow");
944 /* Check for end of acquisition. */
945 if (!subpriv->continuous) {
946 /* stop_src == TRIG_COUNT */
947 if (subpriv->stopcount > 0) {
948 subpriv->stopcount--;
949 if (subpriv->stopcount == 0) {
952 dio200_stop_intr(dev,
960 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
962 if (oldevents != s->async->events) {
963 comedi_event(dev, s);
966 return (triggered != 0);
970 * 'cancel' function for an 'INTERRUPT' subdevice.
972 static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
974 dio200_subdev_intr *subpriv = s->private;
977 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
978 if (subpriv->active) {
979 dio200_stop_intr(dev, s);
981 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
987 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
990 dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
996 /* step 1: make sure trigger sources are trivially valid */
998 tmp = cmd->start_src;
999 cmd->start_src &= (TRIG_NOW | TRIG_INT);
1000 if (!cmd->start_src || tmp != cmd->start_src)
1003 tmp = cmd->scan_begin_src;
1004 cmd->scan_begin_src &= TRIG_EXT;
1005 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1008 tmp = cmd->convert_src;
1009 cmd->convert_src &= TRIG_NOW;
1010 if (!cmd->convert_src || tmp != cmd->convert_src)
1013 tmp = cmd->scan_end_src;
1014 cmd->scan_end_src &= TRIG_COUNT;
1015 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1018 tmp = cmd->stop_src;
1019 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
1020 if (!cmd->stop_src || tmp != cmd->stop_src)
1026 /* step 2: make sure trigger sources are unique and mutually compatible */
1028 /* these tests are true if more than one _src bit is set */
1029 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1031 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1033 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1035 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1037 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1043 /* step 3: make sure arguments are trivially compatible */
1045 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
1046 if (cmd->start_arg != 0) {
1051 /* cmd->scan_begin_src == TRIG_EXT */
1052 if (cmd->scan_begin_arg != 0) {
1053 cmd->scan_begin_arg = 0;
1057 /* cmd->convert_src == TRIG_NOW */
1058 if (cmd->convert_arg != 0) {
1059 cmd->convert_arg = 0;
1063 /* cmd->scan_end_src == TRIG_COUNT */
1064 if (cmd->scan_end_arg != cmd->chanlist_len) {
1065 cmd->scan_end_arg = cmd->chanlist_len;
1069 switch (cmd->stop_src) {
1071 /* any count allowed */
1074 if (cmd->stop_arg != 0) {
1086 /* step 4: fix up any arguments */
1088 /* if (err) return 4; */
1094 * 'do_cmd' function for an 'INTERRUPT' subdevice.
1096 static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
1098 comedi_cmd *cmd = &s->async->cmd;
1099 dio200_subdev_intr *subpriv = s->private;
1100 unsigned long flags;
1103 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1104 subpriv->active = 1;
1106 /* Set up end of acquisition. */
1107 switch (cmd->stop_src) {
1109 subpriv->continuous = 0;
1110 subpriv->stopcount = cmd->stop_arg;
1114 subpriv->continuous = 1;
1115 subpriv->stopcount = 0;
1119 /* Set up start of acquisition. */
1120 switch (cmd->start_src) {
1122 s->async->inttrig = dio200_inttrig_start_intr;
1126 event = dio200_start_intr(dev, s);
1129 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1132 comedi_event(dev, s);
1139 * This function initializes an 'INTERRUPT' subdevice.
1142 dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
1143 unsigned int offset, unsigned valid_isns)
1145 dio200_subdev_intr *subpriv;
1147 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1149 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1153 subpriv->ofs = offset;
1154 subpriv->valid_isns = valid_isns;
1155 spin_lock_init(&subpriv->spinlock);
1157 if (thislayout->has_int_sce) {
1158 /* Disable interrupt sources. */
1159 dio200_write8(dev, subpriv->ofs, 0);
1162 s->private = subpriv;
1163 s->type = COMEDI_SUBD_DI;
1164 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1165 if (thislayout->has_int_sce) {
1166 s->n_chan = DIO200_MAX_ISNS;
1167 s->len_chanlist = DIO200_MAX_ISNS;
1169 /* No interrupt source register. Support single channel. */
1171 s->len_chanlist = 1;
1173 s->range_table = &range_digital;
1175 s->insn_bits = dio200_subdev_intr_insn_bits;
1176 s->do_cmdtest = dio200_subdev_intr_cmdtest;
1177 s->do_cmd = dio200_subdev_intr_cmd;
1178 s->cancel = dio200_subdev_intr_cancel;
1184 * This function cleans up an 'INTERRUPT' subdevice.
1187 dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
1189 dio200_subdev_intr *subpriv = s->private;
1197 * Interrupt service routine.
1199 static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
1201 comedi_device *dev = d;
1204 if (!dev->attached) {
1208 if (devpriv->intr_sd >= 0) {
1209 handled = dio200_handle_read_intr(dev,
1210 dev->subdevices + devpriv->intr_sd);
1215 return IRQ_RETVAL(handled);
1219 * Read an '8254' counter subdevice channel.
1221 static inline unsigned int
1222 dio200_subdev_8254_read_chan(comedi_device * dev, comedi_subdevice * s,
1225 unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1230 dio200_write8(dev, i8254_ofs + i8254_control_reg, val);
1233 val = dio200_read8(dev, i8254_ofs + chan);
1235 val += dio200_read8(dev, i8254_ofs + chan) << 8;
1241 * Write an '8254' counter subdevice channel.
1244 dio200_subdev_8254_write_chan(comedi_device * dev, comedi_subdevice * s,
1245 unsigned int chan, unsigned int count)
1247 unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1250 dio200_write8(dev, i8254_ofs + chan, count & 0xff);
1252 dio200_write8(dev, i8254_ofs + chan, (count >> 8) & 0xff);
1256 * Set mode of an '8254' counter subdevice channel.
1259 dio200_subdev_8254_set_mode(comedi_device * dev, comedi_subdevice * s,
1260 unsigned int chan, unsigned int mode)
1262 unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1266 byte |= 0x30; /* load lsb then msb */
1267 byte |= (mode & 0xf); /* set counter mode and BCD|binary */
1268 dio200_write8(dev, i8254_ofs + i8254_control_reg, byte);
1272 * Read status byte of an '8254' counter subdevice channel.
1274 static inline unsigned int
1275 dio200_subdev_8254_status(comedi_device * dev, comedi_subdevice * s,
1278 unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1280 dio200_write8(dev, i8254_ofs + i8254_control_reg, (0xE0 | 2 << chan));
1281 return dio200_read8(dev, i8254_ofs + chan);
1285 * Handle 'insn_read' for an '8254' counter subdevice.
1288 dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
1289 comedi_insn * insn, lsampl_t * data)
1291 dio200_subdev_8254 *subpriv = s->private;
1292 int chan = CR_CHAN(insn->chanspec);
1293 unsigned long flags;
1298 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1299 data[0] = dio200_subdev_8254_read_chan(dev, s, chan);
1300 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1306 * Handle 'insn_write' for an '8254' counter subdevice.
1309 dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
1310 comedi_insn * insn, lsampl_t * data)
1312 dio200_subdev_8254 *subpriv = s->private;
1313 int chan = CR_CHAN(insn->chanspec);
1314 unsigned long flags;
1319 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1320 dio200_subdev_8254_write_chan(dev, s, chan, data[0]);
1321 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1327 * Set gate source for an '8254' counter subdevice channel.
1330 dio200_subdev_8254_set_gate_src(comedi_device * dev, comedi_subdevice *s,
1331 unsigned int counter_number, unsigned int gate_src)
1333 dio200_subdev_8254 *subpriv = s->private;
1336 if (!thislayout->has_clk_gat_sce)
1338 if (counter_number > 2)
1343 subpriv->gate_src[counter_number] = gate_src;
1344 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1345 dio200_write8(dev, subpriv->gat_sce_ofs, byte);
1351 * Get gate source for an '8254' counter subdevice channel.
1354 dio200_subdev_8254_get_gate_src(comedi_device * dev, comedi_subdevice *s,
1355 unsigned int counter_number)
1357 dio200_subdev_8254 *subpriv = s->private;
1359 if (!thislayout->has_clk_gat_sce)
1361 if (counter_number > 2)
1364 return subpriv->gate_src[counter_number];
1368 * Set clock source for an '8254' counter subdevice channel.
1371 dio200_subdev_8254_set_clock_src(comedi_device * dev, comedi_subdevice *s,
1372 unsigned int counter_number, unsigned int clock_src)
1374 dio200_subdev_8254 *subpriv = s->private;
1377 if (!thislayout->has_clk_gat_sce)
1379 if (counter_number > 2)
1384 subpriv->clock_src[counter_number] = clock_src;
1385 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1386 dio200_write8(dev, subpriv->clk_sce_ofs, byte);
1392 * Get clock source for an '8254' counter subdevice channel.
1395 dio200_subdev_8254_get_clock_src(comedi_device * dev, comedi_subdevice *s,
1396 unsigned int counter_number, lsampl_t * period_ns)
1398 dio200_subdev_8254 *subpriv = s->private;
1401 if (!thislayout->has_clk_gat_sce)
1403 if (counter_number > 2)
1406 clock_src = subpriv->clock_src[counter_number];
1407 *period_ns = clock_period[clock_src];
1412 * Handle 'insn_config' for an '8254' counter subdevice.
1415 dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
1416 comedi_insn * insn, lsampl_t * data)
1418 dio200_subdev_8254 *subpriv = s->private;
1420 int chan = CR_CHAN(insn->chanspec);
1421 unsigned long flags;
1423 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1425 case INSN_CONFIG_SET_COUNTER_MODE:
1426 if (data[1] > (I8254_MODE5 | I8254_BINARY))
1429 dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
1431 case INSN_CONFIG_8254_READ_STATUS:
1432 data[1] = dio200_subdev_8254_status(dev, s, chan);
1434 case INSN_CONFIG_SET_GATE_SRC:
1435 ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
1439 case INSN_CONFIG_GET_GATE_SRC:
1440 ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
1447 case INSN_CONFIG_SET_CLOCK_SRC:
1448 ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
1452 case INSN_CONFIG_GET_CLOCK_SRC:
1453 ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
1464 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1465 return ret < 0 ? ret : insn->n;
1469 * This function initializes an '8254' counter subdevice.
1471 * offset is the offset to the 8254 chip.
1474 dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
1475 unsigned int offset)
1477 dio200_subdev_8254 *subpriv;
1480 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1482 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1487 s->private = subpriv;
1488 s->type = COMEDI_SUBD_COUNTER;
1489 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1491 s->maxdata = 0xFFFF;
1492 s->insn_read = dio200_subdev_8254_read;
1493 s->insn_write = dio200_subdev_8254_write;
1494 s->insn_config = dio200_subdev_8254_config;
1496 spin_lock_init(&subpriv->spinlock);
1497 subpriv->ofs = offset;
1498 if (thislayout->has_clk_gat_sce) {
1499 /* Derive CLK_SCE and GAT_SCE register offsets from
1501 subpriv->clk_sce_ofs =
1502 DIO200_XCLK_SCE + (offset >> 3);
1503 subpriv->gat_sce_ofs =
1504 DIO200_XGAT_SCE + (offset >> 3);
1505 subpriv->which = (offset >> 2) & 1;
1508 /* Initialize channels. */
1509 for (chan = 0; chan < 3; chan++) {
1510 dio200_subdev_8254_set_mode(dev, s, chan,
1511 (I8254_MODE0 | I8254_BINARY));
1512 if (thislayout->has_clk_gat_sce) {
1513 /* Gate source 0 is VCC (logic 1). */
1514 dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
1515 /* Clock source 0 is the dedicated clock input. */
1516 dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
1524 * This function cleans up an '8254' counter subdevice.
1527 dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
1529 dio200_subdev_8254 *subpriv = s->private;
1537 * This function sets I/O directions for an '8255' DIO subdevice.
1540 dio200_subdev_8255_set_dir(comedi_device * dev, comedi_subdevice * s)
1542 dio200_subdev_8255 *subpriv = s->private;
1546 /* 1 in io_bits indicates output, 1 in config indicates input */
1547 if (!(s->io_bits & 0x0000ff))
1549 if (!(s->io_bits & 0x00ff00))
1551 if (!(s->io_bits & 0x0f0000))
1552 config |= CR_C_LO_IO;
1553 if (!(s->io_bits & 0xf00000))
1554 config |= CR_C_HI_IO;
1556 dio200_write8(dev, subpriv->ofs + 3, config);
1560 * Handle 'insn_bits' for an '8255' DIO subdevice.
1563 dio200_subdev_8255_bits(comedi_device * dev, comedi_subdevice * s,
1564 comedi_insn * insn, lsampl_t * data)
1566 unsigned int i8255_ofs = ((dio200_subdev_8255 *)s->private)->ofs;
1569 s->state &= ~data[0];
1570 s->state |= (data[0] & data[1]);
1572 if (data[0] & 0xff) {
1573 dio200_write8(dev, i8255_ofs, s->state & 0xff);
1575 if (data[0] & 0xff00) {
1576 dio200_write8(dev, i8255_ofs + 1,
1577 (s->state >> 8) & 0xff);
1579 if (data[0] & 0xff0000) {
1580 dio200_write8(dev, i8255_ofs + 2,
1581 (s->state >> 16) & 0xff);
1585 data[1] = dio200_read8(dev, i8255_ofs);
1586 data[1] |= dio200_read8(dev, i8255_ofs + 1) << 8;
1587 data[1] |= dio200_read8(dev, i8255_ofs + 2) << 16;
1593 * Handle 'insn_config' for an '8255' DIO subdevice.
1596 dio200_subdev_8255_config(comedi_device * dev, comedi_subdevice * s,
1597 comedi_insn * insn, lsampl_t * data)
1602 mask = 1 << CR_CHAN(insn->chanspec);
1603 if (mask & 0x0000ff) {
1605 } else if (mask & 0x00ff00) {
1607 } else if (mask & 0x0f0000) {
1614 case INSN_CONFIG_DIO_INPUT:
1615 s->io_bits &= ~bits;
1617 case INSN_CONFIG_DIO_OUTPUT:
1620 case INSN_CONFIG_DIO_QUERY:
1621 data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
1628 dio200_subdev_8255_set_dir(dev, s);
1634 * This function initializes an '8255' DIO subdevice.
1636 * offset is the offset to the 8255 chip.
1639 dio200_subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
1640 unsigned int offset)
1642 dio200_subdev_8255 *subpriv;
1644 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1646 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1651 subpriv->ofs = offset;
1653 s->private = subpriv;
1654 s->type = COMEDI_SUBD_DIO;
1655 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1657 s->range_table = &range_digital;
1659 s->insn_bits = dio200_subdev_8255_bits;
1660 s->insn_config = dio200_subdev_8255_config;
1664 dio200_subdev_8255_set_dir(dev, s);
1670 * This function cleans up an '8255' DIO subdevice.
1673 dio200_subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s)
1675 dio200_subdev_8255 *subpriv = s->private;
1682 #ifdef CONFIG_COMEDI_PCI
1684 * This function does some special set-up for the PCIe boards
1685 * PCIe215, PCIe236, PCIe296.
1688 dio200_pcie_board_setup(comedi_device * dev)
1690 struct pci_dev *pci_dev = devpriv->pci_dev;
1691 unsigned char __iomem *brbase;
1692 resource_size_t brlen;
1695 * The board uses Altera Cyclone IV with PCI-Express hard IP.
1696 * The FPGA configuration has the PCI-Express Avalon-MM Bridge
1697 * Control registers in PCI BAR 0, offset 0, and the length of
1698 * these registers is 0x4000.
1700 * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
1701 * Enable" register at offset 0x50 to allow generation of PCIe
1702 * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
1704 brlen = pci_resource_len(pci_dev, 0);
1705 if (brlen < 0x4000 ||
1706 !(pci_resource_flags(pci_dev, 0) & IORESOURCE_MEM)) {
1707 printk(KERN_ERR "comedi%d: error! bad PCI region!\n",
1711 brbase = ioremap_nocache(pci_resource_start(pci_dev, 0), brlen);
1713 printk(KERN_ERR "comedi%d: error! failed to map registers!\n",
1717 writel(0x80, brbase + 0x50);
1720 * Enable "enhanced" features of board.
1722 dio200_write8(dev, DIO200_ENHANCE, 1);
1728 * Attach is called by the Comedi core to configure the driver
1729 * for a particular board. If you specified a board_name array
1730 * in the driver structure, dev->board_ptr contains that
1733 static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
1735 comedi_subdevice *s;
1736 unsigned long iobase = 0;
1737 unsigned int irq = 0;
1738 #ifdef CONFIG_COMEDI_PCI
1739 struct pci_dev *pci_dev = NULL;
1740 int bus = 0, slot = 0;
1742 const dio200_layout *layout;
1748 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1749 DIO200_DRIVER_NAME);
1751 if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
1752 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1757 /* Process options. */
1758 switch (thisboard->bustype) {
1760 iobase = it->options[0];
1761 irq = it->options[1];
1764 #ifdef CONFIG_COMEDI_PCI
1766 bus = it->options[0];
1767 slot = it->options[1];
1770 if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
1772 devpriv->pci_dev = pci_dev;
1777 "comedi%d: %s: BUG! cannot determine board type!\n",
1778 dev->minor, DIO200_DRIVER_NAME);
1783 devpriv->intr_sd = -1;
1784 devpriv->io.regtype = no_regtype;
1785 devpriv->io.regshift = thisboard->mainshift;
1787 /* Enable device and reserve I/O spaces. */
1788 #ifdef CONFIG_COMEDI_PCI
1790 resource_size_t base, len;
1793 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1796 "comedi%d: error! cannot enable PCI device and request regions!\n",
1800 bar = thisboard->mainbar;
1801 base = pci_resource_start(pci_dev, bar);
1802 len = pci_resource_len(pci_dev, bar);
1803 if (len < thisboard->mainsize) {
1805 "comedi%d: error! PCI region size too small!\n",
1809 if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
1810 devpriv->io.u.membase = ioremap_nocache(base, len);
1811 if (!devpriv->io.u.membase) {
1813 "comedi%d: error! cannot remap registers!\n",
1817 devpriv->io.regtype = mmio_regtype;
1819 devpriv->io.u.iobase = (unsigned long)base;
1820 devpriv->io.regtype = io_regtype;
1826 ret = dio200_request_region(dev->minor, iobase,
1827 thisboard->mainsize);
1831 devpriv->io.u.iobase = iobase;
1832 devpriv->io.regtype = io_regtype;
1835 switch (thisboard->model) {
1836 #ifdef CONFIG_COMEDI_PCI
1840 ret = dio200_pcie_board_setup(dev);
1850 layout = thislayout;
1851 if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
1852 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1857 for (n = 0; n < dev->n_subdevices; n++) {
1858 s = &dev->subdevices[n];
1859 switch (layout->sdtype[n]) {
1861 /* counter subdevice (8254) */
1862 ret = dio200_subdev_8254_init(dev, s,
1869 /* digital i/o subdevice (8255) */
1870 ret = dio200_subdev_8255_init(dev, s,
1877 /* 'INTERRUPT' subdevice */
1879 ret = dio200_subdev_intr_init(dev, s,
1880 DIO200_INT_SCE, layout->sdinfo[n]);
1884 devpriv->intr_sd = n;
1886 s->type = COMEDI_SUBD_UNUSED;
1890 /* TODO. Fall-thru to default for now. */
1892 s->type = COMEDI_SUBD_UNUSED;
1897 sdx = devpriv->intr_sd;
1898 if (sdx >= 0 && sdx < dev->n_subdevices) {
1899 dev->read_subdev = &dev->subdevices[sdx];
1902 dev->board_name = thisboard->name;
1905 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1907 if (comedi_request_irq(irq, dio200_interrupt, flags,
1908 DIO200_DRIVER_NAME, dev) >= 0) {
1912 "comedi%d: warning! irq %u unavailable!\n",
1917 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1918 if (thisboard->bustype == isa_bustype) {
1919 printk("(base %#lx) ", iobase);
1921 #ifdef CONFIG_COMEDI_PCI
1922 printk("(pci %s) ", pci_name(pci_dev));
1926 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1928 printk("(no irq) ");
1931 printk("attached\n");
1937 * _detach is called to deconfigure a device. It should deallocate
1939 * This function is also called when _attach() fails, so it should be
1940 * careful not to release resources that were not necessarily
1941 * allocated by _attach(). dev->private and dev->subdevices are
1942 * deallocated automatically by the core.
1944 static int dio200_detach(comedi_device * dev)
1946 const dio200_layout *layout;
1949 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1950 DIO200_DRIVER_NAME);
1953 comedi_free_irq(dev->irq, dev);
1955 if (dev->subdevices) {
1956 layout = thislayout;
1957 for (n = 0; n < dev->n_subdevices; n++) {
1958 comedi_subdevice *s = &dev->subdevices[n];
1959 switch (layout->sdtype[n]) {
1961 dio200_subdev_8254_cleanup(dev, s);
1964 dio200_subdev_8255_cleanup(dev, s);
1967 dio200_subdev_intr_cleanup(dev, s);
1975 if (devpriv->io.regtype == mmio_regtype) {
1976 iounmap(devpriv->io.u.membase);
1978 #ifdef CONFIG_COMEDI_PCI
1979 if (devpriv->pci_dev) {
1980 if (devpriv->io.regtype != no_regtype) {
1981 comedi_pci_disable(devpriv->pci_dev);
1983 pci_dev_put(devpriv->pci_dev);
1987 if (devpriv->io.regtype == io_regtype) {
1988 release_region(devpriv->io.u.iobase,
1989 thisboard->mainsize);
1993 if (dev->board_name) {
1994 printk(KERN_INFO "comedi%d: %s removed\n",
1995 dev->minor, dev->board_name);