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_fc.h"
217 #define DIO200_DRIVER_NAME "amplc_dio200"
219 #define DO_ISA IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
220 #define DO_PCI IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
223 #define PCI_VENDOR_ID_AMPLICON 0x14dc
224 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
225 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
226 #define PCI_DEVICE_ID_INVALID 0xffff
228 /* 200 series registers */
229 #define DIO200_IO_SIZE 0x20
230 #define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
231 #define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
232 #define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
233 #define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
234 #define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
235 #define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
236 #define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
239 * Macros for constructing value for DIO_200_?CLK_SCE and
240 * DIO_200_?GAT_SCE registers:
242 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
243 * 'chan' is the channel: 0, 1 or 2.
244 * 'source' is the signal source: 0 to 7.
246 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
247 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
250 * Periods of the internal clock sources in nanoseconds.
252 static const unsigned clock_period[8] = {
253 0, /* dedicated clock input/output pin */
260 0 /* group clock input pin */
264 * Board descriptions.
267 enum dio200_bustype { isa_bustype, pci_bustype };
272 pc215e_model, pci215_model,
274 pc272e_model, pci272_model,
290 struct dio200_board {
292 unsigned short devid;
293 enum dio200_bustype bustype;
294 enum dio200_model model;
295 enum dio200_layout layout;
298 static const struct dio200_board dio200_boards[] = {
302 .bustype = isa_bustype,
303 .model = pc212e_model,
304 .layout = pc212_layout,
308 .bustype = isa_bustype,
309 .model = pc214e_model,
310 .layout = pc214_layout,
314 .bustype = isa_bustype,
315 .model = pc215e_model,
316 .layout = pc215_layout,
320 .bustype = isa_bustype,
321 .model = pc218e_model,
322 .layout = pc218_layout,
326 .bustype = isa_bustype,
327 .model = pc272e_model,
328 .layout = pc272_layout,
334 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
335 .bustype = pci_bustype,
336 .model = pci215_model,
337 .layout = pc215_layout,
341 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
342 .bustype = pci_bustype,
343 .model = pci272_model,
344 .layout = pc272_layout,
347 .name = DIO200_DRIVER_NAME,
348 .devid = PCI_DEVICE_ID_INVALID,
349 .bustype = pci_bustype,
350 .model = anypci_model, /* wildcard */
356 * Layout descriptions - some ISA and PCI board descriptions share the same
360 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
362 #define DIO200_MAX_SUBDEVS 7
363 #define DIO200_MAX_ISNS 6
365 struct dio200_layout_struct {
366 unsigned short n_subdevs; /* number of subdevices */
367 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */
368 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */
369 char has_int_sce; /* has interrupt enable/status register */
370 char has_clk_gat_sce; /* has clock/gate selection registers */
373 static const struct dio200_layout_struct dio200_layouts[] = {
377 .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
380 .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
383 .has_clk_gat_sce = 1,
387 .sdtype = {sd_8255, sd_8255, sd_8254,
389 .sdinfo = {0x00, 0x08, 0x10, 0x01},
391 .has_clk_gat_sce = 0,
396 .sdtype = {sd_8255, sd_8255, sd_8254,
399 .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
401 .has_clk_gat_sce = 1,
406 .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
409 .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
413 .has_clk_gat_sce = 1,
418 .sdtype = {sd_8255, sd_8255, sd_8255,
420 .sdinfo = {0x00, 0x08, 0x10, 0x3F},
422 .has_clk_gat_sce = 0,
426 /* this structure is for data unique to this hardware driver. If
427 several hardware drivers keep similar information in this structure,
428 feel free to suggest moving the variable to the struct comedi_device struct.
430 struct dio200_private {
434 struct dio200_subdev_8254 {
435 unsigned long iobase; /* Counter base address */
436 unsigned long clk_sce_iobase; /* CLK_SCE base address */
437 unsigned long gat_sce_iobase; /* GAT_SCE base address */
438 int which; /* Bit 5 of CLK_SCE or GAT_SCE */
440 unsigned clock_src[3]; /* Current clock sources */
441 unsigned gate_src[3]; /* Current gate sources */
445 struct dio200_subdev_intr {
446 unsigned long iobase;
450 unsigned int valid_isns;
451 unsigned int enabled_isns;
452 unsigned int stopcount;
456 static inline bool is_pci_board(const struct dio200_board *board)
458 return DO_PCI && board->bustype == pci_bustype;
461 static inline bool is_isa_board(const struct dio200_board *board)
463 return DO_ISA && board->bustype == isa_bustype;
467 * This function looks for a board matching the supplied PCI device.
469 static const struct dio200_board *
470 dio200_find_pci_board(struct pci_dev *pci_dev)
474 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++)
475 if (is_pci_board(&dio200_boards[i]) &&
476 pci_dev->device == dio200_boards[i].devid)
477 return &dio200_boards[i];
482 * This function looks for a PCI device matching the requested board name,
485 static struct pci_dev *dio200_find_pci_dev(struct comedi_device *dev,
486 struct comedi_devconfig *it)
488 const struct dio200_board *thisboard = comedi_board(dev);
489 struct pci_dev *pci_dev = NULL;
490 int bus = it->options[0];
491 int slot = it->options[1];
493 for_each_pci_dev(pci_dev) {
495 if (bus != pci_dev->bus->number ||
496 slot != PCI_SLOT(pci_dev->devfn))
499 if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
502 if (thisboard->model == anypci_model) {
503 /* Wildcard board matches any supported PCI board. */
504 const struct dio200_board *foundboard;
506 foundboard = dio200_find_pci_board(pci_dev);
507 if (foundboard == NULL)
509 /* Replace wildcard board_ptr. */
510 dev->board_ptr = foundboard;
512 /* Match specific model name. */
513 if (pci_dev->device != thisboard->devid)
518 dev_err(dev->class_dev,
519 "No supported board found! (req. bus %d, slot %d)\n",
525 * This function checks and requests an I/O region, reporting an error
526 * if there is a conflict.
529 dio200_request_region(struct comedi_device *dev,
530 unsigned long from, unsigned long extent)
532 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
533 dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n",
541 * 'insn_bits' function for an 'INTERRUPT' subdevice.
544 dio200_subdev_intr_insn_bits(struct comedi_device *dev,
545 struct comedi_subdevice *s,
546 struct comedi_insn *insn, unsigned int *data)
548 struct dio200_subdev_intr *subpriv = s->private;
550 if (subpriv->has_int_sce) {
551 /* Just read the interrupt status register. */
552 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
554 /* No interrupt status register. */
562 * Called to stop acquisition for an 'INTERRUPT' subdevice.
564 static void dio200_stop_intr(struct comedi_device *dev,
565 struct comedi_subdevice *s)
567 struct dio200_subdev_intr *subpriv = s->private;
570 subpriv->enabled_isns = 0;
571 if (subpriv->has_int_sce)
572 outb(0, subpriv->iobase);
576 * Called to start acquisition for an 'INTERRUPT' subdevice.
578 static int dio200_start_intr(struct comedi_device *dev,
579 struct comedi_subdevice *s)
583 struct dio200_subdev_intr *subpriv = s->private;
584 struct comedi_cmd *cmd = &s->async->cmd;
587 if (!subpriv->continuous && subpriv->stopcount == 0) {
588 /* An empty acquisition! */
589 s->async->events |= COMEDI_CB_EOA;
593 /* Determine interrupt sources to enable. */
596 for (n = 0; n < cmd->chanlist_len; n++)
597 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
599 isn_bits &= subpriv->valid_isns;
600 /* Enable interrupt sources. */
601 subpriv->enabled_isns = isn_bits;
602 if (subpriv->has_int_sce)
603 outb(isn_bits, subpriv->iobase);
610 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
613 dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
614 unsigned int trignum)
616 struct dio200_subdev_intr *subpriv;
623 subpriv = s->private;
625 spin_lock_irqsave(&subpriv->spinlock, flags);
626 s->async->inttrig = NULL;
628 event = dio200_start_intr(dev, s);
630 spin_unlock_irqrestore(&subpriv->spinlock, flags);
633 comedi_event(dev, s);
639 * This is called from the interrupt service routine to handle a read
640 * scan on an 'INTERRUPT' subdevice.
642 static int dio200_handle_read_intr(struct comedi_device *dev,
643 struct comedi_subdevice *s)
645 struct dio200_subdev_intr *subpriv = s->private;
648 unsigned cur_enabled;
649 unsigned int oldevents;
654 spin_lock_irqsave(&subpriv->spinlock, flags);
655 oldevents = s->async->events;
656 if (subpriv->has_int_sce) {
658 * Collect interrupt sources that have triggered and disable
659 * them temporarily. Loop around until no extra interrupt
660 * sources have triggered, at which point, the valid part of
661 * the interrupt status register will read zero, clearing the
662 * cause of the interrupt.
664 * Mask off interrupt sources already seen to avoid infinite
665 * loop in case of misconfiguration.
667 cur_enabled = subpriv->enabled_isns;
668 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
669 & ~triggered)) != 0) {
670 triggered |= intstat;
671 cur_enabled &= ~triggered;
672 outb(cur_enabled, subpriv->iobase);
676 * No interrupt status register. Assume the single interrupt
677 * source has triggered.
679 triggered = subpriv->enabled_isns;
684 * Some interrupt sources have triggered and have been
685 * temporarily disabled to clear the cause of the interrupt.
687 * Reenable them NOW to minimize the time they are disabled.
689 cur_enabled = subpriv->enabled_isns;
690 if (subpriv->has_int_sce)
691 outb(cur_enabled, subpriv->iobase);
693 if (subpriv->active) {
695 * The command is still active.
697 * Ignore interrupt sources that the command isn't
698 * interested in (just in case there's a race
701 if (triggered & subpriv->enabled_isns) {
702 /* Collect scan data. */
704 unsigned int n, ch, len;
707 len = s->async->cmd.chanlist_len;
708 for (n = 0; n < len; n++) {
709 ch = CR_CHAN(s->async->cmd.chanlist[n]);
710 if (triggered & (1U << ch))
713 /* Write the scan to the buffer. */
714 if (comedi_buf_put(s->async, val)) {
715 s->async->events |= (COMEDI_CB_BLOCK |
718 /* Error! Stop acquisition. */
719 dio200_stop_intr(dev, s);
720 s->async->events |= COMEDI_CB_ERROR
721 | COMEDI_CB_OVERFLOW;
722 comedi_error(dev, "buffer overflow");
725 /* Check for end of acquisition. */
726 if (!subpriv->continuous) {
727 /* stop_src == TRIG_COUNT */
728 if (subpriv->stopcount > 0) {
729 subpriv->stopcount--;
730 if (subpriv->stopcount == 0) {
733 dio200_stop_intr(dev,
741 spin_unlock_irqrestore(&subpriv->spinlock, flags);
743 if (oldevents != s->async->events)
744 comedi_event(dev, s);
746 return (triggered != 0);
750 * 'cancel' function for an 'INTERRUPT' subdevice.
752 static int dio200_subdev_intr_cancel(struct comedi_device *dev,
753 struct comedi_subdevice *s)
755 struct dio200_subdev_intr *subpriv = s->private;
758 spin_lock_irqsave(&subpriv->spinlock, flags);
760 dio200_stop_intr(dev, s);
762 spin_unlock_irqrestore(&subpriv->spinlock, flags);
768 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
771 dio200_subdev_intr_cmdtest(struct comedi_device *dev,
772 struct comedi_subdevice *s, struct comedi_cmd *cmd)
776 /* Step 1 : check if triggers are trivially valid */
778 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT);
779 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
780 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
781 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
782 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
787 /* Step 2a : make sure trigger sources are unique */
789 err |= cfc_check_trigger_is_unique(cmd->start_src);
790 err |= cfc_check_trigger_is_unique(cmd->stop_src);
792 /* Step 2b : and mutually compatible */
797 /* step 3: make sure arguments are trivially compatible */
799 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
800 if (cmd->start_arg != 0) {
805 /* cmd->scan_begin_src == TRIG_EXT */
806 if (cmd->scan_begin_arg != 0) {
807 cmd->scan_begin_arg = 0;
811 /* cmd->convert_src == TRIG_NOW */
812 if (cmd->convert_arg != 0) {
813 cmd->convert_arg = 0;
817 /* cmd->scan_end_src == TRIG_COUNT */
818 if (cmd->scan_end_arg != cmd->chanlist_len) {
819 cmd->scan_end_arg = cmd->chanlist_len;
823 switch (cmd->stop_src) {
825 /* any count allowed */
828 if (cmd->stop_arg != 0) {
840 /* step 4: fix up any arguments */
842 /* if (err) return 4; */
848 * 'do_cmd' function for an 'INTERRUPT' subdevice.
850 static int dio200_subdev_intr_cmd(struct comedi_device *dev,
851 struct comedi_subdevice *s)
853 struct comedi_cmd *cmd = &s->async->cmd;
854 struct dio200_subdev_intr *subpriv = s->private;
858 spin_lock_irqsave(&subpriv->spinlock, flags);
861 /* Set up end of acquisition. */
862 switch (cmd->stop_src) {
864 subpriv->continuous = 0;
865 subpriv->stopcount = cmd->stop_arg;
869 subpriv->continuous = 1;
870 subpriv->stopcount = 0;
874 /* Set up start of acquisition. */
875 switch (cmd->start_src) {
877 s->async->inttrig = dio200_inttrig_start_intr;
881 event = dio200_start_intr(dev, s);
884 spin_unlock_irqrestore(&subpriv->spinlock, flags);
887 comedi_event(dev, s);
893 * This function initializes an 'INTERRUPT' subdevice.
896 dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
897 unsigned long iobase, unsigned valid_isns,
900 struct dio200_subdev_intr *subpriv;
902 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
904 dev_err(dev->class_dev, "error! out of memory!\n");
907 subpriv->iobase = iobase;
908 subpriv->has_int_sce = has_int_sce;
909 subpriv->valid_isns = valid_isns;
910 spin_lock_init(&subpriv->spinlock);
913 outb(0, subpriv->iobase); /* Disable interrupt sources. */
915 s->private = subpriv;
916 s->type = COMEDI_SUBD_DI;
917 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
919 s->n_chan = DIO200_MAX_ISNS;
920 s->len_chanlist = DIO200_MAX_ISNS;
922 /* No interrupt source register. Support single channel. */
926 s->range_table = &range_digital;
928 s->insn_bits = dio200_subdev_intr_insn_bits;
929 s->do_cmdtest = dio200_subdev_intr_cmdtest;
930 s->do_cmd = dio200_subdev_intr_cmd;
931 s->cancel = dio200_subdev_intr_cancel;
937 * This function cleans up an 'INTERRUPT' subdevice.
940 dio200_subdev_intr_cleanup(struct comedi_device *dev,
941 struct comedi_subdevice *s)
943 struct dio200_subdev_intr *subpriv = s->private;
948 * Interrupt service routine.
950 static irqreturn_t dio200_interrupt(int irq, void *d)
952 struct comedi_device *dev = d;
953 struct dio200_private *devpriv = dev->private;
954 struct comedi_subdevice *s;
960 if (devpriv->intr_sd >= 0) {
961 s = &dev->subdevices[devpriv->intr_sd];
962 handled = dio200_handle_read_intr(dev, s);
967 return IRQ_RETVAL(handled);
971 * Handle 'insn_read' for an '8254' counter subdevice.
974 dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
975 struct comedi_insn *insn, unsigned int *data)
977 struct dio200_subdev_8254 *subpriv = s->private;
978 int chan = CR_CHAN(insn->chanspec);
981 spin_lock_irqsave(&subpriv->spinlock, flags);
982 data[0] = i8254_read(subpriv->iobase, 0, chan);
983 spin_unlock_irqrestore(&subpriv->spinlock, flags);
989 * Handle 'insn_write' for an '8254' counter subdevice.
992 dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
993 struct comedi_insn *insn, unsigned int *data)
995 struct dio200_subdev_8254 *subpriv = s->private;
996 int chan = CR_CHAN(insn->chanspec);
999 spin_lock_irqsave(&subpriv->spinlock, flags);
1000 i8254_write(subpriv->iobase, 0, chan, data[0]);
1001 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1007 * Set gate source for an '8254' counter subdevice channel.
1010 dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1011 unsigned int counter_number, unsigned int gate_src)
1015 if (!subpriv->has_clk_gat_sce)
1017 if (counter_number > 2)
1022 subpriv->gate_src[counter_number] = gate_src;
1023 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1024 outb(byte, subpriv->gat_sce_iobase);
1030 * Get gate source for an '8254' counter subdevice channel.
1033 dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1034 unsigned int counter_number)
1036 if (!subpriv->has_clk_gat_sce)
1038 if (counter_number > 2)
1041 return subpriv->gate_src[counter_number];
1045 * Set clock source for an '8254' counter subdevice channel.
1048 dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1049 unsigned int counter_number, unsigned int clock_src)
1053 if (!subpriv->has_clk_gat_sce)
1055 if (counter_number > 2)
1060 subpriv->clock_src[counter_number] = clock_src;
1061 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1062 outb(byte, subpriv->clk_sce_iobase);
1068 * Get clock source for an '8254' counter subdevice channel.
1071 dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1072 unsigned int counter_number, unsigned int *period_ns)
1076 if (!subpriv->has_clk_gat_sce)
1078 if (counter_number > 2)
1081 clock_src = subpriv->clock_src[counter_number];
1082 *period_ns = clock_period[clock_src];
1087 * Handle 'insn_config' for an '8254' counter subdevice.
1090 dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1091 struct comedi_insn *insn, unsigned int *data)
1093 struct dio200_subdev_8254 *subpriv = s->private;
1095 int chan = CR_CHAN(insn->chanspec);
1096 unsigned long flags;
1098 spin_lock_irqsave(&subpriv->spinlock, flags);
1100 case INSN_CONFIG_SET_COUNTER_MODE:
1101 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1105 case INSN_CONFIG_8254_READ_STATUS:
1106 data[1] = i8254_status(subpriv->iobase, 0, chan);
1108 case INSN_CONFIG_SET_GATE_SRC:
1109 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1113 case INSN_CONFIG_GET_GATE_SRC:
1114 ret = dio200_get_gate_src(subpriv, chan);
1121 case INSN_CONFIG_SET_CLOCK_SRC:
1122 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1126 case INSN_CONFIG_GET_CLOCK_SRC:
1127 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1138 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1139 return ret < 0 ? ret : insn->n;
1143 * This function initializes an '8254' counter subdevice.
1145 * Note: iobase is the base address of the board, not the subdevice;
1146 * offset is the offset to the 8254 chip.
1149 dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1150 unsigned long iobase, unsigned offset,
1151 int has_clk_gat_sce)
1153 struct dio200_subdev_8254 *subpriv;
1156 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1158 dev_err(dev->class_dev, "error! out of memory!\n");
1162 s->private = subpriv;
1163 s->type = COMEDI_SUBD_COUNTER;
1164 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1166 s->maxdata = 0xFFFF;
1167 s->insn_read = dio200_subdev_8254_read;
1168 s->insn_write = dio200_subdev_8254_write;
1169 s->insn_config = dio200_subdev_8254_config;
1171 spin_lock_init(&subpriv->spinlock);
1172 subpriv->iobase = offset + iobase;
1173 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1174 if (has_clk_gat_sce) {
1175 /* Derive CLK_SCE and GAT_SCE register offsets from
1177 subpriv->clk_sce_iobase =
1178 DIO200_XCLK_SCE + (offset >> 3) + iobase;
1179 subpriv->gat_sce_iobase =
1180 DIO200_XGAT_SCE + (offset >> 3) + iobase;
1181 subpriv->which = (offset >> 2) & 1;
1184 /* Initialize channels. */
1185 for (chan = 0; chan < 3; chan++) {
1186 i8254_set_mode(subpriv->iobase, 0, chan,
1187 I8254_MODE0 | I8254_BINARY);
1188 if (subpriv->has_clk_gat_sce) {
1189 /* Gate source 0 is VCC (logic 1). */
1190 dio200_set_gate_src(subpriv, chan, 0);
1191 /* Clock source 0 is the dedicated clock input. */
1192 dio200_set_clock_src(subpriv, chan, 0);
1200 * This function cleans up an '8254' counter subdevice.
1203 dio200_subdev_8254_cleanup(struct comedi_device *dev,
1204 struct comedi_subdevice *s)
1206 struct dio200_subdev_intr *subpriv = s->private;
1210 static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
1212 const struct dio200_board *thisboard = comedi_board(dev);
1213 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1217 if (is_isa_board(thisboard))
1218 tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
1219 "(base %#lx) ", dev->iobase);
1220 else if (is_pci_board(thisboard))
1221 tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
1222 "(pci %s) ", pci_name(pcidev));
1226 tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
1228 (dev->irq ? "" : " UNAVAILABLE"));
1230 tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
1232 dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf);
1235 static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
1236 unsigned int irq, unsigned long req_irq_flags)
1238 const struct dio200_board *thisboard = comedi_board(dev);
1239 struct dio200_private *devpriv = dev->private;
1240 const struct dio200_layout_struct *layout =
1241 &dio200_layouts[thisboard->layout];
1242 struct comedi_subdevice *s;
1247 devpriv->intr_sd = -1;
1248 dev->iobase = iobase;
1249 dev->board_name = thisboard->name;
1251 ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
1255 for (n = 0; n < dev->n_subdevices; n++) {
1256 s = &dev->subdevices[n];
1257 switch (layout->sdtype[n]) {
1259 /* counter subdevice (8254) */
1260 ret = dio200_subdev_8254_init(dev, s, iobase,
1262 layout->has_clk_gat_sce);
1267 /* digital i/o subdevice (8255) */
1268 ret = subdev_8255_init(dev, s, NULL,
1269 iobase + layout->sdinfo[n]);
1274 /* 'INTERRUPT' subdevice */
1276 ret = dio200_subdev_intr_init(dev, s,
1284 devpriv->intr_sd = n;
1286 s->type = COMEDI_SUBD_UNUSED;
1290 s->type = COMEDI_SUBD_UNUSED;
1294 sdx = devpriv->intr_sd;
1295 if (sdx >= 0 && sdx < dev->n_subdevices)
1296 dev->read_subdev = &dev->subdevices[sdx];
1298 if (request_irq(irq, dio200_interrupt, req_irq_flags,
1299 DIO200_DRIVER_NAME, dev) >= 0) {
1302 dev_warn(dev->class_dev,
1303 "warning! irq %u unavailable!\n", irq);
1306 dio200_report_attach(dev, irq);
1310 static int dio200_pci_common_attach(struct comedi_device *dev,
1311 struct pci_dev *pci_dev)
1313 unsigned long iobase;
1316 comedi_set_hw_dev(dev, &pci_dev->dev);
1318 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1320 dev_err(dev->class_dev,
1321 "error! cannot enable PCI device and request regions!\n");
1324 iobase = pci_resource_start(pci_dev, 2);
1325 return dio200_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
1329 * Attach is called by the Comedi core to configure the driver
1330 * for a particular board. If you specified a board_name array
1331 * in the driver structure, dev->board_ptr contains that
1334 static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1336 const struct dio200_board *thisboard = comedi_board(dev);
1339 dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n");
1341 ret = alloc_private(dev, sizeof(struct dio200_private));
1343 dev_err(dev->class_dev, "error! out of memory!\n");
1347 /* Process options and reserve resources according to bus type. */
1348 if (is_isa_board(thisboard)) {
1349 unsigned long iobase;
1352 iobase = it->options[0];
1353 irq = it->options[1];
1354 ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE);
1357 return dio200_common_attach(dev, iobase, irq, 0);
1358 } else if (is_pci_board(thisboard)) {
1359 struct pci_dev *pci_dev;
1361 pci_dev = dio200_find_pci_dev(dev, it);
1364 return dio200_pci_common_attach(dev, pci_dev);
1366 dev_err(dev->class_dev, DIO200_DRIVER_NAME
1367 ": BUG! cannot determine board type!\n");
1373 * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
1374 * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should
1375 * be a board entry matching the supplied PCI device.
1377 static int __devinit dio200_attach_pci(struct comedi_device *dev,
1378 struct pci_dev *pci_dev)
1385 dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
1387 ret = alloc_private(dev, sizeof(struct dio200_private));
1389 dev_err(dev->class_dev, "error! out of memory!\n");
1392 dev->board_ptr = dio200_find_pci_board(pci_dev);
1393 if (dev->board_ptr == NULL) {
1394 dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
1398 * Need to 'get' the PCI device to match the 'put' in dio200_detach().
1399 * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
1400 * support for manual attachment of PCI devices via dio200_attach()
1403 pci_dev_get(pci_dev);
1404 return dio200_pci_common_attach(dev, pci_dev);
1407 static void dio200_detach(struct comedi_device *dev)
1409 const struct dio200_board *thisboard = comedi_board(dev);
1410 const struct dio200_layout_struct *layout;
1414 free_irq(dev->irq, dev);
1415 if (dev->subdevices) {
1416 layout = &dio200_layouts[thisboard->layout];
1417 for (n = 0; n < dev->n_subdevices; n++) {
1418 struct comedi_subdevice *s = &dev->subdevices[n];
1419 switch (layout->sdtype[n]) {
1421 dio200_subdev_8254_cleanup(dev, s);
1424 subdev_8255_cleanup(dev, s);
1427 dio200_subdev_intr_cleanup(dev, s);
1434 if (is_isa_board(thisboard)) {
1436 release_region(dev->iobase, DIO200_IO_SIZE);
1437 } else if (is_pci_board(thisboard)) {
1438 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1441 comedi_pci_disable(pcidev);
1442 pci_dev_put(pcidev);
1448 * The struct comedi_driver structure tells the Comedi core module
1449 * which functions to call to configure/deconfigure (attach/detach)
1450 * the board, and also about the kernel module that contains
1453 static struct comedi_driver amplc_dio200_driver = {
1454 .driver_name = DIO200_DRIVER_NAME,
1455 .module = THIS_MODULE,
1456 .attach = dio200_attach,
1457 .attach_pci = dio200_attach_pci,
1458 .detach = dio200_detach,
1459 .board_name = &dio200_boards[0].name,
1460 .offset = sizeof(struct dio200_board),
1461 .num_names = ARRAY_SIZE(dio200_boards),
1465 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
1466 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
1467 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
1471 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
1473 static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev,
1474 const struct pci_device_id
1477 return comedi_pci_auto_config(dev, &lc_dio200_driver);
1480 static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev)
1482 comedi_pci_auto_unconfig(dev);
1485 static struct pci_driver amplc_dio200_pci_driver = {
1486 .name = DIO200_DRIVER_NAME,
1487 .id_table = dio200_pci_table,
1488 .probe = &lc_dio200_pci_probe,
1489 .remove = __devexit_p(&lc_dio200_pci_remove)
1491 module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
1493 module_comedi_driver(amplc_dio200_driver);
1496 MODULE_AUTHOR("Comedi http://www.comedi.org");
1497 MODULE_DESCRIPTION("Comedi low-level driver");
1498 MODULE_LICENSE("GPL");