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"
216 #define DIO200_DRIVER_NAME "amplc_dio200"
219 #define PCI_VENDOR_ID_AMPLICON 0x14dc
220 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
221 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
222 #define PCI_DEVICE_ID_INVALID 0xffff
224 /* 200 series registers */
225 #define DIO200_IO_SIZE 0x20
226 #define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
227 #define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
228 #define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
229 #define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
230 #define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
231 #define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
232 #define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
235 * Macros for constructing value for DIO_200_?CLK_SCE and
236 * DIO_200_?GAT_SCE registers:
238 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
239 * 'chan' is the channel: 0, 1 or 2.
240 * 'source' is the signal source: 0 to 7.
242 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
243 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
246 * Periods of the internal clock sources in nanoseconds.
248 static const unsigned clock_period
[8] = {
249 0, /* dedicated clock input/output pin */
256 0 /* group clock input pin */
260 * Board descriptions.
263 enum dio200_bustype
{ isa_bustype
, pci_bustype
};
268 pc215e_model
, pci215_model
,
270 pc272e_model
, pci272_model
,
275 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
280 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
286 struct dio200_board
{
288 unsigned short devid
;
289 enum dio200_bustype bustype
;
290 enum dio200_model model
;
291 enum dio200_layout layout
;
294 static const struct dio200_board dio200_boards
[] = {
295 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
298 .bustype
= isa_bustype
,
299 .model
= pc212e_model
,
300 .layout
= pc212_layout
,
304 .bustype
= isa_bustype
,
305 .model
= pc214e_model
,
306 .layout
= pc214_layout
,
310 .bustype
= isa_bustype
,
311 .model
= pc215e_model
,
312 .layout
= pc215_layout
,
316 .bustype
= isa_bustype
,
317 .model
= pc218e_model
,
318 .layout
= pc218_layout
,
322 .bustype
= isa_bustype
,
323 .model
= pc272e_model
,
324 .layout
= pc272_layout
,
327 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
330 .devid
= PCI_DEVICE_ID_AMPLICON_PCI215
,
331 .bustype
= pci_bustype
,
332 .model
= pci215_model
,
333 .layout
= pc215_layout
,
337 .devid
= PCI_DEVICE_ID_AMPLICON_PCI272
,
338 .bustype
= pci_bustype
,
339 .model
= pci272_model
,
340 .layout
= pc272_layout
,
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
[] = {
370 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
373 .sdtype
= {sd_8255
, sd_8254
, sd_8254
, sd_8254
,
376 .sdinfo
= {0x00, 0x08, 0x0C, 0x10, 0x14,
379 .has_clk_gat_sce
= 1,
383 .sdtype
= {sd_8255
, sd_8255
, sd_8254
,
385 .sdinfo
= {0x00, 0x08, 0x10, 0x01},
387 .has_clk_gat_sce
= 0,
392 .sdtype
= {sd_8255
, sd_8255
, sd_8254
,
395 .sdinfo
= {0x00, 0x08, 0x10, 0x14, 0x3F},
397 .has_clk_gat_sce
= 1,
399 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
402 .sdtype
= {sd_8254
, sd_8254
, sd_8255
, sd_8254
,
405 .sdinfo
= {0x00, 0x04, 0x08, 0x0C, 0x10,
409 .has_clk_gat_sce
= 1,
414 .sdtype
= {sd_8255
, sd_8255
, sd_8255
,
416 .sdinfo
= {0x00, 0x08, 0x10, 0x3F},
418 .has_clk_gat_sce
= 0,
422 /* this structure is for data unique to this hardware driver. If
423 several hardware drivers keep similar information in this structure,
424 feel free to suggest moving the variable to the struct comedi_device struct.
426 struct dio200_private
{
427 struct pci_dev
*pci_dev
; /* PCI device */
431 struct dio200_subdev_8254
{
432 unsigned long iobase
; /* Counter base address */
433 unsigned long clk_sce_iobase
; /* CLK_SCE base address */
434 unsigned long gat_sce_iobase
; /* GAT_SCE base address */
435 int which
; /* Bit 5 of CLK_SCE or GAT_SCE */
437 unsigned clock_src
[3]; /* Current clock sources */
438 unsigned gate_src
[3]; /* Current gate sources */
442 struct dio200_subdev_intr
{
443 unsigned long iobase
;
447 unsigned int valid_isns
;
448 unsigned int enabled_isns
;
449 unsigned int stopcount
;
454 * This function looks for a board matching the supplied PCI device.
456 static const struct dio200_board
*
457 dio200_find_pci_board(struct pci_dev
*pci_dev
)
461 for (i
= 0; i
< ARRAY_SIZE(dio200_boards
); i
++)
462 if (dio200_boards
[i
].bustype
== pci_bustype
&&
463 pci_dev
->device
== dio200_boards
[i
].devid
)
464 return &dio200_boards
[i
];
469 * This function looks for a PCI device matching the requested board name,
472 static struct pci_dev
*
473 dio200_find_pci(struct comedi_device
*dev
, int bus
, int slot
)
475 const struct dio200_board
*thisboard
= comedi_board(dev
);
476 struct pci_dev
*pci_dev
= NULL
;
478 /* Look for matching PCI device. */
479 for (pci_dev
= pci_get_device(PCI_VENDOR_ID_AMPLICON
, PCI_ANY_ID
, NULL
);
481 pci_dev
= pci_get_device(PCI_VENDOR_ID_AMPLICON
,
482 PCI_ANY_ID
, pci_dev
)) {
483 /* If bus/slot specified, check them. */
485 if (bus
!= pci_dev
->bus
->number
486 || slot
!= PCI_SLOT(pci_dev
->devfn
))
489 if (thisboard
->model
== anypci_model
) {
490 /* Wildcard board matches any supported PCI board. */
491 const struct dio200_board
*foundboard
;
493 foundboard
= dio200_find_pci_board(pci_dev
);
494 if (foundboard
== NULL
)
496 /* Replace wildcard board_ptr. */
497 dev
->board_ptr
= foundboard
;
498 thisboard
= comedi_board(dev
);
500 /* Match specific model name. */
501 if (pci_dev
->device
!= thisboard
->devid
)
508 /* No match found. */
510 dev_err(dev
->class_dev
,
511 "error! no %s found at pci %02x:%02x!\n",
512 thisboard
->name
, bus
, slot
);
514 dev_err(dev
->class_dev
, "error! no %s found!\n",
521 * This function checks and requests an I/O region, reporting an error
522 * if there is a conflict.
525 dio200_request_region(struct comedi_device
*dev
,
526 unsigned long from
, unsigned long extent
)
528 if (!from
|| !request_region(from
, extent
, DIO200_DRIVER_NAME
)) {
529 dev_err(dev
->class_dev
, "I/O port conflict (%#lx,%lu)!\n",
537 * 'insn_bits' function for an 'INTERRUPT' subdevice.
540 dio200_subdev_intr_insn_bits(struct comedi_device
*dev
,
541 struct comedi_subdevice
*s
,
542 struct comedi_insn
*insn
, unsigned int *data
)
544 struct dio200_subdev_intr
*subpriv
= s
->private;
546 if (subpriv
->has_int_sce
) {
547 /* Just read the interrupt status register. */
548 data
[1] = inb(subpriv
->iobase
) & subpriv
->valid_isns
;
550 /* No interrupt status register. */
558 * Called to stop acquisition for an 'INTERRUPT' subdevice.
560 static void dio200_stop_intr(struct comedi_device
*dev
,
561 struct comedi_subdevice
*s
)
563 struct dio200_subdev_intr
*subpriv
= s
->private;
566 subpriv
->enabled_isns
= 0;
567 if (subpriv
->has_int_sce
)
568 outb(0, subpriv
->iobase
);
572 * Called to start acquisition for an 'INTERRUPT' subdevice.
574 static int dio200_start_intr(struct comedi_device
*dev
,
575 struct comedi_subdevice
*s
)
579 struct dio200_subdev_intr
*subpriv
= s
->private;
580 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
583 if (!subpriv
->continuous
&& subpriv
->stopcount
== 0) {
584 /* An empty acquisition! */
585 s
->async
->events
|= COMEDI_CB_EOA
;
589 /* Determine interrupt sources to enable. */
592 for (n
= 0; n
< cmd
->chanlist_len
; n
++)
593 isn_bits
|= (1U << CR_CHAN(cmd
->chanlist
[n
]));
595 isn_bits
&= subpriv
->valid_isns
;
596 /* Enable interrupt sources. */
597 subpriv
->enabled_isns
= isn_bits
;
598 if (subpriv
->has_int_sce
)
599 outb(isn_bits
, subpriv
->iobase
);
606 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
609 dio200_inttrig_start_intr(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
610 unsigned int trignum
)
612 struct dio200_subdev_intr
*subpriv
;
619 subpriv
= s
->private;
621 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
622 s
->async
->inttrig
= NULL
;
624 event
= dio200_start_intr(dev
, s
);
626 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
629 comedi_event(dev
, s
);
635 * This is called from the interrupt service routine to handle a read
636 * scan on an 'INTERRUPT' subdevice.
638 static int dio200_handle_read_intr(struct comedi_device
*dev
,
639 struct comedi_subdevice
*s
)
641 struct dio200_subdev_intr
*subpriv
= s
->private;
644 unsigned cur_enabled
;
645 unsigned int oldevents
;
650 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
651 oldevents
= s
->async
->events
;
652 if (subpriv
->has_int_sce
) {
654 * Collect interrupt sources that have triggered and disable
655 * them temporarily. Loop around until no extra interrupt
656 * sources have triggered, at which point, the valid part of
657 * the interrupt status register will read zero, clearing the
658 * cause of the interrupt.
660 * Mask off interrupt sources already seen to avoid infinite
661 * loop in case of misconfiguration.
663 cur_enabled
= subpriv
->enabled_isns
;
664 while ((intstat
= (inb(subpriv
->iobase
) & subpriv
->valid_isns
665 & ~triggered
)) != 0) {
666 triggered
|= intstat
;
667 cur_enabled
&= ~triggered
;
668 outb(cur_enabled
, subpriv
->iobase
);
672 * No interrupt status register. Assume the single interrupt
673 * source has triggered.
675 triggered
= subpriv
->enabled_isns
;
680 * Some interrupt sources have triggered and have been
681 * temporarily disabled to clear the cause of the interrupt.
683 * Reenable them NOW to minimize the time they are disabled.
685 cur_enabled
= subpriv
->enabled_isns
;
686 if (subpriv
->has_int_sce
)
687 outb(cur_enabled
, subpriv
->iobase
);
689 if (subpriv
->active
) {
691 * The command is still active.
693 * Ignore interrupt sources that the command isn't
694 * interested in (just in case there's a race
697 if (triggered
& subpriv
->enabled_isns
) {
698 /* Collect scan data. */
700 unsigned int n
, ch
, len
;
703 len
= s
->async
->cmd
.chanlist_len
;
704 for (n
= 0; n
< len
; n
++) {
705 ch
= CR_CHAN(s
->async
->cmd
.chanlist
[n
]);
706 if (triggered
& (1U << ch
))
709 /* Write the scan to the buffer. */
710 if (comedi_buf_put(s
->async
, val
)) {
711 s
->async
->events
|= (COMEDI_CB_BLOCK
|
714 /* Error! Stop acquisition. */
715 dio200_stop_intr(dev
, s
);
716 s
->async
->events
|= COMEDI_CB_ERROR
717 | COMEDI_CB_OVERFLOW
;
718 comedi_error(dev
, "buffer overflow");
721 /* Check for end of acquisition. */
722 if (!subpriv
->continuous
) {
723 /* stop_src == TRIG_COUNT */
724 if (subpriv
->stopcount
> 0) {
725 subpriv
->stopcount
--;
726 if (subpriv
->stopcount
== 0) {
729 dio200_stop_intr(dev
,
737 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
739 if (oldevents
!= s
->async
->events
)
740 comedi_event(dev
, s
);
742 return (triggered
!= 0);
746 * 'cancel' function for an 'INTERRUPT' subdevice.
748 static int dio200_subdev_intr_cancel(struct comedi_device
*dev
,
749 struct comedi_subdevice
*s
)
751 struct dio200_subdev_intr
*subpriv
= s
->private;
754 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
756 dio200_stop_intr(dev
, s
);
758 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
764 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
767 dio200_subdev_intr_cmdtest(struct comedi_device
*dev
,
768 struct comedi_subdevice
*s
, struct comedi_cmd
*cmd
)
773 /* step 1: make sure trigger sources are trivially valid */
775 tmp
= cmd
->start_src
;
776 cmd
->start_src
&= (TRIG_NOW
| TRIG_INT
);
777 if (!cmd
->start_src
|| tmp
!= cmd
->start_src
)
780 tmp
= cmd
->scan_begin_src
;
781 cmd
->scan_begin_src
&= TRIG_EXT
;
782 if (!cmd
->scan_begin_src
|| tmp
!= cmd
->scan_begin_src
)
785 tmp
= cmd
->convert_src
;
786 cmd
->convert_src
&= TRIG_NOW
;
787 if (!cmd
->convert_src
|| tmp
!= cmd
->convert_src
)
790 tmp
= cmd
->scan_end_src
;
791 cmd
->scan_end_src
&= TRIG_COUNT
;
792 if (!cmd
->scan_end_src
|| tmp
!= cmd
->scan_end_src
)
796 cmd
->stop_src
&= (TRIG_COUNT
| TRIG_NONE
);
797 if (!cmd
->stop_src
|| tmp
!= cmd
->stop_src
)
803 /* step 2: make sure trigger sources are unique and mutually
806 /* these tests are true if more than one _src bit is set */
807 if ((cmd
->start_src
& (cmd
->start_src
- 1)) != 0)
809 if ((cmd
->scan_begin_src
& (cmd
->scan_begin_src
- 1)) != 0)
811 if ((cmd
->convert_src
& (cmd
->convert_src
- 1)) != 0)
813 if ((cmd
->scan_end_src
& (cmd
->scan_end_src
- 1)) != 0)
815 if ((cmd
->stop_src
& (cmd
->stop_src
- 1)) != 0)
821 /* step 3: make sure arguments are trivially compatible */
823 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
824 if (cmd
->start_arg
!= 0) {
829 /* cmd->scan_begin_src == TRIG_EXT */
830 if (cmd
->scan_begin_arg
!= 0) {
831 cmd
->scan_begin_arg
= 0;
835 /* cmd->convert_src == TRIG_NOW */
836 if (cmd
->convert_arg
!= 0) {
837 cmd
->convert_arg
= 0;
841 /* cmd->scan_end_src == TRIG_COUNT */
842 if (cmd
->scan_end_arg
!= cmd
->chanlist_len
) {
843 cmd
->scan_end_arg
= cmd
->chanlist_len
;
847 switch (cmd
->stop_src
) {
849 /* any count allowed */
852 if (cmd
->stop_arg
!= 0) {
864 /* step 4: fix up any arguments */
866 /* if (err) return 4; */
872 * 'do_cmd' function for an 'INTERRUPT' subdevice.
874 static int dio200_subdev_intr_cmd(struct comedi_device
*dev
,
875 struct comedi_subdevice
*s
)
877 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
878 struct dio200_subdev_intr
*subpriv
= s
->private;
882 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
885 /* Set up end of acquisition. */
886 switch (cmd
->stop_src
) {
888 subpriv
->continuous
= 0;
889 subpriv
->stopcount
= cmd
->stop_arg
;
893 subpriv
->continuous
= 1;
894 subpriv
->stopcount
= 0;
898 /* Set up start of acquisition. */
899 switch (cmd
->start_src
) {
901 s
->async
->inttrig
= dio200_inttrig_start_intr
;
905 event
= dio200_start_intr(dev
, s
);
908 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
911 comedi_event(dev
, s
);
917 * This function initializes an 'INTERRUPT' subdevice.
920 dio200_subdev_intr_init(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
921 unsigned long iobase
, unsigned valid_isns
,
924 struct dio200_subdev_intr
*subpriv
;
926 subpriv
= kzalloc(sizeof(*subpriv
), GFP_KERNEL
);
928 dev_err(dev
->class_dev
, "error! out of memory!\n");
931 subpriv
->iobase
= iobase
;
932 subpriv
->has_int_sce
= has_int_sce
;
933 subpriv
->valid_isns
= valid_isns
;
934 spin_lock_init(&subpriv
->spinlock
);
937 outb(0, subpriv
->iobase
); /* Disable interrupt sources. */
939 s
->private = subpriv
;
940 s
->type
= COMEDI_SUBD_DI
;
941 s
->subdev_flags
= SDF_READABLE
| SDF_CMD_READ
;
943 s
->n_chan
= DIO200_MAX_ISNS
;
944 s
->len_chanlist
= DIO200_MAX_ISNS
;
946 /* No interrupt source register. Support single channel. */
950 s
->range_table
= &range_digital
;
952 s
->insn_bits
= dio200_subdev_intr_insn_bits
;
953 s
->do_cmdtest
= dio200_subdev_intr_cmdtest
;
954 s
->do_cmd
= dio200_subdev_intr_cmd
;
955 s
->cancel
= dio200_subdev_intr_cancel
;
961 * This function cleans up an 'INTERRUPT' subdevice.
964 dio200_subdev_intr_cleanup(struct comedi_device
*dev
,
965 struct comedi_subdevice
*s
)
967 struct dio200_subdev_intr
*subpriv
= s
->private;
972 * Interrupt service routine.
974 static irqreturn_t
dio200_interrupt(int irq
, void *d
)
976 struct comedi_device
*dev
= d
;
977 struct dio200_private
*devpriv
= dev
->private;
983 if (devpriv
->intr_sd
>= 0) {
984 handled
= dio200_handle_read_intr(dev
,
991 return IRQ_RETVAL(handled
);
995 * Handle 'insn_read' for an '8254' counter subdevice.
998 dio200_subdev_8254_read(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
999 struct comedi_insn
*insn
, unsigned int *data
)
1001 struct dio200_subdev_8254
*subpriv
= s
->private;
1002 int chan
= CR_CHAN(insn
->chanspec
);
1003 unsigned long flags
;
1005 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
1006 data
[0] = i8254_read(subpriv
->iobase
, 0, chan
);
1007 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
1013 * Handle 'insn_write' for an '8254' counter subdevice.
1016 dio200_subdev_8254_write(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
1017 struct comedi_insn
*insn
, unsigned int *data
)
1019 struct dio200_subdev_8254
*subpriv
= s
->private;
1020 int chan
= CR_CHAN(insn
->chanspec
);
1021 unsigned long flags
;
1023 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
1024 i8254_write(subpriv
->iobase
, 0, chan
, data
[0]);
1025 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
1031 * Set gate source for an '8254' counter subdevice channel.
1034 dio200_set_gate_src(struct dio200_subdev_8254
*subpriv
,
1035 unsigned int counter_number
, unsigned int gate_src
)
1039 if (!subpriv
->has_clk_gat_sce
)
1041 if (counter_number
> 2)
1046 subpriv
->gate_src
[counter_number
] = gate_src
;
1047 byte
= GAT_SCE(subpriv
->which
, counter_number
, gate_src
);
1048 outb(byte
, subpriv
->gat_sce_iobase
);
1054 * Get gate source for an '8254' counter subdevice channel.
1057 dio200_get_gate_src(struct dio200_subdev_8254
*subpriv
,
1058 unsigned int counter_number
)
1060 if (!subpriv
->has_clk_gat_sce
)
1062 if (counter_number
> 2)
1065 return subpriv
->gate_src
[counter_number
];
1069 * Set clock source for an '8254' counter subdevice channel.
1072 dio200_set_clock_src(struct dio200_subdev_8254
*subpriv
,
1073 unsigned int counter_number
, unsigned int clock_src
)
1077 if (!subpriv
->has_clk_gat_sce
)
1079 if (counter_number
> 2)
1084 subpriv
->clock_src
[counter_number
] = clock_src
;
1085 byte
= CLK_SCE(subpriv
->which
, counter_number
, clock_src
);
1086 outb(byte
, subpriv
->clk_sce_iobase
);
1092 * Get clock source for an '8254' counter subdevice channel.
1095 dio200_get_clock_src(struct dio200_subdev_8254
*subpriv
,
1096 unsigned int counter_number
, unsigned int *period_ns
)
1100 if (!subpriv
->has_clk_gat_sce
)
1102 if (counter_number
> 2)
1105 clock_src
= subpriv
->clock_src
[counter_number
];
1106 *period_ns
= clock_period
[clock_src
];
1111 * Handle 'insn_config' for an '8254' counter subdevice.
1114 dio200_subdev_8254_config(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
1115 struct comedi_insn
*insn
, unsigned int *data
)
1117 struct dio200_subdev_8254
*subpriv
= s
->private;
1119 int chan
= CR_CHAN(insn
->chanspec
);
1120 unsigned long flags
;
1122 spin_lock_irqsave(&subpriv
->spinlock
, flags
);
1124 case INSN_CONFIG_SET_COUNTER_MODE
:
1125 ret
= i8254_set_mode(subpriv
->iobase
, 0, chan
, data
[1]);
1129 case INSN_CONFIG_8254_READ_STATUS
:
1130 data
[1] = i8254_status(subpriv
->iobase
, 0, chan
);
1132 case INSN_CONFIG_SET_GATE_SRC
:
1133 ret
= dio200_set_gate_src(subpriv
, chan
, data
[2]);
1137 case INSN_CONFIG_GET_GATE_SRC
:
1138 ret
= dio200_get_gate_src(subpriv
, chan
);
1145 case INSN_CONFIG_SET_CLOCK_SRC
:
1146 ret
= dio200_set_clock_src(subpriv
, chan
, data
[1]);
1150 case INSN_CONFIG_GET_CLOCK_SRC
:
1151 ret
= dio200_get_clock_src(subpriv
, chan
, &data
[2]);
1162 spin_unlock_irqrestore(&subpriv
->spinlock
, flags
);
1163 return ret
< 0 ? ret
: insn
->n
;
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(struct comedi_device
*dev
, struct comedi_subdevice
*s
,
1174 unsigned long iobase
, unsigned offset
,
1175 int has_clk_gat_sce
)
1177 struct dio200_subdev_8254
*subpriv
;
1180 subpriv
= kzalloc(sizeof(*subpriv
), GFP_KERNEL
);
1182 dev_err(dev
->class_dev
, "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 spin_lock_init(&subpriv
->spinlock
);
1196 subpriv
->iobase
= offset
+ iobase
;
1197 subpriv
->has_clk_gat_sce
= has_clk_gat_sce
;
1198 if (has_clk_gat_sce
) {
1199 /* Derive CLK_SCE and GAT_SCE register offsets from
1201 subpriv
->clk_sce_iobase
=
1202 DIO200_XCLK_SCE
+ (offset
>> 3) + iobase
;
1203 subpriv
->gat_sce_iobase
=
1204 DIO200_XGAT_SCE
+ (offset
>> 3) + iobase
;
1205 subpriv
->which
= (offset
>> 2) & 1;
1208 /* Initialize channels. */
1209 for (chan
= 0; chan
< 3; chan
++) {
1210 i8254_set_mode(subpriv
->iobase
, 0, chan
,
1211 I8254_MODE0
| I8254_BINARY
);
1212 if (subpriv
->has_clk_gat_sce
) {
1213 /* Gate source 0 is VCC (logic 1). */
1214 dio200_set_gate_src(subpriv
, chan
, 0);
1215 /* Clock source 0 is the dedicated clock input. */
1216 dio200_set_clock_src(subpriv
, chan
, 0);
1224 * This function cleans up an '8254' counter subdevice.
1227 dio200_subdev_8254_cleanup(struct comedi_device
*dev
,
1228 struct comedi_subdevice
*s
)
1230 struct dio200_subdev_intr
*subpriv
= s
->private;
1234 static void dio200_report_attach(struct comedi_device
*dev
, unsigned int irq
)
1236 const struct dio200_board
*thisboard
= comedi_board(dev
);
1237 struct dio200_private
*devpriv
= dev
->private;
1241 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA
) &&
1242 thisboard
->bustype
== isa_bustype
)
1243 tmplen
= scnprintf(tmpbuf
, sizeof(tmpbuf
),
1244 "(base %#lx) ", dev
->iobase
);
1245 else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI
) &&
1246 thisboard
->bustype
== pci_bustype
)
1247 tmplen
= scnprintf(tmpbuf
, sizeof(tmpbuf
),
1248 "(pci %s) ", pci_name(devpriv
->pci_dev
));
1252 tmplen
+= scnprintf(&tmpbuf
[tmplen
], sizeof(tmpbuf
) - tmplen
,
1254 (dev
->irq
? "" : " UNAVAILABLE"));
1256 tmplen
+= scnprintf(&tmpbuf
[tmplen
], sizeof(tmpbuf
) - tmplen
,
1258 dev_info(dev
->class_dev
, "%s %sattached\n", dev
->board_name
, tmpbuf
);
1261 static int dio200_common_attach(struct comedi_device
*dev
, unsigned long iobase
,
1262 unsigned int irq
, unsigned long req_irq_flags
)
1264 const struct dio200_board
*thisboard
= comedi_board(dev
);
1265 struct dio200_private
*devpriv
= dev
->private;
1266 const struct dio200_layout_struct
*layout
=
1267 &dio200_layouts
[thisboard
->layout
];
1268 struct comedi_subdevice
*s
;
1273 devpriv
->intr_sd
= -1;
1274 dev
->iobase
= iobase
;
1275 dev
->board_name
= thisboard
->name
;
1277 ret
= comedi_alloc_subdevices(dev
, layout
->n_subdevs
);
1281 for (n
= 0; n
< dev
->n_subdevices
; n
++) {
1282 s
= &dev
->subdevices
[n
];
1283 switch (layout
->sdtype
[n
]) {
1285 /* counter subdevice (8254) */
1286 ret
= dio200_subdev_8254_init(dev
, s
, iobase
,
1288 layout
->has_clk_gat_sce
);
1293 /* digital i/o subdevice (8255) */
1294 ret
= subdev_8255_init(dev
, s
, NULL
,
1295 iobase
+ layout
->sdinfo
[n
]);
1300 /* 'INTERRUPT' subdevice */
1302 ret
= dio200_subdev_intr_init(dev
, s
,
1310 devpriv
->intr_sd
= n
;
1312 s
->type
= COMEDI_SUBD_UNUSED
;
1316 s
->type
= COMEDI_SUBD_UNUSED
;
1320 sdx
= devpriv
->intr_sd
;
1321 if (sdx
>= 0 && sdx
< dev
->n_subdevices
)
1322 dev
->read_subdev
= &dev
->subdevices
[sdx
];
1324 if (request_irq(irq
, dio200_interrupt
, req_irq_flags
,
1325 DIO200_DRIVER_NAME
, dev
) >= 0) {
1328 dev_warn(dev
->class_dev
,
1329 "warning! irq %u unavailable!\n", irq
);
1332 dio200_report_attach(dev
, irq
);
1336 static int dio200_pci_common_attach(struct comedi_device
*dev
,
1337 struct pci_dev
*pci_dev
)
1339 struct dio200_private
*devpriv
= dev
->private;
1340 unsigned long iobase
;
1343 devpriv
->pci_dev
= pci_dev
;
1344 ret
= comedi_pci_enable(pci_dev
, DIO200_DRIVER_NAME
);
1346 dev_err(dev
->class_dev
,
1347 "error! cannot enable PCI device and request regions!\n");
1350 iobase
= pci_resource_start(pci_dev
, 2);
1351 return dio200_common_attach(dev
, iobase
, pci_dev
->irq
, IRQF_SHARED
);
1355 * Attach is called by the Comedi core to configure the driver
1356 * for a particular board. If you specified a board_name array
1357 * in the driver structure, dev->board_ptr contains that
1360 static int dio200_attach(struct comedi_device
*dev
, struct comedi_devconfig
*it
)
1362 const struct dio200_board
*thisboard
= comedi_board(dev
);
1365 dev_info(dev
->class_dev
, DIO200_DRIVER_NAME
": attach\n");
1367 ret
= alloc_private(dev
, sizeof(struct dio200_private
));
1369 dev_err(dev
->class_dev
, "error! out of memory!\n");
1373 /* Process options and reserve resources according to bus type. */
1374 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA
) &&
1375 thisboard
->bustype
== isa_bustype
) {
1376 unsigned long iobase
;
1379 iobase
= it
->options
[0];
1380 irq
= it
->options
[1];
1381 ret
= dio200_request_region(dev
, iobase
, DIO200_IO_SIZE
);
1384 return dio200_common_attach(dev
, iobase
, irq
, 0);
1385 } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI
) &&
1386 thisboard
->bustype
== pci_bustype
) {
1387 struct pci_dev
*pci_dev
;
1390 bus
= it
->options
[0];
1391 slot
= it
->options
[1];
1392 pci_dev
= dio200_find_pci(dev
, bus
, slot
);
1393 if (pci_dev
== NULL
)
1395 return dio200_pci_common_attach(dev
, pci_dev
);
1397 dev_err(dev
->class_dev
, DIO200_DRIVER_NAME
1398 ": BUG! cannot determine board type!\n");
1404 * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
1405 * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should
1406 * be a board entry matching the supplied PCI device.
1408 static int __devinit
dio200_attach_pci(struct comedi_device
*dev
,
1409 struct pci_dev
*pci_dev
)
1413 if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI
))
1416 dev_info(dev
->class_dev
, DIO200_DRIVER_NAME
": attach pci %s\n",
1418 ret
= alloc_private(dev
, sizeof(struct dio200_private
));
1420 dev_err(dev
->class_dev
, "error! out of memory!\n");
1423 dev
->board_ptr
= dio200_find_pci_board(pci_dev
);
1424 if (dev
->board_ptr
== NULL
) {
1425 dev_err(dev
->class_dev
, "BUG! cannot determine board type!\n");
1428 return dio200_pci_common_attach(dev
, pci_dev
);
1431 static void dio200_detach(struct comedi_device
*dev
)
1433 const struct dio200_board
*thisboard
= comedi_board(dev
);
1434 struct dio200_private
*devpriv
= dev
->private;
1435 const struct dio200_layout_struct
*layout
;
1439 free_irq(dev
->irq
, dev
);
1440 if (dev
->subdevices
) {
1441 layout
= &dio200_layouts
[thisboard
->layout
];
1442 for (n
= 0; n
< dev
->n_subdevices
; n
++) {
1443 struct comedi_subdevice
*s
= &dev
->subdevices
[n
];
1444 switch (layout
->sdtype
[n
]) {
1446 dio200_subdev_8254_cleanup(dev
, s
);
1449 subdev_8255_cleanup(dev
, s
);
1452 dio200_subdev_intr_cleanup(dev
, s
);
1460 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI
) &&
1461 thisboard
->bustype
== pci_bustype
) {
1462 if (devpriv
->pci_dev
) {
1464 comedi_pci_disable(devpriv
->pci_dev
);
1465 pci_dev_put(devpriv
->pci_dev
);
1467 } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA
) &&
1468 thisboard
->bustype
== isa_bustype
) {
1470 release_region(dev
->iobase
, DIO200_IO_SIZE
);
1476 * The struct comedi_driver structure tells the Comedi core module
1477 * which functions to call to configure/deconfigure (attach/detach)
1478 * the board, and also about the kernel module that contains
1481 static struct comedi_driver amplc_dio200_driver
= {
1482 .driver_name
= DIO200_DRIVER_NAME
,
1483 .module
= THIS_MODULE
,
1484 .attach
= dio200_attach
,
1485 .attach_pci
= dio200_attach_pci
,
1486 .detach
= dio200_detach
,
1487 .board_name
= &dio200_boards
[0].name
,
1488 .offset
= sizeof(struct dio200_board
),
1489 .num_names
= ARRAY_SIZE(dio200_boards
),
1492 #if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
1493 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table
) = {
1494 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON
, PCI_DEVICE_ID_AMPLICON_PCI215
) },
1495 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON
, PCI_DEVICE_ID_AMPLICON_PCI272
) },
1499 MODULE_DEVICE_TABLE(pci
, dio200_pci_table
);
1501 static int __devinit
amplc_dio200_pci_probe(struct pci_dev
*dev
,
1502 const struct pci_device_id
1505 return comedi_pci_auto_config(dev
, &lc_dio200_driver
);
1508 static void __devexit
amplc_dio200_pci_remove(struct pci_dev
*dev
)
1510 comedi_pci_auto_unconfig(dev
);
1513 static struct pci_driver amplc_dio200_pci_driver
= {
1514 .name
= DIO200_DRIVER_NAME
,
1515 .id_table
= dio200_pci_table
,
1516 .probe
= &lc_dio200_pci_probe
,
1517 .remove
= __devexit_p(&lc_dio200_pci_remove
)
1519 module_comedi_pci_driver(amplc_dio200_driver
, amplc_dio200_pci_driver
);
1521 module_comedi_driver(amplc_dio200_driver
);
1524 MODULE_AUTHOR("Comedi http://www.comedi.org");
1525 MODULE_DESCRIPTION("Comedi low-level driver");
1526 MODULE_LICENSE("GPL");