Staging: comedi: Remove COMEDI_INITCLEANUP macro
[deliverable/linux.git] / drivers / staging / comedi / drivers / amplc_dio200.c
CommitLineData
e948cb52
IA
1/*
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.)
6
7 Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
8
9 COMEDI - Linux Control and Measurement Device Interface
10 Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
11
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.
16
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.
21
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.
25
26*/
27/*
28Driver: amplc_dio200
29Description: Amplicon 200 Series Digital I/O
30Author: Ian Abbott <abbotti@mev.co.uk>
31Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
32 PCI215 (pci215 or amplc_dio200), PC218E (pc218e), PC272E (pc272e),
33 PCI272 (pci272 or amplc_dio200)
34Updated: Wed, 22 Oct 2008 13:36:02 +0100
35Status: works
36
37Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
38 [0] - I/O port base address
39 [1] - IRQ (optional, but commands won't work without it)
40
41Configuration 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
45 be used.
46
47Passing a zero for an option is the same as leaving it unspecified.
48
49SUBDEVICES
50
669c930c
BA
51 PC218E PC212E PC215E/PCI215
52 ------------- ------------- -------------
e948cb52
IA
53 Subdevices 7 6 5
54 0 CTR-X1 PPI-X PPI-X
55 1 CTR-X2 CTR-Y1 PPI-Y
56 2 CTR-Y1 CTR-Y2 CTR-Z1
57 3 CTR-Y2 CTR-Z1 CTR-Z2
58 4 CTR-Z1 CTR-Z2 INTERRUPT
59 5 CTR-Z2 INTERRUPT
60 6 INTERRUPT
61
669c930c
BA
62 PC214E PC272E/PCI272
63 ------------- -------------
e948cb52
IA
64 Subdevices 4 4
65 0 PPI-X PPI-X
66 1 PPI-Y PPI-Y
67 2 CTR-Z1* PPI-Z
68 3 INTERRUPT* INTERRUPT
69
70Each PPI is a 8255 chip providing 24 DIO channels. The DIO channels
71are configurable as inputs or outputs in four groups:
72
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
77
78Only mode 0 of the 8255 chips is supported.
79
80Each CTR is a 8254 chip providing 3 16-bit counter channels. Each
81channel is configured individually with INSN_CONFIG instructions. The
82specific type of configuration instruction is specified in data[0].
83Some configuration instructions expect an additional parameter in
84data[1]; others return a value in data[1]. The following configuration
85instructions are supported:
86
87 INSN_CONFIG_SET_COUNTER_MODE. Sets the counter channel's mode and
88 BCD/binary setting specified in data[1].
89
90 INSN_CONFIG_8254_READ_STATUS. Reads the status register value for the
91 counter channel into data[1].
92
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
96 0 to 7 as follows:
97
98 0. CLK n, the counter channel's dedicated CLK input from the SK1
669c930c
BA
99 connector. (N.B. for other values, the counter channel's CLKn
100 pin on the SK1 connector is an output!)
e948cb52
IA
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
669c930c
BA
108 the SK1 connector. This pin is shared by all three counter
109 channels on the chip.
e948cb52
IA
110
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
113 to the period in ns.
114
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
118 to 7 as follows:
119
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
669c930c
BA
123 connector. (N.B. for other values, the counter channel's GATn
124 pin on the SK1 connector is an output!)
e948cb52 125 3. /OUT n-2, the inverted output of counter channel n-2 (see note
669c930c 126 2 below).
e948cb52
IA
127 4. Reserved.
128 5. Reserved.
129 6. Reserved.
130 7. Reserved.
131
132 INSN_CONFIG_GET_GATE_SRC. Returns the counter channel's current gate
133 source in data[2].
134
135Clock and gate interconnection notes:
136
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.
140
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.
144
145 3. The counter subdevices are connected in a ring, so the highest
146 counter subdevice precedes the lowest.
147
148The 'INTERRUPT' subdevice pretends to be a digital input subdevice. The
149digital inputs come from the interrupt status register. The number of
150channels matches the number of interrupt sources. The PC214E does not
151have an interrupt status register; see notes on 'INTERRUPT SOURCES'
152below.
153
154INTERRUPT SOURCES
155
669c930c
BA
156 PC218E PC212E PC215E/PCI215
157 ------------- ------------- -------------
e948cb52
IA
158 Sources 6 6 6
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
165
669c930c
BA
166 PC214E PC272E/PCI272
167 ------------- -------------
e948cb52
IA
168 Sources 1 6
169 0 JUMPER-J5 PPI-X-C0
170 1 PPI-X-C3
171 2 PPI-Y-C0
172 3 PPI-Y-C3
173 4 PPI-Z-C0
174 5 PPI-Z-C3
175
176When an interrupt source is enabled in the interrupt source enable
177register, a rising edge on the source signal latches the corresponding
178bit to 1 in the interrupt status register.
179
180When the interrupt status register value as a whole (actually, just the
1816 least significant bits) goes from zero to non-zero, the board will
182generate an interrupt. For level-triggered hardware interrupts (PCI
183card), the interrupt will remain asserted until the interrupt status
184register is cleared to zero. For edge-triggered hardware interrupts
185(ISA card), no further interrupts will occur until the interrupt status
186register is cleared to zero. To clear a bit to zero in the interrupt
187status register, the corresponding interrupt source must be disabled
188in the interrupt source enable register (there is no separate interrupt
189clear register).
190
191The PC214E does not have an interrupt source enable register or an
192interrupt status register; its 'INTERRUPT' subdevice has a single
193channel and its interrupt source is selected by the position of jumper
194J5.
195
196COMMANDS
197
198The driver supports a read streaming acquisition command on the
199'INTERRUPT' subdevice. The channel list selects the interrupt sources
200to be enabled. All channels will be sampled together (convert_src ==
201TRIG_NOW). The scan begins a short time after the hardware interrupt
202occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
203scan_begin_arg == 0). The value read from the interrupt status register
790c5541 204is packed into a short value, one bit per requested channel, in the
e948cb52
IA
205order they appear in the channel list.
206*/
207
70265d24 208#include <linux/interrupt.h>
5a0e3ad6 209#include <linux/slab.h>
70265d24 210
e948cb52
IA
211#include "../comedidev.h"
212
213#include "comedi_pci.h"
214
215#include "8255.h"
216#include "8253.h"
217
218#define DIO200_DRIVER_NAME "amplc_dio200"
219
220/* PCI IDs */
6608224c 221#define PCI_VENDOR_ID_AMPLICON 0x14dc
e948cb52
IA
222#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
223#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
224#define PCI_DEVICE_ID_INVALID 0xffff
225
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 */
235
236/*
237 * Macros for constructing value for DIO_200_?CLK_SCE and
238 * DIO_200_?GAT_SCE registers:
239 *
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.
243 */
244#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
245#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
246
247/*
248 * Periods of the internal clock sources in nanoseconds.
249 */
250static const unsigned clock_period[8] = {
251 0, /* dedicated clock input/output pin */
252 100, /* 10 MHz */
253 1000, /* 1 MHz */
254 10000, /* 100 kHz */
255 100000, /* 10 kHz */
256 1000000, /* 1 kHz */
257 0, /* OUT N-1 */
258 0 /* group clock input pin */
259};
260
261/*
262 * Board descriptions.
263 */
264
265enum dio200_bustype { isa_bustype, pci_bustype };
266
267enum dio200_model {
268 pc212e_model,
269 pc214e_model,
270 pc215e_model, pci215_model,
271 pc218e_model,
272 pc272e_model, pci272_model,
273 anypci_model
274};
275
276enum dio200_layout {
277 pc212_layout,
278 pc214_layout,
279 pc215_layout,
280 pc218_layout,
281 pc272_layout
282};
283
3d7a42ef 284struct dio200_board {
e948cb52
IA
285 const char *name;
286 unsigned short devid;
287 enum dio200_bustype bustype;
288 enum dio200_model model;
289 enum dio200_layout layout;
3d7a42ef 290};
e948cb52 291
3d7a42ef 292static const struct dio200_board dio200_boards[] = {
e948cb52 293 {
0a85b6f0
MT
294 .name = "pc212e",
295 .bustype = isa_bustype,
296 .model = pc212e_model,
297 .layout = pc212_layout,
298 },
e948cb52 299 {
0a85b6f0
MT
300 .name = "pc214e",
301 .bustype = isa_bustype,
302 .model = pc214e_model,
303 .layout = pc214_layout,
304 },
e948cb52 305 {
0a85b6f0
MT
306 .name = "pc215e",
307 .bustype = isa_bustype,
308 .model = pc215e_model,
309 .layout = pc215_layout,
310 },
e948cb52
IA
311#ifdef CONFIG_COMEDI_PCI
312 {
0a85b6f0
MT
313 .name = "pci215",
314 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
315 .bustype = pci_bustype,
316 .model = pci215_model,
317 .layout = pc215_layout,
318 },
e948cb52
IA
319#endif
320 {
0a85b6f0
MT
321 .name = "pc218e",
322 .bustype = isa_bustype,
323 .model = pc218e_model,
324 .layout = pc218_layout,
325 },
e948cb52 326 {
0a85b6f0
MT
327 .name = "pc272e",
328 .bustype = isa_bustype,
329 .model = pc272e_model,
330 .layout = pc272_layout,
331 },
e948cb52
IA
332#ifdef CONFIG_COMEDI_PCI
333 {
0a85b6f0
MT
334 .name = "pci272",
335 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
336 .bustype = pci_bustype,
337 .model = pci272_model,
338 .layout = pc272_layout,
339 },
e948cb52
IA
340#endif
341#ifdef CONFIG_COMEDI_PCI
342 {
0a85b6f0
MT
343 .name = DIO200_DRIVER_NAME,
344 .devid = PCI_DEVICE_ID_INVALID,
345 .bustype = pci_bustype,
346 .model = anypci_model, /* wildcard */
347 },
e948cb52
IA
348#endif
349};
350
351/*
352 * Layout descriptions - some ISA and PCI board descriptions share the same
353 * layout.
354 */
355
356enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
357
358#define DIO200_MAX_SUBDEVS 7
359#define DIO200_MAX_ISNS 6
360
af105ad3 361struct dio200_layout_struct {
e948cb52
IA
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 */
af105ad3 367};
e948cb52 368
af105ad3 369static const struct dio200_layout_struct dio200_layouts[] = {
e948cb52 370 [pc212_layout] = {
0a85b6f0
MT
371 .n_subdevs = 6,
372 .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
373 sd_8254,
374 sd_intr},
375 .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
376 0x3F},
377 .has_int_sce = 1,
378 .has_clk_gat_sce = 1,
379 },
e948cb52 380 [pc214_layout] = {
0a85b6f0
MT
381 .n_subdevs = 4,
382 .sdtype = {sd_8255, sd_8255, sd_8254,
383 sd_intr},
384 .sdinfo = {0x00, 0x08, 0x10, 0x01},
385 .has_int_sce = 0,
386 .has_clk_gat_sce = 0,
387 },
e948cb52 388 [pc215_layout] = {
0a85b6f0
MT
389 .n_subdevs = 5,
390 .sdtype = {sd_8255, sd_8255, sd_8254,
391 sd_8254,
392 sd_intr},
393 .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
394 .has_int_sce = 1,
395 .has_clk_gat_sce = 1,
396 },
e948cb52 397 [pc218_layout] = {
0a85b6f0
MT
398 .n_subdevs = 7,
399 .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
400 sd_8254,
401 sd_intr},
402 .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
403 0x14,
404 0x3F},
405 .has_int_sce = 1,
406 .has_clk_gat_sce = 1,
407 },
e948cb52 408 [pc272_layout] = {
0a85b6f0
MT
409 .n_subdevs = 4,
410 .sdtype = {sd_8255, sd_8255, sd_8255,
411 sd_intr},
412 .sdinfo = {0x00, 0x08, 0x10, 0x3F},
413 .has_int_sce = 1,
414 .has_clk_gat_sce = 0,
415 },
e948cb52
IA
416};
417
418/*
419 * PCI driver table.
420 */
421
422#ifdef CONFIG_COMEDI_PCI
423static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
0a85b6f0
MT
424 {
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}, {
429 0}
e948cb52
IA
430};
431
432MODULE_DEVICE_TABLE(pci, dio200_pci_table);
433#endif /* CONFIG_COMEDI_PCI */
434
435/*
436 * Useful for shorthand access to the particular board structure
437 */
3d7a42ef 438#define thisboard ((const struct dio200_board *)dev->board_ptr)
669c930c
BA
439#define thislayout (&dio200_layouts[((struct dio200_board *) \
440 dev->board_ptr)->layout])
e948cb52
IA
441
442/* this structure is for data unique to this hardware driver. If
443 several hardware drivers keep similar information in this structure,
669c930c
BA
444 feel free to suggest moving the variable to the struct comedi_device struct.
445 */
692560db 446struct dio200_private {
e948cb52
IA
447#ifdef CONFIG_COMEDI_PCI
448 struct pci_dev *pci_dev; /* PCI device */
449#endif
450 int intr_sd;
692560db 451};
e948cb52 452
692560db 453#define devpriv ((struct dio200_private *)dev->private)
e948cb52 454
93ba42e9 455struct dio200_subdev_8254 {
e948cb52
IA
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 */
460 int has_clk_gat_sce;
461 unsigned clock_src[3]; /* Current clock sources */
462 unsigned gate_src[3]; /* Current gate sources */
ee4063fa 463 spinlock_t spinlock;
93ba42e9 464};
e948cb52 465
d9752ee0 466struct dio200_subdev_intr {
e948cb52
IA
467 unsigned long iobase;
468 spinlock_t spinlock;
469 int active;
470 int has_int_sce;
471 unsigned int valid_isns;
472 unsigned int enabled_isns;
473 unsigned int stopcount;
474 int continuous;
d9752ee0 475};
e948cb52
IA
476
477/*
139dfbdf 478 * The struct comedi_driver structure tells the Comedi core module
e948cb52
IA
479 * which functions to call to configure/deconfigure (attach/detach)
480 * the board, and also about the kernel module that contains
481 * the device code.
482 */
0a85b6f0
MT
483static int dio200_attach(struct comedi_device *dev,
484 struct comedi_devconfig *it);
da91b269 485static int dio200_detach(struct comedi_device *dev);
139dfbdf 486static struct comedi_driver driver_amplc_dio200 = {
68c3dbff
BP
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),
8629efa4 493 .num_names = ARRAY_SIZE(dio200_boards),
e948cb52
IA
494};
495
496#ifdef CONFIG_COMEDI_PCI
497COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
498#else
7114a280
AT
499static int __init driver_amplc_dio200_init_module(void)
500{
501 return comedi_driver_register(&driver_amplc_dio200);
502}
503
504static void __exit driver_amplc_dio200_cleanup_module(void)
505{
506 comedi_driver_unregister(&driver_amplc_dio200);
507}
508
509module_init(driver_amplc_dio200_init_module);
510module_exit(driver_amplc_dio200_cleanup_module);
e948cb52
IA
511#endif
512
513/*
514 * This function looks for a PCI device matching the requested board name,
515 * bus and slot.
516 */
517#ifdef CONFIG_COMEDI_PCI
518static int
da91b269 519dio200_find_pci(struct comedi_device *dev, int bus, int slot,
0a85b6f0 520 struct pci_dev **pci_dev_p)
e948cb52
IA
521{
522 struct pci_dev *pci_dev = NULL;
523
524 *pci_dev_p = NULL;
525
526 /* Look for matching PCI device. */
527 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
0a85b6f0
MT
528 pci_dev != NULL;
529 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
530 PCI_ANY_ID, pci_dev)) {
e948cb52
IA
531 /* If bus/slot specified, check them. */
532 if (bus || slot) {
533 if (bus != pci_dev->bus->number
0a85b6f0 534 || slot != PCI_SLOT(pci_dev->devfn))
e948cb52
IA
535 continue;
536 }
537 if (thisboard->model == anypci_model) {
538 /* Match any supported model. */
539 int i;
540
541 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
542 if (dio200_boards[i].bustype != pci_bustype)
543 continue;
544 if (pci_dev->device == dio200_boards[i].devid) {
545 /* Change board_ptr to matched board. */
546 dev->board_ptr = &dio200_boards[i];
547 break;
548 }
549 }
550 if (i == ARRAY_SIZE(dio200_boards))
551 continue;
552 } else {
553 /* Match specific model name. */
554 if (pci_dev->device != thisboard->devid)
555 continue;
556 }
557
558 /* Found a match. */
559 *pci_dev_p = pci_dev;
560 return 0;
561 }
562 /* No match found. */
563 if (bus || slot) {
564 printk(KERN_ERR
0a85b6f0
MT
565 "comedi%d: error! no %s found at pci %02x:%02x!\n",
566 dev->minor, thisboard->name, bus, slot);
e948cb52
IA
567 } else {
568 printk(KERN_ERR "comedi%d: error! no %s found!\n",
0a85b6f0 569 dev->minor, thisboard->name);
e948cb52
IA
570 }
571 return -EIO;
572}
573#endif
574
575/*
576 * This function checks and requests an I/O region, reporting an error
577 * if there is a conflict.
578 */
579static int
580dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
581{
582 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
583 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
0a85b6f0 584 minor, from, extent);
e948cb52
IA
585 return -EIO;
586 }
587 return 0;
588}
589
590/*
591 * 'insn_bits' function for an 'INTERRUPT' subdevice.
592 */
593static int
0a85b6f0
MT
594dio200_subdev_intr_insn_bits(struct comedi_device *dev,
595 struct comedi_subdevice *s,
596 struct comedi_insn *insn, unsigned int *data)
e948cb52 597{
d9752ee0 598 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
599
600 if (subpriv->has_int_sce) {
601 /* Just read the interrupt status register. */
602 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
603 } else {
604 /* No interrupt status register. */
605 data[0] = 0;
606 }
607
608 return 2;
609}
610
611/*
612 * Called to stop acquisition for an 'INTERRUPT' subdevice.
613 */
0a85b6f0
MT
614static void dio200_stop_intr(struct comedi_device *dev,
615 struct comedi_subdevice *s)
e948cb52 616{
d9752ee0 617 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
618
619 subpriv->active = 0;
620 subpriv->enabled_isns = 0;
669c930c 621 if (subpriv->has_int_sce)
e948cb52 622 outb(0, subpriv->iobase);
e948cb52
IA
623}
624
625/*
626 * Called to start acquisition for an 'INTERRUPT' subdevice.
627 */
0a85b6f0
MT
628static int dio200_start_intr(struct comedi_device *dev,
629 struct comedi_subdevice *s)
e948cb52
IA
630{
631 unsigned int n;
632 unsigned isn_bits;
d9752ee0 633 struct dio200_subdev_intr *subpriv = s->private;
ea6d0d4c 634 struct comedi_cmd *cmd = &s->async->cmd;
e948cb52
IA
635 int retval = 0;
636
637 if (!subpriv->continuous && subpriv->stopcount == 0) {
638 /* An empty acquisition! */
639 s->async->events |= COMEDI_CB_EOA;
640 subpriv->active = 0;
641 retval = 1;
642 } else {
643 /* Determine interrupt sources to enable. */
644 isn_bits = 0;
645 if (cmd->chanlist) {
669c930c 646 for (n = 0; n < cmd->chanlist_len; n++)
e948cb52 647 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
e948cb52
IA
648 }
649 isn_bits &= subpriv->valid_isns;
650 /* Enable interrupt sources. */
651 subpriv->enabled_isns = isn_bits;
669c930c 652 if (subpriv->has_int_sce)
e948cb52 653 outb(isn_bits, subpriv->iobase);
e948cb52
IA
654 }
655
656 return retval;
657}
658
659/*
660 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
661 */
662static int
da91b269 663dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 664 unsigned int trignum)
e948cb52 665{
d9752ee0 666 struct dio200_subdev_intr *subpriv;
e948cb52
IA
667 unsigned long flags;
668 int event = 0;
669
670 if (trignum != 0)
671 return -EINVAL;
672
673 subpriv = s->private;
674
5f74ea14 675 spin_lock_irqsave(&subpriv->spinlock, flags);
a7f22a84 676 s->async->inttrig = NULL;
669c930c 677 if (subpriv->active)
e948cb52 678 event = dio200_start_intr(dev, s);
669c930c 679
5f74ea14 680 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 681
669c930c 682 if (event)
e948cb52 683 comedi_event(dev, s);
e948cb52
IA
684
685 return 1;
686}
687
688/*
689 * This is called from the interrupt service routine to handle a read
690 * scan on an 'INTERRUPT' subdevice.
691 */
0a85b6f0
MT
692static int dio200_handle_read_intr(struct comedi_device *dev,
693 struct comedi_subdevice *s)
e948cb52 694{
d9752ee0 695 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
696 unsigned triggered;
697 unsigned intstat;
698 unsigned cur_enabled;
699 unsigned int oldevents;
700 unsigned long flags;
701
702 triggered = 0;
703
5f74ea14 704 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
705 oldevents = s->async->events;
706 if (subpriv->has_int_sce) {
707 /*
708 * Collect interrupt sources that have triggered and disable
709 * them temporarily. Loop around until no extra interrupt
710 * sources have triggered, at which point, the valid part of
711 * the interrupt status register will read zero, clearing the
712 * cause of the interrupt.
713 *
714 * Mask off interrupt sources already seen to avoid infinite
715 * loop in case of misconfiguration.
716 */
717 cur_enabled = subpriv->enabled_isns;
718 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
0a85b6f0 719 & ~triggered)) != 0) {
e948cb52
IA
720 triggered |= intstat;
721 cur_enabled &= ~triggered;
722 outb(cur_enabled, subpriv->iobase);
723 }
724 } else {
725 /*
726 * No interrupt status register. Assume the single interrupt
727 * source has triggered.
728 */
729 triggered = subpriv->enabled_isns;
730 }
731
732 if (triggered) {
733 /*
734 * Some interrupt sources have triggered and have been
735 * temporarily disabled to clear the cause of the interrupt.
736 *
737 * Reenable them NOW to minimize the time they are disabled.
738 */
739 cur_enabled = subpriv->enabled_isns;
669c930c 740 if (subpriv->has_int_sce)
e948cb52 741 outb(cur_enabled, subpriv->iobase);
e948cb52
IA
742
743 if (subpriv->active) {
744 /*
745 * The command is still active.
746 *
747 * Ignore interrupt sources that the command isn't
748 * interested in (just in case there's a race
749 * condition).
750 */
751 if (triggered & subpriv->enabled_isns) {
752 /* Collect scan data. */
790c5541 753 short val;
e948cb52
IA
754 unsigned int n, ch, len;
755
756 val = 0;
757 len = s->async->cmd.chanlist_len;
758 for (n = 0; n < len; n++) {
759 ch = CR_CHAN(s->async->cmd.chanlist[n]);
669c930c 760 if (triggered & (1U << ch))
e948cb52 761 val |= (1U << n);
e948cb52
IA
762 }
763 /* Write the scan to the buffer. */
764 if (comedi_buf_put(s->async, val)) {
765 s->async->events |= (COMEDI_CB_BLOCK |
0a85b6f0 766 COMEDI_CB_EOS);
e948cb52
IA
767 } else {
768 /* Error! Stop acquisition. */
769 dio200_stop_intr(dev, s);
770 s->async->events |= COMEDI_CB_ERROR
0a85b6f0 771 | COMEDI_CB_OVERFLOW;
e948cb52
IA
772 comedi_error(dev, "buffer overflow");
773 }
774
775 /* Check for end of acquisition. */
776 if (!subpriv->continuous) {
777 /* stop_src == TRIG_COUNT */
778 if (subpriv->stopcount > 0) {
779 subpriv->stopcount--;
780 if (subpriv->stopcount == 0) {
781 s->async->events |=
0a85b6f0 782 COMEDI_CB_EOA;
e948cb52 783 dio200_stop_intr(dev,
0a85b6f0 784 s);
e948cb52
IA
785 }
786 }
787 }
788 }
789 }
790 }
5f74ea14 791 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 792
669c930c 793 if (oldevents != s->async->events)
e948cb52 794 comedi_event(dev, s);
e948cb52
IA
795
796 return (triggered != 0);
797}
798
799/*
800 * 'cancel' function for an 'INTERRUPT' subdevice.
801 */
0a85b6f0
MT
802static int dio200_subdev_intr_cancel(struct comedi_device *dev,
803 struct comedi_subdevice *s)
e948cb52 804{
d9752ee0 805 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
806 unsigned long flags;
807
5f74ea14 808 spin_lock_irqsave(&subpriv->spinlock, flags);
669c930c 809 if (subpriv->active)
e948cb52 810 dio200_stop_intr(dev, s);
669c930c 811
5f74ea14 812 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
813
814 return 0;
815}
816
817/*
818 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
819 */
820static int
0a85b6f0
MT
821dio200_subdev_intr_cmdtest(struct comedi_device *dev,
822 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e948cb52
IA
823{
824 int err = 0;
825 unsigned int tmp;
826
827 /* step 1: make sure trigger sources are trivially valid */
828
829 tmp = cmd->start_src;
830 cmd->start_src &= (TRIG_NOW | TRIG_INT);
831 if (!cmd->start_src || tmp != cmd->start_src)
832 err++;
833
834 tmp = cmd->scan_begin_src;
835 cmd->scan_begin_src &= TRIG_EXT;
836 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
837 err++;
838
839 tmp = cmd->convert_src;
840 cmd->convert_src &= TRIG_NOW;
841 if (!cmd->convert_src || tmp != cmd->convert_src)
842 err++;
843
844 tmp = cmd->scan_end_src;
845 cmd->scan_end_src &= TRIG_COUNT;
846 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
847 err++;
848
849 tmp = cmd->stop_src;
850 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
851 if (!cmd->stop_src || tmp != cmd->stop_src)
852 err++;
853
854 if (err)
855 return 1;
856
669c930c
BA
857 /* step 2: make sure trigger sources are unique and mutually
858 compatible */
e948cb52
IA
859
860 /* these tests are true if more than one _src bit is set */
861 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
862 err++;
863 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
864 err++;
865 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
866 err++;
867 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
868 err++;
869 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
870 err++;
871
872 if (err)
873 return 2;
874
875 /* step 3: make sure arguments are trivially compatible */
876
877 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
878 if (cmd->start_arg != 0) {
879 cmd->start_arg = 0;
880 err++;
881 }
882
883 /* cmd->scan_begin_src == TRIG_EXT */
884 if (cmd->scan_begin_arg != 0) {
885 cmd->scan_begin_arg = 0;
886 err++;
887 }
888
889 /* cmd->convert_src == TRIG_NOW */
890 if (cmd->convert_arg != 0) {
891 cmd->convert_arg = 0;
892 err++;
893 }
894
895 /* cmd->scan_end_src == TRIG_COUNT */
896 if (cmd->scan_end_arg != cmd->chanlist_len) {
897 cmd->scan_end_arg = cmd->chanlist_len;
898 err++;
899 }
900
901 switch (cmd->stop_src) {
902 case TRIG_COUNT:
903 /* any count allowed */
904 break;
905 case TRIG_NONE:
906 if (cmd->stop_arg != 0) {
907 cmd->stop_arg = 0;
908 err++;
909 }
910 break;
911 default:
912 break;
913 }
914
915 if (err)
916 return 3;
917
918 /* step 4: fix up any arguments */
919
920 /* if (err) return 4; */
921
922 return 0;
923}
924
925/*
926 * 'do_cmd' function for an 'INTERRUPT' subdevice.
927 */
0a85b6f0
MT
928static int dio200_subdev_intr_cmd(struct comedi_device *dev,
929 struct comedi_subdevice *s)
e948cb52 930{
ea6d0d4c 931 struct comedi_cmd *cmd = &s->async->cmd;
d9752ee0 932 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
933 unsigned long flags;
934 int event = 0;
935
5f74ea14 936 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
937 subpriv->active = 1;
938
939 /* Set up end of acquisition. */
940 switch (cmd->stop_src) {
941 case TRIG_COUNT:
942 subpriv->continuous = 0;
943 subpriv->stopcount = cmd->stop_arg;
944 break;
945 default:
946 /* TRIG_NONE */
947 subpriv->continuous = 1;
948 subpriv->stopcount = 0;
949 break;
950 }
951
952 /* Set up start of acquisition. */
953 switch (cmd->start_src) {
954 case TRIG_INT:
955 s->async->inttrig = dio200_inttrig_start_intr;
956 break;
957 default:
958 /* TRIG_NOW */
959 event = dio200_start_intr(dev, s);
960 break;
961 }
5f74ea14 962 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 963
669c930c 964 if (event)
e948cb52 965 comedi_event(dev, s);
e948cb52
IA
966
967 return 0;
968}
969
970/*
971 * This function initializes an 'INTERRUPT' subdevice.
972 */
973static int
da91b269 974dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
975 unsigned long iobase, unsigned valid_isns,
976 int has_int_sce)
e948cb52 977{
d9752ee0 978 struct dio200_subdev_intr *subpriv;
e948cb52
IA
979
980 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
981 if (!subpriv) {
982 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 983 dev->minor);
e948cb52
IA
984 return -ENOMEM;
985 }
986 subpriv->iobase = iobase;
987 subpriv->has_int_sce = has_int_sce;
988 subpriv->valid_isns = valid_isns;
989 spin_lock_init(&subpriv->spinlock);
990
669c930c 991 if (has_int_sce)
e948cb52 992 outb(0, subpriv->iobase); /* Disable interrupt sources. */
e948cb52
IA
993
994 s->private = subpriv;
995 s->type = COMEDI_SUBD_DI;
996 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
997 if (has_int_sce) {
998 s->n_chan = DIO200_MAX_ISNS;
999 s->len_chanlist = DIO200_MAX_ISNS;
1000 } else {
1001 /* No interrupt source register. Support single channel. */
1002 s->n_chan = 1;
1003 s->len_chanlist = 1;
1004 }
1005 s->range_table = &range_digital;
1006 s->maxdata = 1;
1007 s->insn_bits = dio200_subdev_intr_insn_bits;
1008 s->do_cmdtest = dio200_subdev_intr_cmdtest;
1009 s->do_cmd = dio200_subdev_intr_cmd;
1010 s->cancel = dio200_subdev_intr_cancel;
1011
1012 return 0;
1013}
1014
1015/*
1016 * This function cleans up an 'INTERRUPT' subdevice.
1017 */
1018static void
0a85b6f0
MT
1019dio200_subdev_intr_cleanup(struct comedi_device *dev,
1020 struct comedi_subdevice *s)
e948cb52 1021{
d9752ee0 1022 struct dio200_subdev_intr *subpriv = s->private;
669c930c 1023 kfree(subpriv);
e948cb52
IA
1024}
1025
1026/*
1027 * Interrupt service routine.
1028 */
70265d24 1029static irqreturn_t dio200_interrupt(int irq, void *d)
e948cb52 1030{
71b5f4f1 1031 struct comedi_device *dev = d;
e948cb52
IA
1032 int handled;
1033
669c930c 1034 if (!dev->attached)
e948cb52 1035 return IRQ_NONE;
e948cb52
IA
1036
1037 if (devpriv->intr_sd >= 0) {
1038 handled = dio200_handle_read_intr(dev,
0a85b6f0
MT
1039 dev->subdevices +
1040 devpriv->intr_sd);
e948cb52
IA
1041 } else {
1042 handled = 0;
1043 }
1044
1045 return IRQ_RETVAL(handled);
1046}
1047
1048/*
1049 * Handle 'insn_read' for an '8254' counter subdevice.
1050 */
1051static int
da91b269 1052dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1053 struct comedi_insn *insn, unsigned int *data)
e948cb52 1054{
93ba42e9 1055 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1056 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1057 unsigned long flags;
e948cb52 1058
ee4063fa 1059 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1060 data[0] = i8254_read(subpriv->iobase, 0, chan);
ee4063fa 1061 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1062
1063 return 1;
1064}
1065
1066/*
1067 * Handle 'insn_write' for an '8254' counter subdevice.
1068 */
1069static int
da91b269 1070dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1071 struct comedi_insn *insn, unsigned int *data)
e948cb52 1072{
93ba42e9 1073 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1074 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1075 unsigned long flags;
e948cb52 1076
ee4063fa 1077 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1078 i8254_write(subpriv->iobase, 0, chan, data[0]);
ee4063fa 1079 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1080
1081 return 1;
1082}
1083
1084/*
1085 * Set gate source for an '8254' counter subdevice channel.
1086 */
1087static int
0a85b6f0
MT
1088dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1089 unsigned int counter_number, unsigned int gate_src)
e948cb52
IA
1090{
1091 unsigned char byte;
1092
1093 if (!subpriv->has_clk_gat_sce)
1094 return -1;
1095 if (counter_number > 2)
1096 return -1;
1097 if (gate_src > 7)
1098 return -1;
1099
1100 subpriv->gate_src[counter_number] = gate_src;
1101 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1102 outb(byte, subpriv->gat_sce_iobase);
1103
1104 return 0;
1105}
1106
1107/*
1108 * Get gate source for an '8254' counter subdevice channel.
1109 */
1110static int
0a85b6f0
MT
1111dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1112 unsigned int counter_number)
e948cb52
IA
1113{
1114 if (!subpriv->has_clk_gat_sce)
1115 return -1;
1116 if (counter_number > 2)
1117 return -1;
1118
1119 return subpriv->gate_src[counter_number];
1120}
1121
1122/*
1123 * Set clock source for an '8254' counter subdevice channel.
1124 */
1125static int
0a85b6f0
MT
1126dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1127 unsigned int counter_number, unsigned int clock_src)
e948cb52
IA
1128{
1129 unsigned char byte;
1130
1131 if (!subpriv->has_clk_gat_sce)
1132 return -1;
1133 if (counter_number > 2)
1134 return -1;
1135 if (clock_src > 7)
1136 return -1;
1137
1138 subpriv->clock_src[counter_number] = clock_src;
1139 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1140 outb(byte, subpriv->clk_sce_iobase);
1141
1142 return 0;
1143}
1144
1145/*
1146 * Get clock source for an '8254' counter subdevice channel.
1147 */
1148static int
0a85b6f0
MT
1149dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1150 unsigned int counter_number, unsigned int *period_ns)
e948cb52
IA
1151{
1152 unsigned clock_src;
1153
1154 if (!subpriv->has_clk_gat_sce)
1155 return -1;
1156 if (counter_number > 2)
1157 return -1;
1158
1159 clock_src = subpriv->clock_src[counter_number];
1160 *period_ns = clock_period[clock_src];
1161 return clock_src;
1162}
1163
1164/*
1165 * Handle 'insn_config' for an '8254' counter subdevice.
1166 */
1167static int
da91b269 1168dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1169 struct comedi_insn *insn, unsigned int *data)
e948cb52 1170{
93ba42e9 1171 struct dio200_subdev_8254 *subpriv = s->private;
ee4063fa 1172 int ret = 0;
e948cb52 1173 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1174 unsigned long flags;
e948cb52 1175
ee4063fa 1176 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
1177 switch (data[0]) {
1178 case INSN_CONFIG_SET_COUNTER_MODE:
1179 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1180 if (ret < 0)
ee4063fa 1181 ret = -EINVAL;
e948cb52
IA
1182 break;
1183 case INSN_CONFIG_8254_READ_STATUS:
1184 data[1] = i8254_status(subpriv->iobase, 0, chan);
1185 break;
1186 case INSN_CONFIG_SET_GATE_SRC:
1187 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1188 if (ret < 0)
ee4063fa 1189 ret = -EINVAL;
e948cb52
IA
1190 break;
1191 case INSN_CONFIG_GET_GATE_SRC:
1192 ret = dio200_get_gate_src(subpriv, chan);
ee4063fa
IA
1193 if (ret < 0) {
1194 ret = -EINVAL;
1195 break;
1196 }
e948cb52
IA
1197 data[2] = ret;
1198 break;
1199 case INSN_CONFIG_SET_CLOCK_SRC:
1200 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1201 if (ret < 0)
ee4063fa 1202 ret = -EINVAL;
e948cb52
IA
1203 break;
1204 case INSN_CONFIG_GET_CLOCK_SRC:
1205 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
ee4063fa
IA
1206 if (ret < 0) {
1207 ret = -EINVAL;
1208 break;
1209 }
e948cb52
IA
1210 data[1] = ret;
1211 break;
1212 default:
ee4063fa 1213 ret = -EINVAL;
e948cb52
IA
1214 break;
1215 }
ee4063fa
IA
1216 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1217 return ret < 0 ? ret : insn->n;
e948cb52
IA
1218}
1219
1220/*
1221 * This function initializes an '8254' counter subdevice.
1222 *
1223 * Note: iobase is the base address of the board, not the subdevice;
1224 * offset is the offset to the 8254 chip.
1225 */
1226static int
da91b269 1227dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
1228 unsigned long iobase, unsigned offset,
1229 int has_clk_gat_sce)
e948cb52 1230{
93ba42e9 1231 struct dio200_subdev_8254 *subpriv;
e948cb52
IA
1232 unsigned int chan;
1233
1234 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1235 if (!subpriv) {
1236 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1237 dev->minor);
e948cb52
IA
1238 return -ENOMEM;
1239 }
1240
1241 s->private = subpriv;
1242 s->type = COMEDI_SUBD_COUNTER;
1243 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1244 s->n_chan = 3;
1245 s->maxdata = 0xFFFF;
1246 s->insn_read = dio200_subdev_8254_read;
1247 s->insn_write = dio200_subdev_8254_write;
1248 s->insn_config = dio200_subdev_8254_config;
1249
ee4063fa 1250 spin_lock_init(&subpriv->spinlock);
e948cb52
IA
1251 subpriv->iobase = offset + iobase;
1252 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1253 if (has_clk_gat_sce) {
1254 /* Derive CLK_SCE and GAT_SCE register offsets from
1255 * 8254 offset. */
1256 subpriv->clk_sce_iobase =
0a85b6f0 1257 DIO200_XCLK_SCE + (offset >> 3) + iobase;
e948cb52 1258 subpriv->gat_sce_iobase =
0a85b6f0 1259 DIO200_XGAT_SCE + (offset >> 3) + iobase;
e948cb52
IA
1260 subpriv->which = (offset >> 2) & 1;
1261 }
1262
1263 /* Initialize channels. */
1264 for (chan = 0; chan < 3; chan++) {
1265 i8254_set_mode(subpriv->iobase, 0, chan,
0a85b6f0 1266 I8254_MODE0 | I8254_BINARY);
e948cb52
IA
1267 if (subpriv->has_clk_gat_sce) {
1268 /* Gate source 0 is VCC (logic 1). */
1269 dio200_set_gate_src(subpriv, chan, 0);
1270 /* Clock source 0 is the dedicated clock input. */
1271 dio200_set_clock_src(subpriv, chan, 0);
1272 }
1273 }
1274
1275 return 0;
1276}
1277
1278/*
1279 * This function cleans up an '8254' counter subdevice.
1280 */
1281static void
0a85b6f0
MT
1282dio200_subdev_8254_cleanup(struct comedi_device *dev,
1283 struct comedi_subdevice *s)
e948cb52 1284{
d9752ee0 1285 struct dio200_subdev_intr *subpriv = s->private;
669c930c 1286 kfree(subpriv);
e948cb52
IA
1287}
1288
1289/*
1290 * Attach is called by the Comedi core to configure the driver
1291 * for a particular board. If you specified a board_name array
1292 * in the driver structure, dev->board_ptr contains that
1293 * address.
1294 */
da91b269 1295static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
e948cb52 1296{
34c43922 1297 struct comedi_subdevice *s;
e948cb52
IA
1298 unsigned long iobase = 0;
1299 unsigned int irq = 0;
1300#ifdef CONFIG_COMEDI_PCI
1301 struct pci_dev *pci_dev = NULL;
1302 int bus = 0, slot = 0;
1303#endif
af105ad3 1304 const struct dio200_layout_struct *layout;
e948cb52
IA
1305 int share_irq = 0;
1306 int sdx;
1307 unsigned n;
1308 int ret;
1309
1310 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
0a85b6f0 1311 DIO200_DRIVER_NAME);
e948cb52 1312
c3744138
BP
1313 ret = alloc_private(dev, sizeof(struct dio200_private));
1314 if (ret < 0) {
e948cb52 1315 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1316 dev->minor);
e948cb52
IA
1317 return ret;
1318 }
1319
1320 /* Process options. */
1321 switch (thisboard->bustype) {
1322 case isa_bustype:
1323 iobase = it->options[0];
1324 irq = it->options[1];
1325 share_irq = 0;
1326 break;
1327#ifdef CONFIG_COMEDI_PCI
1328 case pci_bustype:
1329 bus = it->options[0];
1330 slot = it->options[1];
1331 share_irq = 1;
1332
c3744138
BP
1333 ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1334 if (ret < 0)
e948cb52
IA
1335 return ret;
1336 devpriv->pci_dev = pci_dev;
1337 break;
1338#endif
1339 default:
1340 printk(KERN_ERR
0a85b6f0
MT
1341 "comedi%d: %s: BUG! cannot determine board type!\n",
1342 dev->minor, DIO200_DRIVER_NAME);
e948cb52
IA
1343 return -EINVAL;
1344 break;
1345 }
1346
1347 devpriv->intr_sd = -1;
1348
1349 /* Enable device and reserve I/O spaces. */
1350#ifdef CONFIG_COMEDI_PCI
1351 if (pci_dev) {
1352 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1353 if (ret < 0) {
1354 printk(KERN_ERR
0a85b6f0
MT
1355 "comedi%d: error! cannot enable PCI device and request regions!\n",
1356 dev->minor);
e948cb52
IA
1357 return ret;
1358 }
1359 iobase = pci_resource_start(pci_dev, 2);
1360 irq = pci_dev->irq;
1361 } else
1362#endif
1363 {
1364 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
669c930c 1365 if (ret < 0)
e948cb52 1366 return ret;
e948cb52
IA
1367 }
1368 dev->iobase = iobase;
1369
1370 layout = thislayout;
c3744138
BP
1371
1372 ret = alloc_subdevices(dev, layout->n_subdevs);
1373 if (ret < 0) {
e948cb52 1374 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1375 dev->minor);
e948cb52
IA
1376 return ret;
1377 }
1378
1379 for (n = 0; n < dev->n_subdevices; n++) {
1380 s = &dev->subdevices[n];
1381 switch (layout->sdtype[n]) {
1382 case sd_8254:
1383 /* counter subdevice (8254) */
1384 ret = dio200_subdev_8254_init(dev, s, iobase,
0a85b6f0
MT
1385 layout->sdinfo[n],
1386 layout->has_clk_gat_sce);
669c930c 1387 if (ret < 0)
e948cb52 1388 return ret;
669c930c 1389
e948cb52
IA
1390 break;
1391 case sd_8255:
1392 /* digital i/o subdevice (8255) */
a7f22a84 1393 ret = subdev_8255_init(dev, s, NULL,
0a85b6f0 1394 iobase + layout->sdinfo[n]);
669c930c 1395 if (ret < 0)
e948cb52 1396 return ret;
669c930c 1397
e948cb52
IA
1398 break;
1399 case sd_intr:
1400 /* 'INTERRUPT' subdevice */
1401 if (irq) {
1402 ret = dio200_subdev_intr_init(dev, s,
0a85b6f0
MT
1403 iobase +
1404 DIO200_INT_SCE,
1405 layout->sdinfo[n],
1406 layout->
1407 has_int_sce);
669c930c 1408 if (ret < 0)
e948cb52 1409 return ret;
669c930c 1410
e948cb52
IA
1411 devpriv->intr_sd = n;
1412 } else {
1413 s->type = COMEDI_SUBD_UNUSED;
1414 }
1415 break;
1416 default:
1417 s->type = COMEDI_SUBD_UNUSED;
1418 break;
1419 }
1420 }
1421
1422 sdx = devpriv->intr_sd;
669c930c 1423 if (sdx >= 0 && sdx < dev->n_subdevices)
e948cb52 1424 dev->read_subdev = &dev->subdevices[sdx];
e948cb52
IA
1425
1426 dev->board_name = thisboard->name;
1427
1428 if (irq) {
1429 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1430
5f74ea14 1431 if (request_irq(irq, dio200_interrupt, flags,
e948cb52
IA
1432 DIO200_DRIVER_NAME, dev) >= 0) {
1433 dev->irq = irq;
1434 } else {
1435 printk(KERN_WARNING
0a85b6f0
MT
1436 "comedi%d: warning! irq %u unavailable!\n",
1437 dev->minor, irq);
e948cb52
IA
1438 }
1439 }
1440
1441 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1442 if (thisboard->bustype == isa_bustype) {
1443 printk("(base %#lx) ", iobase);
1444 } else {
1445#ifdef CONFIG_COMEDI_PCI
1446 printk("(pci %s) ", pci_name(pci_dev));
1447#endif
1448 }
669c930c 1449 if (irq)
e948cb52 1450 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
669c930c 1451 else
e948cb52 1452 printk("(no irq) ");
e948cb52
IA
1453
1454 printk("attached\n");
1455
1456 return 1;
1457}
1458
1459/*
1460 * _detach is called to deconfigure a device. It should deallocate
1461 * resources.
1462 * This function is also called when _attach() fails, so it should be
1463 * careful not to release resources that were not necessarily
1464 * allocated by _attach(). dev->private and dev->subdevices are
1465 * deallocated automatically by the core.
1466 */
da91b269 1467static int dio200_detach(struct comedi_device *dev)
e948cb52 1468{
af105ad3 1469 const struct dio200_layout_struct *layout;
e948cb52
IA
1470 unsigned n;
1471
1472 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
0a85b6f0 1473 DIO200_DRIVER_NAME);
e948cb52 1474
669c930c 1475 if (dev->irq)
5f74ea14 1476 free_irq(dev->irq, dev);
e948cb52
IA
1477 if (dev->subdevices) {
1478 layout = thislayout;
1479 for (n = 0; n < dev->n_subdevices; n++) {
34c43922 1480 struct comedi_subdevice *s = &dev->subdevices[n];
e948cb52
IA
1481 switch (layout->sdtype[n]) {
1482 case sd_8254:
1483 dio200_subdev_8254_cleanup(dev, s);
1484 break;
1485 case sd_8255:
1486 subdev_8255_cleanup(dev, s);
1487 break;
1488 case sd_intr:
1489 dio200_subdev_intr_cleanup(dev, s);
1490 break;
1491 default:
1492 break;
1493 }
1494 }
1495 }
1496 if (devpriv) {
1497#ifdef CONFIG_COMEDI_PCI
1498 if (devpriv->pci_dev) {
669c930c 1499 if (dev->iobase)
e948cb52 1500 comedi_pci_disable(devpriv->pci_dev);
e948cb52
IA
1501 pci_dev_put(devpriv->pci_dev);
1502 } else
1503#endif
1504 {
669c930c 1505 if (dev->iobase)
e948cb52 1506 release_region(dev->iobase, DIO200_IO_SIZE);
e948cb52
IA
1507 }
1508 }
669c930c 1509 if (dev->board_name)
e948cb52 1510 printk(KERN_INFO "comedi%d: %s removed\n",
0a85b6f0 1511 dev->minor, dev->board_name);
e948cb52
IA
1512
1513 return 0;
1514}
90f703d3
AT
1515
1516MODULE_AUTHOR("Comedi http://www.comedi.org");
1517MODULE_DESCRIPTION("Comedi low-level driver");
1518MODULE_LICENSE("GPL");
This page took 0.22642 seconds and 5 git commands to generate.