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.)
7 Copyright (C) 2005 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), PC218E (pc218e), PC272E (pc272e), PCI272 (pci272)
33 Updated: Mon, 06 Aug 2007 11:06:10 +0100
36 Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
37 [0] - I/O port base address
38 [1] - IRQ (optional, but commands won't work without it)
40 Configuration options - PCI215, PCI272:
41 [0] - PCI bus of device (optional)
42 [1] - PCI slot of device (optional)
43 If bus/slot is not specified, the first available PCI device will
46 Passing a zero for an option is the same as leaving it unspecified.
50 PC218E PC212E PC215E/PCI215
51 ------------- ------------- -------------
55 2 CTR-Y1 CTR-Y2 CTR-Z1
56 3 CTR-Y2 CTR-Z1 CTR-Z2
57 4 CTR-Z1 CTR-Z2 INTERRUPT
62 ------------- -------------
67 3 INTERRUPT* INTERRUPT
69 Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels
70 are configurable as inputs or outputs in four groups:
72 Port A - channels 0 to 7
73 Port B - channels 8 to 15
74 Port CL - channels 16 to 19
75 Port CH - channels 20 to 23
77 Only mode 0 of the 8255 chips is supported.
79 Each CTR is a 8254 chip providing 3 16-bit counter channels. Each
80 channel is configured individually with INSN_CONFIG instructions. The
81 specific type of configuration instruction is specified in data[0].
82 Some configuration instructions expect an additional parameter in
83 data[1]; others return a value in data[1]. The following configuration
84 instructions are supported:
86 INSN_CONFIG_8254_SET_MODE. Sets the counter channel's mode and
87 BCD/binary setting specified in data[1].
89 INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the
90 counter channel into data[1].
92 INSN_CONFIG_SET_CLOCK_SRC. Sets the counter channel's clock source as
93 specified in data[1] (this is a hardware-specific value). Not
94 supported on PC214E. For the other boards, valid clock sources are
97 0. CLK n, the counter channel's dedicated CLK input from the SK1
98 connector. (N.B. for other values, the counter channel's CLKn
99 pin on the SK1 connector is an output!)
100 1. Internal 10 MHz clock.
101 2. Internal 1 MHz clock.
102 3. Internal 100 kHz clock.
103 4. Internal 10 kHz clock.
104 5. Internal 1 kHz clock.
105 6. OUT n-1, the output of counter channel n-1 (see note 1 below).
106 7. Ext Clock, the counter chip's dedicated Ext Clock input from
107 the SK1 connector. This pin is shared by all three counter
108 channels on the chip.
110 INSN_CONFIG_GET_CLOCK_SRC. Returns the counter channel's current
111 clock source in data[1]. For internal clock sources, data[2] is set
114 INSN_CONFIG_SET_GATE_SRC. Sets the counter channel's gate source as
115 specified in data[2] (this is a hardware-specific value). Not
116 supported on PC214E. For the other boards, valid gate sources are 0
119 0. VCC (internal +5V d.c.), i.e. gate permanently enabled.
120 1. GND (internal 0V d.c.), i.e. gate permanently disabled.
121 2. GAT n, the counter channel's dedicated GAT input from the SK1
122 connector. (N.B. for other values, the counter channel's GATn
123 pin on the SK1 connector is an output!)
124 3. /OUT n-2, the inverted output of counter channel n-2 (see note
131 INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate
134 Clock and gate interconnection notes:
136 1. Clock source OUT n-1 is the output of the preceding channel on the
137 same counter subdevice if n > 0, or the output of channel 2 on the
138 preceding counter subdevice (see note 3) if n = 0.
140 2. Gate source /OUT n-2 is the inverted output of channel 0 on the
141 same counter subdevice if n = 2, or the inverted output of channel n+1
142 on the preceding counter subdevice (see note 3) if n < 2.
144 3. The counter subdevices are connected in a ring, so the highest
145 counter subdevice precedes the lowest.
147 The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The
148 digital inputs come from the interrupt status register. The number of
149 channels matches the number of interrupt sources. The PC214E does not
150 have an interrupt status register; see notes on 'INTERRUPT SOURCES'
155 PC218E PC212E PC215E/PCI215
156 ------------- ------------- -------------
158 0 CTR-X1-OUT PPI-X-C0 PPI-X-C0
159 1 CTR-X2-OUT PPI-X-C3 PPI-X-C3
160 2 CTR-Y1-OUT CTR-Y1-OUT PPI-Y-C0
161 3 CTR-Y2-OUT CTR-Y2-OUT PPI-Y-C3
162 4 CTR-Z1-OUT CTR-Z1-OUT CTR-Z1-OUT
163 5 CTR-Z2-OUT CTR-Z2-OUT CTR-Z2-OUT
166 ------------- -------------
175 When an interrupt source is enabled in the interrupt source enable
176 register, a rising edge on the source signal latches the corresponding
177 bit to 1 in the interrupt status register.
179 When the interrupt status register value as a whole (actually, just the
180 6 least significant bits) goes from zero to non-zero, the board will
181 generate an interrupt. For level-triggered hardware interrupts (PCI
182 card), the interrupt will remain asserted until the interrupt status
183 register is cleared to zero. For edge-triggered hardware interrupts
184 (ISA card), no further interrupts will occur until the interrupt status
185 register is cleared to zero. To clear a bit to zero in the interrupt
186 status register, the corresponding interrupt source must be disabled
187 in the interrupt source enable register (there is no separate interrupt
190 The PC214E does not have an interrupt source enable register or an
191 interrupt status register; its 'INTERRUPT' subdevice has a single
192 channel and its interrupt source is selected by the position of jumper
197 The driver supports a read streaming acquisition command on the
198 'INTERRUPT' subdevice. The channel list selects the interrupt sources
199 to be enabled. All channels will be sampled together (convert_src ==
200 TRIG_NOW). The scan begins a short time after the hardware interrupt
201 occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
202 scan_begin_arg == 0). The value read from the interrupt status register
203 is packed into a sampl_t value, one bit per requested channel, in the
204 order they appear in the channel list.
207 #include <linux/comedidev.h>
209 #include "comedi_pci.h"
214 #define DIO200_DRIVER_NAME "amplc_dio200"
217 /* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
218 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
219 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
221 /* 200 series registers */
222 #define DIO200_IO_SIZE 0x20
223 #define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
224 #define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
225 #define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
226 #define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
227 #define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
228 #define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
229 #define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
232 * Macros for constructing value for DIO_200_?CLK_SCE and
233 * DIO_200_?GAT_SCE registers:
235 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
236 * 'chan' is the channel: 0, 1 or 2.
237 * 'source' is the signal source: 0 to 7.
239 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
240 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
243 * Periods of the internal clock sources in nanoseconds.
245 static const unsigned clock_period[8] = {
246 0, /* dedicated clock input/output pin */
253 0 /* group clock input pin */
257 * Board descriptions.
260 enum dio200_bustype { isa_bustype, pci_bustype };
265 pc215e_model, pci215_model,
267 pc272e_model, pci272_model
278 typedef struct dio200_board_struct {
280 enum dio200_bustype bustype;
281 enum dio200_model model;
282 enum dio200_layout layout;
285 static const dio200_board dio200_boards[] = {
288 bustype: isa_bustype,
290 layout: pc212_layout,
294 bustype: isa_bustype,
296 layout: pc214_layout,
300 bustype: isa_bustype,
302 layout: pc215_layout,
306 bustype: pci_bustype,
308 layout: pc215_layout,
312 bustype: isa_bustype,
314 layout: pc218_layout,
318 bustype: isa_bustype,
320 layout: pc272_layout,
324 bustype: pci_bustype,
326 layout: pc272_layout,
331 * Layout descriptions - some ISA and PCI board descriptions share the same
335 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
337 #define DIO200_MAX_SUBDEVS 7
338 #define DIO200_MAX_ISNS 6
340 typedef struct dio200_layout_struct {
341 unsigned short n_subdevs; /* number of subdevices */
342 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */
343 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */
344 char has_int_sce; /* has interrupt enable/status register */
345 char has_clk_gat_sce; /* has clock/gate selection registers */
348 static const dio200_layout dio200_layouts[] = {
351 sdtype: {sd_8255, sd_8254, sd_8254, sd_8254,
354 sdinfo: {0x00, 0x08, 0x0C, 0x10, 0x14,
361 sdtype: {sd_8255, sd_8255, sd_8254,
363 sdinfo: {0x00, 0x08, 0x10, 0x01},
369 sdtype: {sd_8255, sd_8255, sd_8254,
372 sdinfo: {0x00, 0x08, 0x10, 0x14, 0x3F},
378 sdtype: {sd_8254, sd_8254, sd_8255, sd_8254,
381 sdinfo: {0x00, 0x04, 0x08, 0x0C, 0x10,
389 sdtype: {sd_8255, sd_8255, sd_8255,
391 sdinfo: {0x00, 0x08, 0x10, 0x3F},
401 static struct pci_device_id dio200_pci_table[] __devinitdata = {
402 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
403 PCI_ANY_ID, PCI_ANY_ID, 0, 0, pci215_model},
404 {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
405 PCI_ANY_ID, PCI_ANY_ID, 0, 0, pci272_model},
409 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
412 * Useful for shorthand access to the particular board structure
414 #define thisboard ((const dio200_board *)dev->board_ptr)
415 #define thislayout (&dio200_layouts[((dio200_board *)dev->board_ptr)->layout])
417 /* this structure is for data unique to this hardware driver. If
418 several hardware drivers keep similar information in this structure,
419 feel free to suggest moving the variable to the comedi_device struct. */
421 struct pci_dev *pci_dev; /* PCI device */
425 #define devpriv ((dio200_private *)dev->private)
428 unsigned long iobase; /* Counter base address */
429 unsigned long clk_sce_iobase; /* CLK_SCE base address */
430 unsigned long gat_sce_iobase; /* GAT_SCE base address */
431 int which; /* Bit 5 of CLK_SCE or GAT_SCE */
433 unsigned clock_src[3]; /* Current clock sources */
434 unsigned gate_src[3]; /* Current gate sources */
435 } dio200_subdev_8254;
438 unsigned long iobase;
442 unsigned int valid_isns;
443 unsigned int enabled_isns;
444 unsigned int stopcount;
446 } dio200_subdev_intr;
449 * The comedi_driver structure tells the Comedi core module
450 * which functions to call to configure/deconfigure (attach/detach)
451 * the board, and also about the kernel module that contains
454 static int dio200_attach(comedi_device * dev, comedi_devconfig * it);
455 static int dio200_detach(comedi_device * dev);
456 static comedi_driver driver_amplc_dio200 = {
457 driver_name:DIO200_DRIVER_NAME,
459 attach:dio200_attach,
460 detach:dio200_detach,
461 board_name:&dio200_boards[0].name,
462 offset:sizeof(dio200_board),
463 num_names:sizeof(dio200_boards) / sizeof(dio200_board),
466 COMEDI_INITCLEANUP(driver_amplc_dio200);
469 * This function looks for a PCI device matching the requested board name,
473 dio200_find_pci(comedi_device * dev, int bus, int slot,
474 struct pci_dev **pci_dev_p)
476 struct pci_dev *pci_dev = NULL;
477 struct pci_device_id *pci_id;
481 /* Look for PCI table entry for this model. */
482 for (pci_id = dio200_pci_table; pci_id->vendor != 0; pci_id++) {
483 if (pci_id->driver_data == thisboard->model)
486 if (pci_id->vendor == 0) {
488 "comedi%d: %s: BUG! cannot determine board type!\n",
489 dev->minor, DIO200_DRIVER_NAME);
493 /* Look for matching PCI device. */
494 for (pci_dev = pci_get_device(pci_id->vendor, pci_id->device, NULL);
496 pci_dev = pci_get_device(pci_id->vendor,
497 pci_id->device, pci_dev)) {
498 /* If bus/slot specified, check them. */
500 if (bus != pci_dev->bus->number
501 || slot != PCI_SLOT(pci_dev->devfn))
505 if (pci_id->subvendor != PCI_ANY_ID) {
506 if (pci_dev->subsystem_vendor != pci_id->subvendor)
509 if (pci_id->subdevice != PCI_ANY_ID) {
510 if (pci_dev->subsystem_device != pci_id->subdevice)
514 if (((pci_dev->class ^ pci_id->class) & pci_id->class_mask) !=
519 *pci_dev_p = pci_dev;
522 /* No match found. */
525 "comedi%d: error! no %s found at pci %02x:%02x!\n",
526 dev->minor, thisboard->name, bus, slot);
528 printk(KERN_ERR "comedi%d: error! no %s found!\n",
529 dev->minor, thisboard->name);
535 * This function checks and requests an I/O region, reporting an error
536 * if there is a conflict.
539 dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
541 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
542 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
543 minor, from, extent);
550 * 'insn_bits' function for an 'INTERRUPT' subdevice.
553 dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
554 comedi_insn * insn, lsampl_t * data)
556 dio200_subdev_intr *subpriv = s->private;
558 if (subpriv->has_int_sce) {
559 /* Just read the interrupt status register. */
560 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
562 /* No interrupt status register. */
570 * Called to stop acquisition for an 'INTERRUPT' subdevice.
572 static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
574 dio200_subdev_intr *subpriv = s->private;
576 s->async->inttrig = 0;
578 subpriv->enabled_isns = 0;
579 if (subpriv->has_int_sce) {
580 outb(0, subpriv->iobase);
585 * Called to start acquisition for an 'INTERRUPT' subdevice.
587 static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
591 dio200_subdev_intr *subpriv = s->private;
592 comedi_cmd *cmd = &s->async->cmd;
595 if (!subpriv->continuous && subpriv->stopcount == 0) {
596 /* An empty acquisition! */
597 s->async->events |= COMEDI_CB_EOA;
601 /* Determine interrupt sources to enable. */
604 for (n = 0; n < cmd->chanlist_len; n++) {
605 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
608 isn_bits &= subpriv->valid_isns;
609 /* Enable interrupt sources. */
610 subpriv->enabled_isns = isn_bits;
611 if (subpriv->has_int_sce) {
612 outb(isn_bits, subpriv->iobase);
620 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
623 dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
624 unsigned int trignum)
626 dio200_subdev_intr *subpriv;
633 subpriv = s->private;
635 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
636 s->async->inttrig = 0;
637 if (subpriv->active) {
638 event = dio200_start_intr(dev, s);
640 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
643 comedi_event(dev, s);
650 * This is called from the interrupt service routine to handle a read
651 * scan on an 'INTERRUPT' subdevice.
653 static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
655 dio200_subdev_intr *subpriv = s->private;
658 unsigned cur_enabled;
659 unsigned int oldevents;
664 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
665 oldevents = s->async->events;
666 if (subpriv->has_int_sce) {
668 * Collect interrupt sources that have triggered and disable
669 * them temporarily. Loop around until no extra interrupt
670 * sources have triggered, at which point, the valid part of
671 * the interrupt status register will read zero, clearing the
672 * cause of the interrupt.
674 * Mask off interrupt sources already seen to avoid infinite
675 * loop in case of misconfiguration.
677 cur_enabled = subpriv->enabled_isns;
678 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
679 & ~triggered)) != 0) {
680 triggered |= intstat;
681 cur_enabled &= ~triggered;
682 outb(cur_enabled, subpriv->iobase);
686 * No interrupt status register. Assume the single interrupt
687 * source has triggered.
689 triggered = subpriv->enabled_isns;
694 * Some interrupt sources have triggered and have been
695 * temporarily disabled to clear the cause of the interrupt.
697 * Reenable them NOW to minimize the time they are disabled.
699 cur_enabled = subpriv->enabled_isns;
700 if (subpriv->has_int_sce) {
701 outb(cur_enabled, subpriv->iobase);
704 if (subpriv->active) {
706 * The command is still active.
708 * Ignore interrupt sources that the command isn't
709 * interested in (just in case there's a race
712 if (triggered & subpriv->enabled_isns) {
713 /* Collect scan data. */
715 unsigned int n, ch, len;
718 len = s->async->cmd.chanlist_len;
719 for (n = 0; n < len; n++) {
720 ch = CR_CHAN(s->async->cmd.chanlist[n]);
721 if (triggered & (1U << ch)) {
725 /* Write the scan to the buffer. */
726 if (comedi_buf_put(s->async, val)) {
727 s->async->events |= (COMEDI_CB_BLOCK |
730 /* Error! Stop acquisition. */
731 dio200_stop_intr(dev, s);
734 /* Check for end of acquisition. */
735 if (!subpriv->continuous) {
736 /* stop_src == TRIG_COUNT */
737 if (subpriv->stopcount > 0) {
738 subpriv->stopcount--;
739 if (subpriv->stopcount == 0) {
742 dio200_stop_intr(dev,
750 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
752 if (oldevents != s->async->events) {
753 comedi_event(dev, s);
756 return (triggered != 0);
760 * 'cancel' function for an 'INTERRUPT' subdevice.
762 static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
764 dio200_subdev_intr *subpriv = s->private;
767 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
768 if (subpriv->active) {
769 dio200_stop_intr(dev, s);
771 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
777 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
780 dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
786 /* step 1: make sure trigger sources are trivially valid */
788 tmp = cmd->start_src;
789 cmd->start_src &= (TRIG_NOW | TRIG_INT);
790 if (!cmd->start_src || tmp != cmd->start_src)
793 tmp = cmd->scan_begin_src;
794 cmd->scan_begin_src &= TRIG_EXT;
795 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
798 tmp = cmd->convert_src;
799 cmd->convert_src &= TRIG_NOW;
800 if (!cmd->convert_src || tmp != cmd->convert_src)
803 tmp = cmd->scan_end_src;
804 cmd->scan_end_src &= TRIG_COUNT;
805 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
809 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
810 if (!cmd->stop_src || tmp != cmd->stop_src)
816 /* step 2: make sure trigger sources are unique and mutually compatible */
818 /* these tests are true if more than one _src bit is set */
819 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
821 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
823 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
825 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
827 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
833 /* step 3: make sure arguments are trivially compatible */
835 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
836 if (cmd->start_arg != 0) {
841 /* cmd->scan_begin_src == TRIG_EXT */
842 if (cmd->scan_begin_arg != 0) {
843 cmd->scan_begin_arg = 0;
847 /* cmd->convert_src == TRIG_NOW */
848 if (cmd->convert_arg != 0) {
849 cmd->convert_arg = 0;
853 /* cmd->scan_end_src == TRIG_COUNT */
854 if (cmd->scan_end_arg != cmd->chanlist_len) {
855 cmd->scan_end_arg = cmd->chanlist_len;
859 switch (cmd->stop_src) {
861 /* any count allowed */
864 if (cmd->stop_arg != 0) {
876 /* step 4: fix up any arguments */
878 /* if (err) return 4; */
884 * 'do_cmd' function for an 'INTERRUPT' subdevice.
886 static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
888 comedi_cmd *cmd = &s->async->cmd;
889 dio200_subdev_intr *subpriv = s->private;
893 comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
896 /* Set up end of acquisition. */
897 switch (cmd->stop_src) {
899 subpriv->continuous = 0;
900 subpriv->stopcount = cmd->stop_arg;
904 subpriv->continuous = 1;
905 subpriv->stopcount = 0;
909 /* Set up start of acquisition. */
910 switch (cmd->start_src) {
912 s->async->inttrig = dio200_inttrig_start_intr;
916 event = dio200_start_intr(dev, s);
919 comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
922 comedi_event(dev, s);
929 * This function initializes an 'INTERRUPT' subdevice.
932 dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
933 unsigned long iobase, unsigned valid_isns, int has_int_sce)
935 dio200_subdev_intr *subpriv;
937 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
939 printk(KERN_ERR "comedi%d: error! out of memory!\n",
943 subpriv->iobase = iobase;
944 subpriv->has_int_sce = has_int_sce;
945 subpriv->valid_isns = valid_isns;
946 spin_lock_init(&subpriv->spinlock);
949 outb(0, subpriv->iobase); /* Disable interrupt sources. */
952 s->private = subpriv;
953 s->type = COMEDI_SUBD_DI;
954 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
956 s->n_chan = DIO200_MAX_ISNS;
957 s->len_chanlist = DIO200_MAX_ISNS;
959 /* No interrupt source register. Support single channel. */
963 s->range_table = &range_digital;
965 s->insn_bits = dio200_subdev_intr_insn_bits;
966 s->do_cmdtest = dio200_subdev_intr_cmdtest;
967 s->do_cmd = dio200_subdev_intr_cmd;
968 s->cancel = dio200_subdev_intr_cancel;
974 * This function cleans up an 'INTERRUPT' subdevice.
977 dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
979 dio200_subdev_intr *subpriv = s->private;
987 * Interrupt service routine.
989 static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
991 comedi_device *dev = d;
994 if (!dev->attached) {
998 if (devpriv->intr_sd >= 0) {
999 handled = dio200_handle_read_intr(dev,
1000 dev->subdevices + devpriv->intr_sd);
1005 return IRQ_RETVAL(handled);
1009 * Handle 'insn_read' for an '8254' counter subdevice.
1012 dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
1013 comedi_insn * insn, lsampl_t * data)
1015 dio200_subdev_8254 *subpriv = s->private;
1016 int chan = CR_CHAN(insn->chanspec);
1018 data[0] = i8254_read(subpriv->iobase, 0, chan);
1024 * Handle 'insn_write' for an '8254' counter subdevice.
1027 dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
1028 comedi_insn * insn, lsampl_t * data)
1030 dio200_subdev_8254 *subpriv = s->private;
1031 int chan = CR_CHAN(insn->chanspec);
1033 i8254_write(subpriv->iobase, 0, chan, data[0]);
1039 * Set gate source for an '8254' counter subdevice channel.
1042 dio200_set_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
1043 unsigned int gate_src)
1047 if (!subpriv->has_clk_gat_sce)
1049 if (counter_number > 2)
1054 subpriv->gate_src[counter_number] = gate_src;
1055 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1056 outb(byte, subpriv->gat_sce_iobase);
1062 * Get gate source for an '8254' counter subdevice channel.
1065 dio200_get_gate_src(dio200_subdev_8254 * subpriv, unsigned int counter_number)
1067 if (!subpriv->has_clk_gat_sce)
1069 if (counter_number > 2)
1072 return subpriv->gate_src[counter_number];
1076 * Set clock source for an '8254' counter subdevice channel.
1079 dio200_set_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
1080 unsigned int clock_src)
1084 if (!subpriv->has_clk_gat_sce)
1086 if (counter_number > 2)
1091 subpriv->clock_src[counter_number] = clock_src;
1092 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1093 outb(byte, subpriv->clk_sce_iobase);
1099 * Get clock source for an '8254' counter subdevice channel.
1102 dio200_get_clock_src(dio200_subdev_8254 * subpriv, unsigned int counter_number,
1103 lsampl_t * period_ns)
1107 if (!subpriv->has_clk_gat_sce)
1109 if (counter_number > 2)
1112 clock_src = subpriv->clock_src[counter_number];
1113 *period_ns = clock_period[clock_src];
1118 * Handle 'insn_config' for an '8254' counter subdevice.
1121 dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
1122 comedi_insn * insn, lsampl_t * data)
1124 dio200_subdev_8254 *subpriv = s->private;
1126 int chan = CR_CHAN(insn->chanspec);
1129 case INSN_CONFIG_8254_SET_MODE:
1130 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1134 case INSN_CONFIG_8254_READ_STATUS:
1135 data[1] = i8254_status(subpriv->iobase, 0, chan);
1137 case INSN_CONFIG_SET_GATE_SRC:
1138 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1142 case INSN_CONFIG_GET_GATE_SRC:
1143 ret = dio200_get_gate_src(subpriv, chan);
1148 case INSN_CONFIG_SET_CLOCK_SRC:
1149 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1153 case INSN_CONFIG_GET_CLOCK_SRC:
1154 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1167 * This function initializes an '8254' counter subdevice.
1169 * Note: iobase is the base address of the board, not the subdevice;
1170 * offset is the offset to the 8254 chip.
1173 dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
1174 unsigned long iobase, unsigned offset, int has_clk_gat_sce)
1176 dio200_subdev_8254 *subpriv;
1179 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1181 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1186 s->private = subpriv;
1187 s->type = COMEDI_SUBD_COUNTER;
1188 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1190 s->maxdata = 0xFFFF;
1191 s->insn_read = dio200_subdev_8254_read;
1192 s->insn_write = dio200_subdev_8254_write;
1193 s->insn_config = dio200_subdev_8254_config;
1195 subpriv->iobase = offset + iobase;
1196 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1197 if (has_clk_gat_sce) {
1198 /* Derive CLK_SCE and GAT_SCE register offsets from
1200 subpriv->clk_sce_iobase =
1201 DIO200_XCLK_SCE + (offset >> 3) + iobase;
1202 subpriv->gat_sce_iobase =
1203 DIO200_XGAT_SCE + (offset >> 3) + iobase;
1204 subpriv->which = (offset >> 2) & 1;
1207 /* Initialize channels. */
1208 for (chan = 0; chan < 3; chan++) {
1209 i8254_set_mode(subpriv->iobase, 0, chan,
1210 I8254_MODE0 | I8254_BINARY);
1211 if (subpriv->has_clk_gat_sce) {
1212 /* Gate source 0 is VCC (logic 1). */
1213 dio200_set_gate_src(subpriv, chan, 0);
1214 /* Clock source 0 is the dedicated clock input. */
1215 dio200_set_clock_src(subpriv, chan, 0);
1223 * This function cleans up an '8254' counter subdevice.
1226 dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
1228 dio200_subdev_intr *subpriv = s->private;
1236 * Attach is called by the Comedi core to configure the driver
1237 * for a particular board. If you specified a board_name array
1238 * in the driver structure, dev->board_ptr contains that
1241 static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
1243 comedi_subdevice *s;
1244 struct pci_dev *pci_dev = NULL;
1245 unsigned long iobase = 0;
1246 unsigned int irq = 0;
1247 int bus = 0, slot = 0;
1248 const dio200_layout *layout;
1254 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1255 DIO200_DRIVER_NAME);
1257 if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
1258 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1263 /* Process options. */
1264 switch (thisboard->bustype) {
1266 iobase = it->options[0];
1267 irq = it->options[1];
1271 bus = it->options[0];
1272 slot = it->options[1];
1275 if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
1277 devpriv->pci_dev = pci_dev;
1281 "comedi%d: %s: BUG! cannot determine board type!\n",
1282 dev->minor, DIO200_DRIVER_NAME);
1287 devpriv->intr_sd = -1;
1289 /* Enable device and reserve I/O spaces. */
1291 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1294 "comedi%d: error! cannot enable PCI device and request regions!\n",
1298 iobase = pci_resource_start(pci_dev, 2);
1301 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1306 dev->iobase = iobase;
1308 layout = thislayout;
1309 if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
1310 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1315 for (n = 0; n < dev->n_subdevices; n++) {
1316 s = &dev->subdevices[n];
1317 switch (layout->sdtype[n]) {
1319 /* counter subdevice (8254) */
1320 ret = dio200_subdev_8254_init(dev, s, iobase,
1321 layout->sdinfo[n], layout->has_clk_gat_sce);
1327 /* digital i/o subdevice (8255) */
1328 ret = subdev_8255_init(dev, s, 0,
1329 iobase + layout->sdinfo[n]);
1335 /* 'INTERRUPT' subdevice */
1337 ret = dio200_subdev_intr_init(dev, s,
1338 iobase + DIO200_INT_SCE,
1339 layout->sdinfo[n], layout->has_int_sce);
1343 devpriv->intr_sd = n;
1345 s->type = COMEDI_SUBD_UNUSED;
1349 s->type = COMEDI_SUBD_UNUSED;
1354 sdx = devpriv->intr_sd;
1355 if (sdx >= 0 && sdx < dev->n_subdevices) {
1356 dev->read_subdev = &dev->subdevices[sdx];
1359 dev->board_name = thisboard->name;
1362 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1364 if (comedi_request_irq(irq, dio200_interrupt, flags,
1365 DIO200_DRIVER_NAME, dev) >= 0) {
1369 "comedi%d: warning! irq %u unavailable!\n",
1374 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1375 if (thisboard->bustype == isa_bustype) {
1376 printk("(base %#lx) ", iobase);
1378 printk("(pci %s) ", pci_name(pci_dev));
1381 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1383 printk("(no irq) ");
1386 printk("attached\n");
1392 * _detach is called to deconfigure a device. It should deallocate
1394 * This function is also called when _attach() fails, so it should be
1395 * careful not to release resources that were not necessarily
1396 * allocated by _attach(). dev->private and dev->subdevices are
1397 * deallocated automatically by the core.
1399 static int dio200_detach(comedi_device * dev)
1401 const dio200_layout *layout;
1404 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1405 DIO200_DRIVER_NAME);
1408 comedi_free_irq(dev->irq, dev);
1410 if (dev->subdevices) {
1411 layout = thislayout;
1412 for (n = 0; n < dev->n_subdevices; n++) {
1413 comedi_subdevice *s = &dev->subdevices[n];
1414 switch (layout->sdtype[n]) {
1416 dio200_subdev_8254_cleanup(dev, s);
1419 subdev_8255_cleanup(dev, s);
1422 dio200_subdev_intr_cleanup(dev, s);
1430 if (devpriv->pci_dev) {
1432 comedi_pci_disable(devpriv->pci_dev);
1434 pci_dev_put(devpriv->pci_dev);
1435 } else if (dev->iobase) {
1436 release_region(dev->iobase, DIO200_IO_SIZE);
1439 if (dev->board_name) {
1440 printk(KERN_INFO "comedi%d: %s removed\n",
1441 dev->minor, dev->board_name);