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 or amplc_dio200), PC218E (pc218e), PC272E (pc272e),
33 PCI272 (pci272 or amplc_dio200)
34 Updated: Wed, 22 Oct 2008 13:36:02 +0100
37 Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
38 [0] - I/O port base address
39 [1] - IRQ (optional, but commands won't work without it)
41 Configuration 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
47 Passing a zero for an option is the same as leaving it unspecified.
51 PC218E PC212E PC215E/PCI215
52 ------------- ------------- -------------
56 2 CTR-Y1 CTR-Y2 CTR-Z1
57 3 CTR-Y2 CTR-Z1 CTR-Z2
58 4 CTR-Z1 CTR-Z2 INTERRUPT
63 ------------- -------------
68 3 INTERRUPT* INTERRUPT
70 Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels
71 are configurable as inputs or outputs in four groups:
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
78 Only mode 0 of the 8255 chips is supported.
80 Each CTR is a 8254 chip providing 3 16-bit counter channels. Each
81 channel is configured individually with INSN_CONFIG instructions. The
82 specific type of configuration instruction is specified in data[0].
83 Some configuration instructions expect an additional parameter in
84 data[1]; others return a value in data[1]. The following configuration
85 instructions are supported:
87 INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and
88 BCD/binary setting specified in data[1].
90 INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the
91 counter channel into data[1].
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
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.
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
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
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
132 INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate
135 Clock and gate interconnection notes:
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.
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.
145 3. The counter subdevices are connected in a ring, so the highest
146 counter subdevice precedes the lowest.
148 The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The
149 digital inputs come from the interrupt status register. The number of
150 channels matches the number of interrupt sources. The PC214E does not
151 have an interrupt status register; see notes on 'INTERRUPT SOURCES'
156 PC218E PC212E PC215E/PCI215
157 ------------- ------------- -------------
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
167 ------------- -------------
176 When an interrupt source is enabled in the interrupt source enable
177 register, a rising edge on the source signal latches the corresponding
178 bit to 1 in the interrupt status register.
180 When the interrupt status register value as a whole (actually, just the
181 6 least significant bits) goes from zero to non-zero, the board will
182 generate an interrupt. For level-triggered hardware interrupts (PCI
183 card), the interrupt will remain asserted until the interrupt status
184 register is cleared to zero. For edge-triggered hardware interrupts
185 (ISA card), no further interrupts will occur until the interrupt status
186 register is cleared to zero. To clear a bit to zero in the interrupt
187 status register, the corresponding interrupt source must be disabled
188 in the interrupt source enable register (there is no separate interrupt
191 The PC214E does not have an interrupt source enable register or an
192 interrupt status register; its 'INTERRUPT' subdevice has a single
193 channel and its interrupt source is selected by the position of jumper
198 The driver supports a read streaming acquisition command on the
199 'INTERRUPT' subdevice. The channel list selects the interrupt sources
200 to be enabled. All channels will be sampled together (convert_src ==
201 TRIG_NOW). The scan begins a short time after the hardware interrupt
202 occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
203 scan_begin_arg == 0). The value read from the interrupt status register
204 is packed into a short value, one bit per requested channel, in the
205 order they appear in the channel list.
208 #include <linux/interrupt.h>
209 #include <linux/slab.h>
211 #include "../comedidev.h"
213 #include "comedi_pci.h"
218 #define DIO200_DRIVER_NAME "amplc_dio200"
221 #define PCI_VENDOR_ID_AMPLICON 0x14dc
222 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
223 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
224 #define PCI_DEVICE_ID_INVALID 0xffff
226 /* 200 series registers */
227 #define DIO200_IO_SIZE 0x20
228 #define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
229 #define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
230 #define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
231 #define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
232 #define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
233 #define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
234 #define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
237 * Macros for constructing value for DIO_200_?CLK_SCE and
238 * DIO_200_?GAT_SCE registers:
240 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
241 * 'chan' is the channel: 0, 1 or 2.
242 * 'source' is the signal source: 0 to 7.
244 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
245 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
248 * Periods of the internal clock sources in nanoseconds.
250 static const unsigned clock_period[8] = {
251 0, /* dedicated clock input/output pin */
258 0 /* group clock input pin */
262 * Board descriptions.
265 enum dio200_bustype { isa_bustype, pci_bustype };
270 pc215e_model, pci215_model,
272 pc272e_model, pci272_model,
284 struct dio200_board {
286 unsigned short devid;
287 enum dio200_bustype bustype;
288 enum dio200_model model;
289 enum dio200_layout layout;
292 static const struct dio200_board dio200_boards[] = {
295 .bustype = isa_bustype,
296 .model = pc212e_model,
297 .layout = pc212_layout,
301 .bustype = isa_bustype,
302 .model = pc214e_model,
303 .layout = pc214_layout,
307 .bustype = isa_bustype,
308 .model = pc215e_model,
309 .layout = pc215_layout,
311 #ifdef CONFIG_COMEDI_PCI
314 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
315 .bustype = pci_bustype,
316 .model = pci215_model,
317 .layout = pc215_layout,
322 .bustype = isa_bustype,
323 .model = pc218e_model,
324 .layout = pc218_layout,
328 .bustype = isa_bustype,
329 .model = pc272e_model,
330 .layout = pc272_layout,
332 #ifdef CONFIG_COMEDI_PCI
335 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
336 .bustype = pci_bustype,
337 .model = pci272_model,
338 .layout = pc272_layout,
341 #ifdef CONFIG_COMEDI_PCI
343 .name = DIO200_DRIVER_NAME,
344 .devid = PCI_DEVICE_ID_INVALID,
345 .bustype = pci_bustype,
346 .model = anypci_model, /* wildcard */
352 * Layout descriptions - some ISA and PCI board descriptions share the same
356 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
358 #define DIO200_MAX_SUBDEVS 7
359 #define DIO200_MAX_ISNS 6
361 struct dio200_layout_struct {
362 unsigned short n_subdevs; /* number of subdevices */
363 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */
364 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */
365 char has_int_sce; /* has interrupt enable/status register */
366 char has_clk_gat_sce; /* has clock/gate selection registers */
369 static const struct dio200_layout_struct dio200_layouts[] = {
372 .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
375 .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
378 .has_clk_gat_sce = 1,
382 .sdtype = {sd_8255, sd_8255, sd_8254,
384 .sdinfo = {0x00, 0x08, 0x10, 0x01},
386 .has_clk_gat_sce = 0,
390 .sdtype = {sd_8255, sd_8255, sd_8254,
393 .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
395 .has_clk_gat_sce = 1,
399 .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
402 .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
406 .has_clk_gat_sce = 1,
410 .sdtype = {sd_8255, sd_8255, sd_8255,
412 .sdinfo = {0x00, 0x08, 0x10, 0x3F},
414 .has_clk_gat_sce = 0,
422 #ifdef CONFIG_COMEDI_PCI
423 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
425 PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
426 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
427 PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
428 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
432 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
433 #endif /* CONFIG_COMEDI_PCI */
436 * Useful for shorthand access to the particular board structure
438 #define thisboard ((const struct dio200_board *)dev->board_ptr)
439 #define thislayout (&dio200_layouts[((struct dio200_board *) \
440 dev->board_ptr)->layout])
442 /* this structure is for data unique to this hardware driver. If
443 several hardware drivers keep similar information in this structure,
444 feel free to suggest moving the variable to the struct comedi_device struct.
446 struct dio200_private {
447 #ifdef CONFIG_COMEDI_PCI
448 struct pci_dev *pci_dev; /* PCI device */
453 #define devpriv ((struct dio200_private *)dev->private)
455 struct dio200_subdev_8254 {
456 unsigned long iobase; /* Counter base address */
457 unsigned long clk_sce_iobase; /* CLK_SCE base address */
458 unsigned long gat_sce_iobase; /* GAT_SCE base address */
459 int which; /* Bit 5 of CLK_SCE or GAT_SCE */
461 unsigned clock_src[3]; /* Current clock sources */
462 unsigned gate_src[3]; /* Current gate sources */
466 struct dio200_subdev_intr {
467 unsigned long iobase;
471 unsigned int valid_isns;
472 unsigned int enabled_isns;
473 unsigned int stopcount;
478 * The struct comedi_driver structure tells the Comedi core module
479 * which functions to call to configure/deconfigure (attach/detach)
480 * the board, and also about the kernel module that contains
483 static int dio200_attach(struct comedi_device *dev,
484 struct comedi_devconfig *it);
485 static int dio200_detach(struct comedi_device *dev);
486 static struct comedi_driver driver_amplc_dio200 = {
487 .driver_name = DIO200_DRIVER_NAME,
488 .module = THIS_MODULE,
489 .attach = dio200_attach,
490 .detach = dio200_detach,
491 .board_name = &dio200_boards[0].name,
492 .offset = sizeof(struct dio200_board),
493 .num_names = ARRAY_SIZE(dio200_boards),
496 #ifdef CONFIG_COMEDI_PCI
497 static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
498 const struct pci_device_id
501 return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
504 static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
506 comedi_pci_auto_unconfig(dev);
509 static struct pci_driver driver_amplc_dio200_pci_driver = {
510 .id_table = dio200_pci_table,
511 .probe = &driver_amplc_dio200_pci_probe,
512 .remove = __devexit_p(&driver_amplc_dio200_pci_remove)
515 static int __init driver_amplc_dio200_init_module(void)
519 retval = comedi_driver_register(&driver_amplc_dio200);
523 driver_amplc_dio200_pci_driver.name =
524 (char *)driver_amplc_dio200.driver_name;
525 return pci_register_driver(&driver_amplc_dio200_pci_driver);
528 static void __exit driver_amplc_dio200_cleanup_module(void)
530 pci_unregister_driver(&driver_amplc_dio200_pci_driver);
531 comedi_driver_unregister(&driver_amplc_dio200);
534 module_init(driver_amplc_dio200_init_module);
535 module_exit(driver_amplc_dio200_cleanup_module);
537 static int __init driver_amplc_dio200_init_module(void)
539 return comedi_driver_register(&driver_amplc_dio200);
542 static void __exit driver_amplc_dio200_cleanup_module(void)
544 comedi_driver_unregister(&driver_amplc_dio200);
547 module_init(driver_amplc_dio200_init_module);
548 module_exit(driver_amplc_dio200_cleanup_module);
552 * This function looks for a PCI device matching the requested board name,
555 #ifdef CONFIG_COMEDI_PCI
557 dio200_find_pci(struct comedi_device *dev, int bus, int slot,
558 struct pci_dev **pci_dev_p)
560 struct pci_dev *pci_dev = NULL;
564 /* Look for matching PCI device. */
565 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
567 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
568 PCI_ANY_ID, pci_dev)) {
569 /* If bus/slot specified, check them. */
571 if (bus != pci_dev->bus->number
572 || slot != PCI_SLOT(pci_dev->devfn))
575 if (thisboard->model == anypci_model) {
576 /* Match any supported model. */
579 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
580 if (dio200_boards[i].bustype != pci_bustype)
582 if (pci_dev->device == dio200_boards[i].devid) {
583 /* Change board_ptr to matched board. */
584 dev->board_ptr = &dio200_boards[i];
588 if (i == ARRAY_SIZE(dio200_boards))
591 /* Match specific model name. */
592 if (pci_dev->device != thisboard->devid)
597 *pci_dev_p = pci_dev;
600 /* No match found. */
603 "comedi%d: error! no %s found at pci %02x:%02x!\n",
604 dev->minor, thisboard->name, bus, slot);
606 printk(KERN_ERR "comedi%d: error! no %s found!\n",
607 dev->minor, thisboard->name);
614 * This function checks and requests an I/O region, reporting an error
615 * if there is a conflict.
618 dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
620 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
621 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
622 minor, from, extent);
629 * 'insn_bits' function for an 'INTERRUPT' subdevice.
632 dio200_subdev_intr_insn_bits(struct comedi_device *dev,
633 struct comedi_subdevice *s,
634 struct comedi_insn *insn, unsigned int *data)
636 struct dio200_subdev_intr *subpriv = s->private;
638 if (subpriv->has_int_sce) {
639 /* Just read the interrupt status register. */
640 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
642 /* No interrupt status register. */
650 * Called to stop acquisition for an 'INTERRUPT' subdevice.
652 static void dio200_stop_intr(struct comedi_device *dev,
653 struct comedi_subdevice *s)
655 struct dio200_subdev_intr *subpriv = s->private;
658 subpriv->enabled_isns = 0;
659 if (subpriv->has_int_sce)
660 outb(0, subpriv->iobase);
664 * Called to start acquisition for an 'INTERRUPT' subdevice.
666 static int dio200_start_intr(struct comedi_device *dev,
667 struct comedi_subdevice *s)
671 struct dio200_subdev_intr *subpriv = s->private;
672 struct comedi_cmd *cmd = &s->async->cmd;
675 if (!subpriv->continuous && subpriv->stopcount == 0) {
676 /* An empty acquisition! */
677 s->async->events |= COMEDI_CB_EOA;
681 /* Determine interrupt sources to enable. */
684 for (n = 0; n < cmd->chanlist_len; n++)
685 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
687 isn_bits &= subpriv->valid_isns;
688 /* Enable interrupt sources. */
689 subpriv->enabled_isns = isn_bits;
690 if (subpriv->has_int_sce)
691 outb(isn_bits, subpriv->iobase);
698 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
701 dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
702 unsigned int trignum)
704 struct dio200_subdev_intr *subpriv;
711 subpriv = s->private;
713 spin_lock_irqsave(&subpriv->spinlock, flags);
714 s->async->inttrig = NULL;
716 event = dio200_start_intr(dev, s);
718 spin_unlock_irqrestore(&subpriv->spinlock, flags);
721 comedi_event(dev, s);
727 * This is called from the interrupt service routine to handle a read
728 * scan on an 'INTERRUPT' subdevice.
730 static int dio200_handle_read_intr(struct comedi_device *dev,
731 struct comedi_subdevice *s)
733 struct dio200_subdev_intr *subpriv = s->private;
736 unsigned cur_enabled;
737 unsigned int oldevents;
742 spin_lock_irqsave(&subpriv->spinlock, flags);
743 oldevents = s->async->events;
744 if (subpriv->has_int_sce) {
746 * Collect interrupt sources that have triggered and disable
747 * them temporarily. Loop around until no extra interrupt
748 * sources have triggered, at which point, the valid part of
749 * the interrupt status register will read zero, clearing the
750 * cause of the interrupt.
752 * Mask off interrupt sources already seen to avoid infinite
753 * loop in case of misconfiguration.
755 cur_enabled = subpriv->enabled_isns;
756 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
757 & ~triggered)) != 0) {
758 triggered |= intstat;
759 cur_enabled &= ~triggered;
760 outb(cur_enabled, subpriv->iobase);
764 * No interrupt status register. Assume the single interrupt
765 * source has triggered.
767 triggered = subpriv->enabled_isns;
772 * Some interrupt sources have triggered and have been
773 * temporarily disabled to clear the cause of the interrupt.
775 * Reenable them NOW to minimize the time they are disabled.
777 cur_enabled = subpriv->enabled_isns;
778 if (subpriv->has_int_sce)
779 outb(cur_enabled, subpriv->iobase);
781 if (subpriv->active) {
783 * The command is still active.
785 * Ignore interrupt sources that the command isn't
786 * interested in (just in case there's a race
789 if (triggered & subpriv->enabled_isns) {
790 /* Collect scan data. */
792 unsigned int n, ch, len;
795 len = s->async->cmd.chanlist_len;
796 for (n = 0; n < len; n++) {
797 ch = CR_CHAN(s->async->cmd.chanlist[n]);
798 if (triggered & (1U << ch))
801 /* Write the scan to the buffer. */
802 if (comedi_buf_put(s->async, val)) {
803 s->async->events |= (COMEDI_CB_BLOCK |
806 /* Error! Stop acquisition. */
807 dio200_stop_intr(dev, s);
808 s->async->events |= COMEDI_CB_ERROR
809 | COMEDI_CB_OVERFLOW;
810 comedi_error(dev, "buffer overflow");
813 /* Check for end of acquisition. */
814 if (!subpriv->continuous) {
815 /* stop_src == TRIG_COUNT */
816 if (subpriv->stopcount > 0) {
817 subpriv->stopcount--;
818 if (subpriv->stopcount == 0) {
821 dio200_stop_intr(dev,
829 spin_unlock_irqrestore(&subpriv->spinlock, flags);
831 if (oldevents != s->async->events)
832 comedi_event(dev, s);
834 return (triggered != 0);
838 * 'cancel' function for an 'INTERRUPT' subdevice.
840 static int dio200_subdev_intr_cancel(struct comedi_device *dev,
841 struct comedi_subdevice *s)
843 struct dio200_subdev_intr *subpriv = s->private;
846 spin_lock_irqsave(&subpriv->spinlock, flags);
848 dio200_stop_intr(dev, s);
850 spin_unlock_irqrestore(&subpriv->spinlock, flags);
856 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
859 dio200_subdev_intr_cmdtest(struct comedi_device *dev,
860 struct comedi_subdevice *s, struct comedi_cmd *cmd)
865 /* step 1: make sure trigger sources are trivially valid */
867 tmp = cmd->start_src;
868 cmd->start_src &= (TRIG_NOW | TRIG_INT);
869 if (!cmd->start_src || tmp != cmd->start_src)
872 tmp = cmd->scan_begin_src;
873 cmd->scan_begin_src &= TRIG_EXT;
874 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
877 tmp = cmd->convert_src;
878 cmd->convert_src &= TRIG_NOW;
879 if (!cmd->convert_src || tmp != cmd->convert_src)
882 tmp = cmd->scan_end_src;
883 cmd->scan_end_src &= TRIG_COUNT;
884 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
888 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
889 if (!cmd->stop_src || tmp != cmd->stop_src)
895 /* step 2: make sure trigger sources are unique and mutually
898 /* these tests are true if more than one _src bit is set */
899 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
901 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
903 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
905 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
907 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
913 /* step 3: make sure arguments are trivially compatible */
915 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
916 if (cmd->start_arg != 0) {
921 /* cmd->scan_begin_src == TRIG_EXT */
922 if (cmd->scan_begin_arg != 0) {
923 cmd->scan_begin_arg = 0;
927 /* cmd->convert_src == TRIG_NOW */
928 if (cmd->convert_arg != 0) {
929 cmd->convert_arg = 0;
933 /* cmd->scan_end_src == TRIG_COUNT */
934 if (cmd->scan_end_arg != cmd->chanlist_len) {
935 cmd->scan_end_arg = cmd->chanlist_len;
939 switch (cmd->stop_src) {
941 /* any count allowed */
944 if (cmd->stop_arg != 0) {
956 /* step 4: fix up any arguments */
958 /* if (err) return 4; */
964 * 'do_cmd' function for an 'INTERRUPT' subdevice.
966 static int dio200_subdev_intr_cmd(struct comedi_device *dev,
967 struct comedi_subdevice *s)
969 struct comedi_cmd *cmd = &s->async->cmd;
970 struct dio200_subdev_intr *subpriv = s->private;
974 spin_lock_irqsave(&subpriv->spinlock, flags);
977 /* Set up end of acquisition. */
978 switch (cmd->stop_src) {
980 subpriv->continuous = 0;
981 subpriv->stopcount = cmd->stop_arg;
985 subpriv->continuous = 1;
986 subpriv->stopcount = 0;
990 /* Set up start of acquisition. */
991 switch (cmd->start_src) {
993 s->async->inttrig = dio200_inttrig_start_intr;
997 event = dio200_start_intr(dev, s);
1000 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1003 comedi_event(dev, s);
1009 * This function initializes an 'INTERRUPT' subdevice.
1012 dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
1013 unsigned long iobase, unsigned valid_isns,
1016 struct dio200_subdev_intr *subpriv;
1018 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1020 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1024 subpriv->iobase = iobase;
1025 subpriv->has_int_sce = has_int_sce;
1026 subpriv->valid_isns = valid_isns;
1027 spin_lock_init(&subpriv->spinlock);
1030 outb(0, subpriv->iobase); /* Disable interrupt sources. */
1032 s->private = subpriv;
1033 s->type = COMEDI_SUBD_DI;
1034 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1036 s->n_chan = DIO200_MAX_ISNS;
1037 s->len_chanlist = DIO200_MAX_ISNS;
1039 /* No interrupt source register. Support single channel. */
1041 s->len_chanlist = 1;
1043 s->range_table = &range_digital;
1045 s->insn_bits = dio200_subdev_intr_insn_bits;
1046 s->do_cmdtest = dio200_subdev_intr_cmdtest;
1047 s->do_cmd = dio200_subdev_intr_cmd;
1048 s->cancel = dio200_subdev_intr_cancel;
1054 * This function cleans up an 'INTERRUPT' subdevice.
1057 dio200_subdev_intr_cleanup(struct comedi_device *dev,
1058 struct comedi_subdevice *s)
1060 struct dio200_subdev_intr *subpriv = s->private;
1065 * Interrupt service routine.
1067 static irqreturn_t dio200_interrupt(int irq, void *d)
1069 struct comedi_device *dev = d;
1075 if (devpriv->intr_sd >= 0) {
1076 handled = dio200_handle_read_intr(dev,
1083 return IRQ_RETVAL(handled);
1087 * Handle 'insn_read' for an '8254' counter subdevice.
1090 dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1091 struct comedi_insn *insn, unsigned int *data)
1093 struct dio200_subdev_8254 *subpriv = s->private;
1094 int chan = CR_CHAN(insn->chanspec);
1095 unsigned long flags;
1097 spin_lock_irqsave(&subpriv->spinlock, flags);
1098 data[0] = i8254_read(subpriv->iobase, 0, chan);
1099 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1105 * Handle 'insn_write' for an '8254' counter subdevice.
1108 dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1109 struct comedi_insn *insn, unsigned int *data)
1111 struct dio200_subdev_8254 *subpriv = s->private;
1112 int chan = CR_CHAN(insn->chanspec);
1113 unsigned long flags;
1115 spin_lock_irqsave(&subpriv->spinlock, flags);
1116 i8254_write(subpriv->iobase, 0, chan, data[0]);
1117 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1123 * Set gate source for an '8254' counter subdevice channel.
1126 dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1127 unsigned int counter_number, unsigned int gate_src)
1131 if (!subpriv->has_clk_gat_sce)
1133 if (counter_number > 2)
1138 subpriv->gate_src[counter_number] = gate_src;
1139 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1140 outb(byte, subpriv->gat_sce_iobase);
1146 * Get gate source for an '8254' counter subdevice channel.
1149 dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1150 unsigned int counter_number)
1152 if (!subpriv->has_clk_gat_sce)
1154 if (counter_number > 2)
1157 return subpriv->gate_src[counter_number];
1161 * Set clock source for an '8254' counter subdevice channel.
1164 dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1165 unsigned int counter_number, unsigned int clock_src)
1169 if (!subpriv->has_clk_gat_sce)
1171 if (counter_number > 2)
1176 subpriv->clock_src[counter_number] = clock_src;
1177 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1178 outb(byte, subpriv->clk_sce_iobase);
1184 * Get clock source for an '8254' counter subdevice channel.
1187 dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1188 unsigned int counter_number, unsigned int *period_ns)
1192 if (!subpriv->has_clk_gat_sce)
1194 if (counter_number > 2)
1197 clock_src = subpriv->clock_src[counter_number];
1198 *period_ns = clock_period[clock_src];
1203 * Handle 'insn_config' for an '8254' counter subdevice.
1206 dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1207 struct comedi_insn *insn, unsigned int *data)
1209 struct dio200_subdev_8254 *subpriv = s->private;
1211 int chan = CR_CHAN(insn->chanspec);
1212 unsigned long flags;
1214 spin_lock_irqsave(&subpriv->spinlock, flags);
1216 case INSN_CONFIG_SET_COUNTER_MODE:
1217 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1221 case INSN_CONFIG_8254_READ_STATUS:
1222 data[1] = i8254_status(subpriv->iobase, 0, chan);
1224 case INSN_CONFIG_SET_GATE_SRC:
1225 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1229 case INSN_CONFIG_GET_GATE_SRC:
1230 ret = dio200_get_gate_src(subpriv, chan);
1237 case INSN_CONFIG_SET_CLOCK_SRC:
1238 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1242 case INSN_CONFIG_GET_CLOCK_SRC:
1243 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1254 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1255 return ret < 0 ? ret : insn->n;
1259 * This function initializes an '8254' counter subdevice.
1261 * Note: iobase is the base address of the board, not the subdevice;
1262 * offset is the offset to the 8254 chip.
1265 dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1266 unsigned long iobase, unsigned offset,
1267 int has_clk_gat_sce)
1269 struct dio200_subdev_8254 *subpriv;
1272 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1274 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1279 s->private = subpriv;
1280 s->type = COMEDI_SUBD_COUNTER;
1281 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1283 s->maxdata = 0xFFFF;
1284 s->insn_read = dio200_subdev_8254_read;
1285 s->insn_write = dio200_subdev_8254_write;
1286 s->insn_config = dio200_subdev_8254_config;
1288 spin_lock_init(&subpriv->spinlock);
1289 subpriv->iobase = offset + iobase;
1290 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1291 if (has_clk_gat_sce) {
1292 /* Derive CLK_SCE and GAT_SCE register offsets from
1294 subpriv->clk_sce_iobase =
1295 DIO200_XCLK_SCE + (offset >> 3) + iobase;
1296 subpriv->gat_sce_iobase =
1297 DIO200_XGAT_SCE + (offset >> 3) + iobase;
1298 subpriv->which = (offset >> 2) & 1;
1301 /* Initialize channels. */
1302 for (chan = 0; chan < 3; chan++) {
1303 i8254_set_mode(subpriv->iobase, 0, chan,
1304 I8254_MODE0 | I8254_BINARY);
1305 if (subpriv->has_clk_gat_sce) {
1306 /* Gate source 0 is VCC (logic 1). */
1307 dio200_set_gate_src(subpriv, chan, 0);
1308 /* Clock source 0 is the dedicated clock input. */
1309 dio200_set_clock_src(subpriv, chan, 0);
1317 * This function cleans up an '8254' counter subdevice.
1320 dio200_subdev_8254_cleanup(struct comedi_device *dev,
1321 struct comedi_subdevice *s)
1323 struct dio200_subdev_intr *subpriv = s->private;
1328 * Attach is called by the Comedi core to configure the driver
1329 * for a particular board. If you specified a board_name array
1330 * in the driver structure, dev->board_ptr contains that
1333 static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1335 struct comedi_subdevice *s;
1336 unsigned long iobase = 0;
1337 unsigned int irq = 0;
1338 #ifdef CONFIG_COMEDI_PCI
1339 struct pci_dev *pci_dev = NULL;
1340 int bus = 0, slot = 0;
1342 const struct dio200_layout_struct *layout;
1348 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1349 DIO200_DRIVER_NAME);
1351 ret = alloc_private(dev, sizeof(struct dio200_private));
1353 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1358 /* Process options. */
1359 switch (thisboard->bustype) {
1361 iobase = it->options[0];
1362 irq = it->options[1];
1365 #ifdef CONFIG_COMEDI_PCI
1367 bus = it->options[0];
1368 slot = it->options[1];
1371 ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1374 devpriv->pci_dev = pci_dev;
1379 "comedi%d: %s: BUG! cannot determine board type!\n",
1380 dev->minor, DIO200_DRIVER_NAME);
1385 devpriv->intr_sd = -1;
1387 /* Enable device and reserve I/O spaces. */
1388 #ifdef CONFIG_COMEDI_PCI
1390 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1393 "comedi%d: error! cannot enable PCI device and request regions!\n",
1397 iobase = pci_resource_start(pci_dev, 2);
1402 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1406 dev->iobase = iobase;
1408 layout = thislayout;
1410 ret = alloc_subdevices(dev, layout->n_subdevs);
1412 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1417 for (n = 0; n < dev->n_subdevices; n++) {
1418 s = &dev->subdevices[n];
1419 switch (layout->sdtype[n]) {
1421 /* counter subdevice (8254) */
1422 ret = dio200_subdev_8254_init(dev, s, iobase,
1424 layout->has_clk_gat_sce);
1430 /* digital i/o subdevice (8255) */
1431 ret = subdev_8255_init(dev, s, NULL,
1432 iobase + layout->sdinfo[n]);
1438 /* 'INTERRUPT' subdevice */
1440 ret = dio200_subdev_intr_init(dev, s,
1449 devpriv->intr_sd = n;
1451 s->type = COMEDI_SUBD_UNUSED;
1455 s->type = COMEDI_SUBD_UNUSED;
1460 sdx = devpriv->intr_sd;
1461 if (sdx >= 0 && sdx < dev->n_subdevices)
1462 dev->read_subdev = &dev->subdevices[sdx];
1464 dev->board_name = thisboard->name;
1467 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1469 if (request_irq(irq, dio200_interrupt, flags,
1470 DIO200_DRIVER_NAME, dev) >= 0) {
1474 "comedi%d: warning! irq %u unavailable!\n",
1479 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1480 if (thisboard->bustype == isa_bustype) {
1481 printk("(base %#lx) ", iobase);
1483 #ifdef CONFIG_COMEDI_PCI
1484 printk("(pci %s) ", pci_name(pci_dev));
1488 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1490 printk("(no irq) ");
1492 printk("attached\n");
1498 * _detach is called to deconfigure a device. It should deallocate
1500 * This function is also called when _attach() fails, so it should be
1501 * careful not to release resources that were not necessarily
1502 * allocated by _attach(). dev->private and dev->subdevices are
1503 * deallocated automatically by the core.
1505 static int dio200_detach(struct comedi_device *dev)
1507 const struct dio200_layout_struct *layout;
1510 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1511 DIO200_DRIVER_NAME);
1514 free_irq(dev->irq, dev);
1515 if (dev->subdevices) {
1516 layout = thislayout;
1517 for (n = 0; n < dev->n_subdevices; n++) {
1518 struct comedi_subdevice *s = &dev->subdevices[n];
1519 switch (layout->sdtype[n]) {
1521 dio200_subdev_8254_cleanup(dev, s);
1524 subdev_8255_cleanup(dev, s);
1527 dio200_subdev_intr_cleanup(dev, s);
1535 #ifdef CONFIG_COMEDI_PCI
1536 if (devpriv->pci_dev) {
1538 comedi_pci_disable(devpriv->pci_dev);
1539 pci_dev_put(devpriv->pci_dev);
1544 release_region(dev->iobase, DIO200_IO_SIZE);
1547 if (dev->board_name)
1548 printk(KERN_INFO "comedi%d: %s removed\n",
1549 dev->minor, dev->board_name);
1554 MODULE_AUTHOR("Comedi http://www.comedi.org");
1555 MODULE_DESCRIPTION("Comedi low-level driver");
1556 MODULE_LICENSE("GPL");