2323 *
2424 * Configuration Options:
2525 * [0] - I/O port base address
26+ * [1] - IRQ (optional)
27+ *
28+ * The board supports interrupts on change of state of the digital inputs.
29+ * The sample data returned by the async command indicates which inputs
30+ * changed state:
31+ *
32+ * Bit 7 - IRQ Enable (1) / Disable (0)
33+ * Bit 1 - Input 8-15 Changed State (1 = Changed, 0 = No Change)
34+ * Bit 0 - Input 0-7 Changed State (1 = Changed, 0 = No Change)
2635 */
2736
2837#include <linux/module.h>
38+ #include <linux/interrupt.h>
39+
2940#include "../comedidev.h"
3041
31- #define AIO_IIRO_16_RELAY_0_7 0x00
32- #define AIO_IIRO_16_INPUT_0_7 0x01
33- #define AIO_IIRO_16_IRQ 0x02
34- #define AIO_IIRO_16_RELAY_8_15 0x04
35- #define AIO_IIRO_16_INPUT_8_15 0x05
42+ #include "comedi_fc.h"
43+
44+ #define AIO_IIRO_16_RELAY_0_7 0x00
45+ #define AIO_IIRO_16_INPUT_0_7 0x01
46+ #define AIO_IIRO_16_IRQ 0x02
47+ #define AIO_IIRO_16_RELAY_8_15 0x04
48+ #define AIO_IIRO_16_INPUT_8_15 0x05
49+ #define AIO_IIRO_16_STATUS 0x07
50+ #define AIO_IIRO_16_STATUS_IRQE BIT(7)
51+ #define AIO_IIRO_16_STATUS_INPUT_8_15 BIT(1)
52+ #define AIO_IIRO_16_STATUS_INPUT_0_7 BIT(0)
53+
54+ static irqreturn_t aio_iiro_16_cos (int irq , void * d )
55+ {
56+ struct comedi_device * dev = d ;
57+ struct comedi_subdevice * s = dev -> read_subdev ;
58+ unsigned int status ;
59+
60+ status = inb (dev -> iobase + AIO_IIRO_16_STATUS );
61+ if (!(status & AIO_IIRO_16_STATUS_IRQE ))
62+ return IRQ_NONE ;
63+
64+ comedi_buf_write_samples (s , & status , 1 );
65+ comedi_handle_events (dev , s );
66+
67+ return IRQ_HANDLED ;
68+ }
3669
3770static void aio_iiro_enable_irq (struct comedi_device * dev , bool enable )
3871{
@@ -42,6 +75,60 @@ static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable)
4275 outb (0 , dev -> iobase + AIO_IIRO_16_IRQ );
4376}
4477
78+ static int aio_iiro_16_cos_cancel (struct comedi_device * dev ,
79+ struct comedi_subdevice * s )
80+ {
81+ aio_iiro_enable_irq (dev , false);
82+
83+ return 0 ;
84+ }
85+
86+ static int aio_iiro_16_cos_cmd (struct comedi_device * dev ,
87+ struct comedi_subdevice * s )
88+ {
89+ aio_iiro_enable_irq (dev , true);
90+
91+ return 0 ;
92+ }
93+
94+ static int aio_iiro_16_cos_cmdtest (struct comedi_device * dev ,
95+ struct comedi_subdevice * s ,
96+ struct comedi_cmd * cmd )
97+ {
98+ int err = 0 ;
99+
100+ /* Step 1 : check if triggers are trivially valid */
101+
102+ err |= cfc_check_trigger_src (& cmd -> start_src , TRIG_NOW );
103+ err |= cfc_check_trigger_src (& cmd -> scan_begin_src , TRIG_EXT );
104+ err |= cfc_check_trigger_src (& cmd -> convert_src , TRIG_FOLLOW );
105+ err |= cfc_check_trigger_src (& cmd -> scan_end_src , TRIG_COUNT );
106+ err |= cfc_check_trigger_src (& cmd -> stop_src , TRIG_NONE );
107+
108+ if (err )
109+ return 1 ;
110+
111+ /* Step 2a : make sure trigger sources are unique */
112+ /* Step 2b : and mutually compatible */
113+
114+ /* Step 3: check if arguments are trivially valid */
115+
116+ err |= cfc_check_trigger_arg_is (& cmd -> start_arg , 0 );
117+ err |= cfc_check_trigger_arg_is (& cmd -> scan_begin_arg , 0 );
118+ err |= cfc_check_trigger_arg_is (& cmd -> convert_arg , 0 );
119+ err |= cfc_check_trigger_arg_is (& cmd -> scan_end_arg , cmd -> chanlist_len );
120+ err |= cfc_check_trigger_arg_is (& cmd -> stop_arg , 0 );
121+
122+ if (err )
123+ return 3 ;
124+
125+ /* Step 4: fix up any arguments */
126+
127+ /* Step 5: check channel list if it exists */
128+
129+ return 0 ;
130+ }
131+
45132static int aio_iiro_16_do_insn_bits (struct comedi_device * dev ,
46133 struct comedi_subdevice * s ,
47134 struct comedi_insn * insn ,
@@ -82,6 +169,17 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
82169
83170 aio_iiro_enable_irq (dev , false);
84171
172+ /*
173+ * Digital input change of state interrupts are optionally supported
174+ * using IRQ 2-7, 10-12, 14, or 15.
175+ */
176+ if ((1 << it -> options [1 ]) & 0xdcfc ) {
177+ ret = request_irq (it -> options [1 ], aio_iiro_16_cos , 0 ,
178+ dev -> board_name , dev );
179+ if (ret == 0 )
180+ dev -> irq = it -> options [1 ];
181+ }
182+
85183 ret = comedi_alloc_subdevices (dev , 2 );
86184 if (ret )
87185 return ret ;
@@ -107,6 +205,14 @@ static int aio_iiro_16_attach(struct comedi_device *dev,
107205 s -> maxdata = 1 ;
108206 s -> range_table = & range_digital ;
109207 s -> insn_bits = aio_iiro_16_di_insn_bits ;
208+ if (dev -> irq ) {
209+ dev -> read_subdev = s ;
210+ s -> subdev_flags |= SDF_CMD_READ ;
211+ s -> len_chanlist = 1 ;
212+ s -> do_cmdtest = aio_iiro_16_cos_cmdtest ;
213+ s -> do_cmd = aio_iiro_16_cos_cmd ;
214+ s -> cancel = aio_iiro_16_cos_cancel ;
215+ }
110216
111217 return 0 ;
112218}
0 commit comments