This source file includes following definitions.
- apci1032_reset
- apci1032_cos_insn_config
- apci1032_cos_insn_bits
- apci1032_cos_cmdtest
- apci1032_cos_cmd
- apci1032_cos_cancel
- apci1032_interrupt
- apci1032_di_insn_bits
- apci1032_auto_attach
- apci1032_detach
- apci1032_pci_probe
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64 #include <linux/module.h>
65 #include <linux/interrupt.h>
66
67 #include "../comedi_pci.h"
68 #include "amcc_s5933.h"
69
70
71
72
73 #define APCI1032_DI_REG 0x00
74 #define APCI1032_MODE1_REG 0x04
75 #define APCI1032_MODE2_REG 0x08
76 #define APCI1032_STATUS_REG 0x0c
77 #define APCI1032_CTRL_REG 0x10
78 #define APCI1032_CTRL_INT_MODE(x) (((x) & 0x1) << 1)
79 #define APCI1032_CTRL_INT_OR APCI1032_CTRL_INT_MODE(0)
80 #define APCI1032_CTRL_INT_AND APCI1032_CTRL_INT_MODE(1)
81 #define APCI1032_CTRL_INT_ENA BIT(2)
82
83 struct apci1032_private {
84 unsigned long amcc_iobase;
85 unsigned int mode1;
86 unsigned int mode2;
87 unsigned int ctrl;
88 };
89
90 static int apci1032_reset(struct comedi_device *dev)
91 {
92
93 outl(0x0, dev->iobase + APCI1032_CTRL_REG);
94
95 inl(dev->iobase + APCI1032_STATUS_REG);
96
97 outl(0x0, dev->iobase + APCI1032_MODE1_REG);
98 outl(0x0, dev->iobase + APCI1032_MODE2_REG);
99
100 return 0;
101 }
102
103 static int apci1032_cos_insn_config(struct comedi_device *dev,
104 struct comedi_subdevice *s,
105 struct comedi_insn *insn,
106 unsigned int *data)
107 {
108 struct apci1032_private *devpriv = dev->private;
109 unsigned int shift, oldmask;
110
111 switch (data[0]) {
112 case INSN_CONFIG_DIGITAL_TRIG:
113 if (data[1] != 0)
114 return -EINVAL;
115 shift = data[3];
116 oldmask = (1U << shift) - 1;
117 switch (data[2]) {
118 case COMEDI_DIGITAL_TRIG_DISABLE:
119 devpriv->ctrl = 0;
120 devpriv->mode1 = 0;
121 devpriv->mode2 = 0;
122 apci1032_reset(dev);
123 break;
124 case COMEDI_DIGITAL_TRIG_ENABLE_EDGES:
125 if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
126 APCI1032_CTRL_INT_OR)) {
127
128 devpriv->ctrl = APCI1032_CTRL_INT_ENA |
129 APCI1032_CTRL_INT_OR;
130
131 devpriv->mode1 = 0;
132 devpriv->mode2 = 0;
133 } else {
134
135 devpriv->mode1 &= oldmask;
136 devpriv->mode2 &= oldmask;
137 }
138
139 devpriv->mode1 |= data[4] << shift;
140 devpriv->mode2 |= data[5] << shift;
141 break;
142 case COMEDI_DIGITAL_TRIG_ENABLE_LEVELS:
143 if (devpriv->ctrl != (APCI1032_CTRL_INT_ENA |
144 APCI1032_CTRL_INT_AND)) {
145
146 devpriv->ctrl = APCI1032_CTRL_INT_ENA |
147 APCI1032_CTRL_INT_AND;
148
149 devpriv->mode1 = 0;
150 devpriv->mode2 = 0;
151 } else {
152
153 devpriv->mode1 &= oldmask;
154 devpriv->mode2 &= oldmask;
155 }
156
157 devpriv->mode1 |= data[4] << shift;
158 devpriv->mode2 |= data[5] << shift;
159 break;
160 default:
161 return -EINVAL;
162 }
163 break;
164 default:
165 return -EINVAL;
166 }
167
168 return insn->n;
169 }
170
171 static int apci1032_cos_insn_bits(struct comedi_device *dev,
172 struct comedi_subdevice *s,
173 struct comedi_insn *insn,
174 unsigned int *data)
175 {
176 data[1] = s->state;
177
178 return 0;
179 }
180
181 static int apci1032_cos_cmdtest(struct comedi_device *dev,
182 struct comedi_subdevice *s,
183 struct comedi_cmd *cmd)
184 {
185 int err = 0;
186
187
188
189 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
190 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
191 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
192 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
193 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);
194
195 if (err)
196 return 1;
197
198
199
200
201
202
203 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
204 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
205 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
206 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
207 cmd->chanlist_len);
208 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
209
210 if (err)
211 return 3;
212
213
214
215
216
217 return 0;
218 }
219
220
221
222
223
224
225 static int apci1032_cos_cmd(struct comedi_device *dev,
226 struct comedi_subdevice *s)
227 {
228 struct apci1032_private *devpriv = dev->private;
229
230 if (!devpriv->ctrl) {
231 dev_warn(dev->class_dev,
232 "Interrupts disabled due to mode configuration!\n");
233 return -EINVAL;
234 }
235
236 outl(devpriv->mode1, dev->iobase + APCI1032_MODE1_REG);
237 outl(devpriv->mode2, dev->iobase + APCI1032_MODE2_REG);
238 outl(devpriv->ctrl, dev->iobase + APCI1032_CTRL_REG);
239
240 return 0;
241 }
242
243 static int apci1032_cos_cancel(struct comedi_device *dev,
244 struct comedi_subdevice *s)
245 {
246 return apci1032_reset(dev);
247 }
248
249 static irqreturn_t apci1032_interrupt(int irq, void *d)
250 {
251 struct comedi_device *dev = d;
252 struct apci1032_private *devpriv = dev->private;
253 struct comedi_subdevice *s = dev->read_subdev;
254 unsigned int ctrl;
255
256
257 if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) &
258 INTCSR_INTR_ASSERTED) == 0)
259 return IRQ_NONE;
260
261
262 ctrl = inl(dev->iobase + APCI1032_CTRL_REG);
263 if ((ctrl & APCI1032_CTRL_INT_ENA) == 0)
264 return IRQ_HANDLED;
265
266
267 outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG);
268
269 s->state = inl(dev->iobase + APCI1032_STATUS_REG) & 0xffff;
270 comedi_buf_write_samples(s, &s->state, 1);
271 comedi_handle_events(dev, s);
272
273
274 outl(ctrl, dev->iobase + APCI1032_CTRL_REG);
275
276 return IRQ_HANDLED;
277 }
278
279 static int apci1032_di_insn_bits(struct comedi_device *dev,
280 struct comedi_subdevice *s,
281 struct comedi_insn *insn,
282 unsigned int *data)
283 {
284 data[1] = inl(dev->iobase + APCI1032_DI_REG);
285
286 return insn->n;
287 }
288
289 static int apci1032_auto_attach(struct comedi_device *dev,
290 unsigned long context_unused)
291 {
292 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
293 struct apci1032_private *devpriv;
294 struct comedi_subdevice *s;
295 int ret;
296
297 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
298 if (!devpriv)
299 return -ENOMEM;
300
301 ret = comedi_pci_enable(dev);
302 if (ret)
303 return ret;
304
305 devpriv->amcc_iobase = pci_resource_start(pcidev, 0);
306 dev->iobase = pci_resource_start(pcidev, 1);
307 apci1032_reset(dev);
308 if (pcidev->irq > 0) {
309 ret = request_irq(pcidev->irq, apci1032_interrupt, IRQF_SHARED,
310 dev->board_name, dev);
311 if (ret == 0)
312 dev->irq = pcidev->irq;
313 }
314
315 ret = comedi_alloc_subdevices(dev, 2);
316 if (ret)
317 return ret;
318
319
320 s = &dev->subdevices[0];
321 s->type = COMEDI_SUBD_DI;
322 s->subdev_flags = SDF_READABLE;
323 s->n_chan = 32;
324 s->maxdata = 1;
325 s->range_table = &range_digital;
326 s->insn_bits = apci1032_di_insn_bits;
327
328
329 s = &dev->subdevices[1];
330 if (dev->irq) {
331 dev->read_subdev = s;
332 s->type = COMEDI_SUBD_DI;
333 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
334 s->n_chan = 1;
335 s->maxdata = 1;
336 s->range_table = &range_digital;
337 s->insn_config = apci1032_cos_insn_config;
338 s->insn_bits = apci1032_cos_insn_bits;
339 s->len_chanlist = 1;
340 s->do_cmdtest = apci1032_cos_cmdtest;
341 s->do_cmd = apci1032_cos_cmd;
342 s->cancel = apci1032_cos_cancel;
343 } else {
344 s->type = COMEDI_SUBD_UNUSED;
345 }
346
347 return 0;
348 }
349
350 static void apci1032_detach(struct comedi_device *dev)
351 {
352 if (dev->iobase)
353 apci1032_reset(dev);
354 comedi_pci_detach(dev);
355 }
356
357 static struct comedi_driver apci1032_driver = {
358 .driver_name = "addi_apci_1032",
359 .module = THIS_MODULE,
360 .auto_attach = apci1032_auto_attach,
361 .detach = apci1032_detach,
362 };
363
364 static int apci1032_pci_probe(struct pci_dev *dev,
365 const struct pci_device_id *id)
366 {
367 return comedi_pci_auto_config(dev, &apci1032_driver, id->driver_data);
368 }
369
370 static const struct pci_device_id apci1032_pci_table[] = {
371 { PCI_DEVICE(PCI_VENDOR_ID_ADDIDATA, 0x1003) },
372 { 0 }
373 };
374 MODULE_DEVICE_TABLE(pci, apci1032_pci_table);
375
376 static struct pci_driver apci1032_pci_driver = {
377 .name = "addi_apci_1032",
378 .id_table = apci1032_pci_table,
379 .probe = apci1032_pci_probe,
380 .remove = comedi_pci_auto_unconfig,
381 };
382 module_comedi_pci_driver(apci1032_driver, apci1032_pci_driver);
383
384 MODULE_AUTHOR("Comedi http://www.comedi.org");
385 MODULE_DESCRIPTION("ADDI-DATA APCI-1032, 32 channel DI boards");
386 MODULE_LICENSE("GPL");