]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/staging/comedi/drivers/amplc_dio200.c
Merge branch 'perf-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[net-next-2.6.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
499COMEDI_INITCLEANUP(driver_amplc_dio200);
500#endif
501
502/*
503 * This function looks for a PCI device matching the requested board name,
504 * bus and slot.
505 */
506#ifdef CONFIG_COMEDI_PCI
507static int
da91b269 508dio200_find_pci(struct comedi_device *dev, int bus, int slot,
0a85b6f0 509 struct pci_dev **pci_dev_p)
e948cb52
IA
510{
511 struct pci_dev *pci_dev = NULL;
512
513 *pci_dev_p = NULL;
514
515 /* Look for matching PCI device. */
516 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
0a85b6f0
MT
517 pci_dev != NULL;
518 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
519 PCI_ANY_ID, pci_dev)) {
e948cb52
IA
520 /* If bus/slot specified, check them. */
521 if (bus || slot) {
522 if (bus != pci_dev->bus->number
0a85b6f0 523 || slot != PCI_SLOT(pci_dev->devfn))
e948cb52
IA
524 continue;
525 }
526 if (thisboard->model == anypci_model) {
527 /* Match any supported model. */
528 int i;
529
530 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
531 if (dio200_boards[i].bustype != pci_bustype)
532 continue;
533 if (pci_dev->device == dio200_boards[i].devid) {
534 /* Change board_ptr to matched board. */
535 dev->board_ptr = &dio200_boards[i];
536 break;
537 }
538 }
539 if (i == ARRAY_SIZE(dio200_boards))
540 continue;
541 } else {
542 /* Match specific model name. */
543 if (pci_dev->device != thisboard->devid)
544 continue;
545 }
546
547 /* Found a match. */
548 *pci_dev_p = pci_dev;
549 return 0;
550 }
551 /* No match found. */
552 if (bus || slot) {
553 printk(KERN_ERR
0a85b6f0
MT
554 "comedi%d: error! no %s found at pci %02x:%02x!\n",
555 dev->minor, thisboard->name, bus, slot);
e948cb52
IA
556 } else {
557 printk(KERN_ERR "comedi%d: error! no %s found!\n",
0a85b6f0 558 dev->minor, thisboard->name);
e948cb52
IA
559 }
560 return -EIO;
561}
562#endif
563
564/*
565 * This function checks and requests an I/O region, reporting an error
566 * if there is a conflict.
567 */
568static int
569dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
570{
571 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
572 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
0a85b6f0 573 minor, from, extent);
e948cb52
IA
574 return -EIO;
575 }
576 return 0;
577}
578
579/*
580 * 'insn_bits' function for an 'INTERRUPT' subdevice.
581 */
582static int
0a85b6f0
MT
583dio200_subdev_intr_insn_bits(struct comedi_device *dev,
584 struct comedi_subdevice *s,
585 struct comedi_insn *insn, unsigned int *data)
e948cb52 586{
d9752ee0 587 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
588
589 if (subpriv->has_int_sce) {
590 /* Just read the interrupt status register. */
591 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
592 } else {
593 /* No interrupt status register. */
594 data[0] = 0;
595 }
596
597 return 2;
598}
599
600/*
601 * Called to stop acquisition for an 'INTERRUPT' subdevice.
602 */
0a85b6f0
MT
603static void dio200_stop_intr(struct comedi_device *dev,
604 struct comedi_subdevice *s)
e948cb52 605{
d9752ee0 606 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
607
608 subpriv->active = 0;
609 subpriv->enabled_isns = 0;
669c930c 610 if (subpriv->has_int_sce)
e948cb52 611 outb(0, subpriv->iobase);
e948cb52
IA
612}
613
614/*
615 * Called to start acquisition for an 'INTERRUPT' subdevice.
616 */
0a85b6f0
MT
617static int dio200_start_intr(struct comedi_device *dev,
618 struct comedi_subdevice *s)
e948cb52
IA
619{
620 unsigned int n;
621 unsigned isn_bits;
d9752ee0 622 struct dio200_subdev_intr *subpriv = s->private;
ea6d0d4c 623 struct comedi_cmd *cmd = &s->async->cmd;
e948cb52
IA
624 int retval = 0;
625
626 if (!subpriv->continuous && subpriv->stopcount == 0) {
627 /* An empty acquisition! */
628 s->async->events |= COMEDI_CB_EOA;
629 subpriv->active = 0;
630 retval = 1;
631 } else {
632 /* Determine interrupt sources to enable. */
633 isn_bits = 0;
634 if (cmd->chanlist) {
669c930c 635 for (n = 0; n < cmd->chanlist_len; n++)
e948cb52 636 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
e948cb52
IA
637 }
638 isn_bits &= subpriv->valid_isns;
639 /* Enable interrupt sources. */
640 subpriv->enabled_isns = isn_bits;
669c930c 641 if (subpriv->has_int_sce)
e948cb52 642 outb(isn_bits, subpriv->iobase);
e948cb52
IA
643 }
644
645 return retval;
646}
647
648/*
649 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
650 */
651static int
da91b269 652dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 653 unsigned int trignum)
e948cb52 654{
d9752ee0 655 struct dio200_subdev_intr *subpriv;
e948cb52
IA
656 unsigned long flags;
657 int event = 0;
658
659 if (trignum != 0)
660 return -EINVAL;
661
662 subpriv = s->private;
663
5f74ea14 664 spin_lock_irqsave(&subpriv->spinlock, flags);
a7f22a84 665 s->async->inttrig = NULL;
669c930c 666 if (subpriv->active)
e948cb52 667 event = dio200_start_intr(dev, s);
669c930c 668
5f74ea14 669 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 670
669c930c 671 if (event)
e948cb52 672 comedi_event(dev, s);
e948cb52
IA
673
674 return 1;
675}
676
677/*
678 * This is called from the interrupt service routine to handle a read
679 * scan on an 'INTERRUPT' subdevice.
680 */
0a85b6f0
MT
681static int dio200_handle_read_intr(struct comedi_device *dev,
682 struct comedi_subdevice *s)
e948cb52 683{
d9752ee0 684 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
685 unsigned triggered;
686 unsigned intstat;
687 unsigned cur_enabled;
688 unsigned int oldevents;
689 unsigned long flags;
690
691 triggered = 0;
692
5f74ea14 693 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
694 oldevents = s->async->events;
695 if (subpriv->has_int_sce) {
696 /*
697 * Collect interrupt sources that have triggered and disable
698 * them temporarily. Loop around until no extra interrupt
699 * sources have triggered, at which point, the valid part of
700 * the interrupt status register will read zero, clearing the
701 * cause of the interrupt.
702 *
703 * Mask off interrupt sources already seen to avoid infinite
704 * loop in case of misconfiguration.
705 */
706 cur_enabled = subpriv->enabled_isns;
707 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
0a85b6f0 708 & ~triggered)) != 0) {
e948cb52
IA
709 triggered |= intstat;
710 cur_enabled &= ~triggered;
711 outb(cur_enabled, subpriv->iobase);
712 }
713 } else {
714 /*
715 * No interrupt status register. Assume the single interrupt
716 * source has triggered.
717 */
718 triggered = subpriv->enabled_isns;
719 }
720
721 if (triggered) {
722 /*
723 * Some interrupt sources have triggered and have been
724 * temporarily disabled to clear the cause of the interrupt.
725 *
726 * Reenable them NOW to minimize the time they are disabled.
727 */
728 cur_enabled = subpriv->enabled_isns;
669c930c 729 if (subpriv->has_int_sce)
e948cb52 730 outb(cur_enabled, subpriv->iobase);
e948cb52
IA
731
732 if (subpriv->active) {
733 /*
734 * The command is still active.
735 *
736 * Ignore interrupt sources that the command isn't
737 * interested in (just in case there's a race
738 * condition).
739 */
740 if (triggered & subpriv->enabled_isns) {
741 /* Collect scan data. */
790c5541 742 short val;
e948cb52
IA
743 unsigned int n, ch, len;
744
745 val = 0;
746 len = s->async->cmd.chanlist_len;
747 for (n = 0; n < len; n++) {
748 ch = CR_CHAN(s->async->cmd.chanlist[n]);
669c930c 749 if (triggered & (1U << ch))
e948cb52 750 val |= (1U << n);
e948cb52
IA
751 }
752 /* Write the scan to the buffer. */
753 if (comedi_buf_put(s->async, val)) {
754 s->async->events |= (COMEDI_CB_BLOCK |
0a85b6f0 755 COMEDI_CB_EOS);
e948cb52
IA
756 } else {
757 /* Error! Stop acquisition. */
758 dio200_stop_intr(dev, s);
759 s->async->events |= COMEDI_CB_ERROR
0a85b6f0 760 | COMEDI_CB_OVERFLOW;
e948cb52
IA
761 comedi_error(dev, "buffer overflow");
762 }
763
764 /* Check for end of acquisition. */
765 if (!subpriv->continuous) {
766 /* stop_src == TRIG_COUNT */
767 if (subpriv->stopcount > 0) {
768 subpriv->stopcount--;
769 if (subpriv->stopcount == 0) {
770 s->async->events |=
0a85b6f0 771 COMEDI_CB_EOA;
e948cb52 772 dio200_stop_intr(dev,
0a85b6f0 773 s);
e948cb52
IA
774 }
775 }
776 }
777 }
778 }
779 }
5f74ea14 780 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 781
669c930c 782 if (oldevents != s->async->events)
e948cb52 783 comedi_event(dev, s);
e948cb52
IA
784
785 return (triggered != 0);
786}
787
788/*
789 * 'cancel' function for an 'INTERRUPT' subdevice.
790 */
0a85b6f0
MT
791static int dio200_subdev_intr_cancel(struct comedi_device *dev,
792 struct comedi_subdevice *s)
e948cb52 793{
d9752ee0 794 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
795 unsigned long flags;
796
5f74ea14 797 spin_lock_irqsave(&subpriv->spinlock, flags);
669c930c 798 if (subpriv->active)
e948cb52 799 dio200_stop_intr(dev, s);
669c930c 800
5f74ea14 801 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
802
803 return 0;
804}
805
806/*
807 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
808 */
809static int
0a85b6f0
MT
810dio200_subdev_intr_cmdtest(struct comedi_device *dev,
811 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e948cb52
IA
812{
813 int err = 0;
814 unsigned int tmp;
815
816 /* step 1: make sure trigger sources are trivially valid */
817
818 tmp = cmd->start_src;
819 cmd->start_src &= (TRIG_NOW | TRIG_INT);
820 if (!cmd->start_src || tmp != cmd->start_src)
821 err++;
822
823 tmp = cmd->scan_begin_src;
824 cmd->scan_begin_src &= TRIG_EXT;
825 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
826 err++;
827
828 tmp = cmd->convert_src;
829 cmd->convert_src &= TRIG_NOW;
830 if (!cmd->convert_src || tmp != cmd->convert_src)
831 err++;
832
833 tmp = cmd->scan_end_src;
834 cmd->scan_end_src &= TRIG_COUNT;
835 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
836 err++;
837
838 tmp = cmd->stop_src;
839 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
840 if (!cmd->stop_src || tmp != cmd->stop_src)
841 err++;
842
843 if (err)
844 return 1;
845
669c930c
BA
846 /* step 2: make sure trigger sources are unique and mutually
847 compatible */
e948cb52
IA
848
849 /* these tests are true if more than one _src bit is set */
850 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
851 err++;
852 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
853 err++;
854 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
855 err++;
856 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
857 err++;
858 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
859 err++;
860
861 if (err)
862 return 2;
863
864 /* step 3: make sure arguments are trivially compatible */
865
866 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
867 if (cmd->start_arg != 0) {
868 cmd->start_arg = 0;
869 err++;
870 }
871
872 /* cmd->scan_begin_src == TRIG_EXT */
873 if (cmd->scan_begin_arg != 0) {
874 cmd->scan_begin_arg = 0;
875 err++;
876 }
877
878 /* cmd->convert_src == TRIG_NOW */
879 if (cmd->convert_arg != 0) {
880 cmd->convert_arg = 0;
881 err++;
882 }
883
884 /* cmd->scan_end_src == TRIG_COUNT */
885 if (cmd->scan_end_arg != cmd->chanlist_len) {
886 cmd->scan_end_arg = cmd->chanlist_len;
887 err++;
888 }
889
890 switch (cmd->stop_src) {
891 case TRIG_COUNT:
892 /* any count allowed */
893 break;
894 case TRIG_NONE:
895 if (cmd->stop_arg != 0) {
896 cmd->stop_arg = 0;
897 err++;
898 }
899 break;
900 default:
901 break;
902 }
903
904 if (err)
905 return 3;
906
907 /* step 4: fix up any arguments */
908
909 /* if (err) return 4; */
910
911 return 0;
912}
913
914/*
915 * 'do_cmd' function for an 'INTERRUPT' subdevice.
916 */
0a85b6f0
MT
917static int dio200_subdev_intr_cmd(struct comedi_device *dev,
918 struct comedi_subdevice *s)
e948cb52 919{
ea6d0d4c 920 struct comedi_cmd *cmd = &s->async->cmd;
d9752ee0 921 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
922 unsigned long flags;
923 int event = 0;
924
5f74ea14 925 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
926 subpriv->active = 1;
927
928 /* Set up end of acquisition. */
929 switch (cmd->stop_src) {
930 case TRIG_COUNT:
931 subpriv->continuous = 0;
932 subpriv->stopcount = cmd->stop_arg;
933 break;
934 default:
935 /* TRIG_NONE */
936 subpriv->continuous = 1;
937 subpriv->stopcount = 0;
938 break;
939 }
940
941 /* Set up start of acquisition. */
942 switch (cmd->start_src) {
943 case TRIG_INT:
944 s->async->inttrig = dio200_inttrig_start_intr;
945 break;
946 default:
947 /* TRIG_NOW */
948 event = dio200_start_intr(dev, s);
949 break;
950 }
5f74ea14 951 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 952
669c930c 953 if (event)
e948cb52 954 comedi_event(dev, s);
e948cb52
IA
955
956 return 0;
957}
958
959/*
960 * This function initializes an 'INTERRUPT' subdevice.
961 */
962static int
da91b269 963dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
964 unsigned long iobase, unsigned valid_isns,
965 int has_int_sce)
e948cb52 966{
d9752ee0 967 struct dio200_subdev_intr *subpriv;
e948cb52
IA
968
969 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
970 if (!subpriv) {
971 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 972 dev->minor);
e948cb52
IA
973 return -ENOMEM;
974 }
975 subpriv->iobase = iobase;
976 subpriv->has_int_sce = has_int_sce;
977 subpriv->valid_isns = valid_isns;
978 spin_lock_init(&subpriv->spinlock);
979
669c930c 980 if (has_int_sce)
e948cb52 981 outb(0, subpriv->iobase); /* Disable interrupt sources. */
e948cb52
IA
982
983 s->private = subpriv;
984 s->type = COMEDI_SUBD_DI;
985 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
986 if (has_int_sce) {
987 s->n_chan = DIO200_MAX_ISNS;
988 s->len_chanlist = DIO200_MAX_ISNS;
989 } else {
990 /* No interrupt source register. Support single channel. */
991 s->n_chan = 1;
992 s->len_chanlist = 1;
993 }
994 s->range_table = &range_digital;
995 s->maxdata = 1;
996 s->insn_bits = dio200_subdev_intr_insn_bits;
997 s->do_cmdtest = dio200_subdev_intr_cmdtest;
998 s->do_cmd = dio200_subdev_intr_cmd;
999 s->cancel = dio200_subdev_intr_cancel;
1000
1001 return 0;
1002}
1003
1004/*
1005 * This function cleans up an 'INTERRUPT' subdevice.
1006 */
1007static void
0a85b6f0
MT
1008dio200_subdev_intr_cleanup(struct comedi_device *dev,
1009 struct comedi_subdevice *s)
e948cb52 1010{
d9752ee0 1011 struct dio200_subdev_intr *subpriv = s->private;
669c930c 1012 kfree(subpriv);
e948cb52
IA
1013}
1014
1015/*
1016 * Interrupt service routine.
1017 */
70265d24 1018static irqreturn_t dio200_interrupt(int irq, void *d)
e948cb52 1019{
71b5f4f1 1020 struct comedi_device *dev = d;
e948cb52
IA
1021 int handled;
1022
669c930c 1023 if (!dev->attached)
e948cb52 1024 return IRQ_NONE;
e948cb52
IA
1025
1026 if (devpriv->intr_sd >= 0) {
1027 handled = dio200_handle_read_intr(dev,
0a85b6f0
MT
1028 dev->subdevices +
1029 devpriv->intr_sd);
e948cb52
IA
1030 } else {
1031 handled = 0;
1032 }
1033
1034 return IRQ_RETVAL(handled);
1035}
1036
1037/*
1038 * Handle 'insn_read' for an '8254' counter subdevice.
1039 */
1040static int
da91b269 1041dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1042 struct comedi_insn *insn, unsigned int *data)
e948cb52 1043{
93ba42e9 1044 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1045 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1046 unsigned long flags;
e948cb52 1047
ee4063fa 1048 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1049 data[0] = i8254_read(subpriv->iobase, 0, chan);
ee4063fa 1050 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1051
1052 return 1;
1053}
1054
1055/*
1056 * Handle 'insn_write' for an '8254' counter subdevice.
1057 */
1058static int
da91b269 1059dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1060 struct comedi_insn *insn, unsigned int *data)
e948cb52 1061{
93ba42e9 1062 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1063 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1064 unsigned long flags;
e948cb52 1065
ee4063fa 1066 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1067 i8254_write(subpriv->iobase, 0, chan, data[0]);
ee4063fa 1068 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1069
1070 return 1;
1071}
1072
1073/*
1074 * Set gate source for an '8254' counter subdevice channel.
1075 */
1076static int
0a85b6f0
MT
1077dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1078 unsigned int counter_number, unsigned int gate_src)
e948cb52
IA
1079{
1080 unsigned char byte;
1081
1082 if (!subpriv->has_clk_gat_sce)
1083 return -1;
1084 if (counter_number > 2)
1085 return -1;
1086 if (gate_src > 7)
1087 return -1;
1088
1089 subpriv->gate_src[counter_number] = gate_src;
1090 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1091 outb(byte, subpriv->gat_sce_iobase);
1092
1093 return 0;
1094}
1095
1096/*
1097 * Get gate source for an '8254' counter subdevice channel.
1098 */
1099static int
0a85b6f0
MT
1100dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1101 unsigned int counter_number)
e948cb52
IA
1102{
1103 if (!subpriv->has_clk_gat_sce)
1104 return -1;
1105 if (counter_number > 2)
1106 return -1;
1107
1108 return subpriv->gate_src[counter_number];
1109}
1110
1111/*
1112 * Set clock source for an '8254' counter subdevice channel.
1113 */
1114static int
0a85b6f0
MT
1115dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1116 unsigned int counter_number, unsigned int clock_src)
e948cb52
IA
1117{
1118 unsigned char byte;
1119
1120 if (!subpriv->has_clk_gat_sce)
1121 return -1;
1122 if (counter_number > 2)
1123 return -1;
1124 if (clock_src > 7)
1125 return -1;
1126
1127 subpriv->clock_src[counter_number] = clock_src;
1128 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1129 outb(byte, subpriv->clk_sce_iobase);
1130
1131 return 0;
1132}
1133
1134/*
1135 * Get clock source for an '8254' counter subdevice channel.
1136 */
1137static int
0a85b6f0
MT
1138dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1139 unsigned int counter_number, unsigned int *period_ns)
e948cb52
IA
1140{
1141 unsigned clock_src;
1142
1143 if (!subpriv->has_clk_gat_sce)
1144 return -1;
1145 if (counter_number > 2)
1146 return -1;
1147
1148 clock_src = subpriv->clock_src[counter_number];
1149 *period_ns = clock_period[clock_src];
1150 return clock_src;
1151}
1152
1153/*
1154 * Handle 'insn_config' for an '8254' counter subdevice.
1155 */
1156static int
da91b269 1157dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1158 struct comedi_insn *insn, unsigned int *data)
e948cb52 1159{
93ba42e9 1160 struct dio200_subdev_8254 *subpriv = s->private;
ee4063fa 1161 int ret = 0;
e948cb52 1162 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1163 unsigned long flags;
e948cb52 1164
ee4063fa 1165 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
1166 switch (data[0]) {
1167 case INSN_CONFIG_SET_COUNTER_MODE:
1168 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1169 if (ret < 0)
ee4063fa 1170 ret = -EINVAL;
e948cb52
IA
1171 break;
1172 case INSN_CONFIG_8254_READ_STATUS:
1173 data[1] = i8254_status(subpriv->iobase, 0, chan);
1174 break;
1175 case INSN_CONFIG_SET_GATE_SRC:
1176 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1177 if (ret < 0)
ee4063fa 1178 ret = -EINVAL;
e948cb52
IA
1179 break;
1180 case INSN_CONFIG_GET_GATE_SRC:
1181 ret = dio200_get_gate_src(subpriv, chan);
ee4063fa
IA
1182 if (ret < 0) {
1183 ret = -EINVAL;
1184 break;
1185 }
e948cb52
IA
1186 data[2] = ret;
1187 break;
1188 case INSN_CONFIG_SET_CLOCK_SRC:
1189 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1190 if (ret < 0)
ee4063fa 1191 ret = -EINVAL;
e948cb52
IA
1192 break;
1193 case INSN_CONFIG_GET_CLOCK_SRC:
1194 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
ee4063fa
IA
1195 if (ret < 0) {
1196 ret = -EINVAL;
1197 break;
1198 }
e948cb52
IA
1199 data[1] = ret;
1200 break;
1201 default:
ee4063fa 1202 ret = -EINVAL;
e948cb52
IA
1203 break;
1204 }
ee4063fa
IA
1205 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1206 return ret < 0 ? ret : insn->n;
e948cb52
IA
1207}
1208
1209/*
1210 * This function initializes an '8254' counter subdevice.
1211 *
1212 * Note: iobase is the base address of the board, not the subdevice;
1213 * offset is the offset to the 8254 chip.
1214 */
1215static int
da91b269 1216dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
1217 unsigned long iobase, unsigned offset,
1218 int has_clk_gat_sce)
e948cb52 1219{
93ba42e9 1220 struct dio200_subdev_8254 *subpriv;
e948cb52
IA
1221 unsigned int chan;
1222
1223 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1224 if (!subpriv) {
1225 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1226 dev->minor);
e948cb52
IA
1227 return -ENOMEM;
1228 }
1229
1230 s->private = subpriv;
1231 s->type = COMEDI_SUBD_COUNTER;
1232 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1233 s->n_chan = 3;
1234 s->maxdata = 0xFFFF;
1235 s->insn_read = dio200_subdev_8254_read;
1236 s->insn_write = dio200_subdev_8254_write;
1237 s->insn_config = dio200_subdev_8254_config;
1238
ee4063fa 1239 spin_lock_init(&subpriv->spinlock);
e948cb52
IA
1240 subpriv->iobase = offset + iobase;
1241 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1242 if (has_clk_gat_sce) {
1243 /* Derive CLK_SCE and GAT_SCE register offsets from
1244 * 8254 offset. */
1245 subpriv->clk_sce_iobase =
0a85b6f0 1246 DIO200_XCLK_SCE + (offset >> 3) + iobase;
e948cb52 1247 subpriv->gat_sce_iobase =
0a85b6f0 1248 DIO200_XGAT_SCE + (offset >> 3) + iobase;
e948cb52
IA
1249 subpriv->which = (offset >> 2) & 1;
1250 }
1251
1252 /* Initialize channels. */
1253 for (chan = 0; chan < 3; chan++) {
1254 i8254_set_mode(subpriv->iobase, 0, chan,
0a85b6f0 1255 I8254_MODE0 | I8254_BINARY);
e948cb52
IA
1256 if (subpriv->has_clk_gat_sce) {
1257 /* Gate source 0 is VCC (logic 1). */
1258 dio200_set_gate_src(subpriv, chan, 0);
1259 /* Clock source 0 is the dedicated clock input. */
1260 dio200_set_clock_src(subpriv, chan, 0);
1261 }
1262 }
1263
1264 return 0;
1265}
1266
1267/*
1268 * This function cleans up an '8254' counter subdevice.
1269 */
1270static void
0a85b6f0
MT
1271dio200_subdev_8254_cleanup(struct comedi_device *dev,
1272 struct comedi_subdevice *s)
e948cb52 1273{
d9752ee0 1274 struct dio200_subdev_intr *subpriv = s->private;
669c930c 1275 kfree(subpriv);
e948cb52
IA
1276}
1277
1278/*
1279 * Attach is called by the Comedi core to configure the driver
1280 * for a particular board. If you specified a board_name array
1281 * in the driver structure, dev->board_ptr contains that
1282 * address.
1283 */
da91b269 1284static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
e948cb52 1285{
34c43922 1286 struct comedi_subdevice *s;
e948cb52
IA
1287 unsigned long iobase = 0;
1288 unsigned int irq = 0;
1289#ifdef CONFIG_COMEDI_PCI
1290 struct pci_dev *pci_dev = NULL;
1291 int bus = 0, slot = 0;
1292#endif
af105ad3 1293 const struct dio200_layout_struct *layout;
e948cb52
IA
1294 int share_irq = 0;
1295 int sdx;
1296 unsigned n;
1297 int ret;
1298
1299 printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
0a85b6f0 1300 DIO200_DRIVER_NAME);
e948cb52 1301
c3744138
BP
1302 ret = alloc_private(dev, sizeof(struct dio200_private));
1303 if (ret < 0) {
e948cb52 1304 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1305 dev->minor);
e948cb52
IA
1306 return ret;
1307 }
1308
1309 /* Process options. */
1310 switch (thisboard->bustype) {
1311 case isa_bustype:
1312 iobase = it->options[0];
1313 irq = it->options[1];
1314 share_irq = 0;
1315 break;
1316#ifdef CONFIG_COMEDI_PCI
1317 case pci_bustype:
1318 bus = it->options[0];
1319 slot = it->options[1];
1320 share_irq = 1;
1321
c3744138
BP
1322 ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1323 if (ret < 0)
e948cb52
IA
1324 return ret;
1325 devpriv->pci_dev = pci_dev;
1326 break;
1327#endif
1328 default:
1329 printk(KERN_ERR
0a85b6f0
MT
1330 "comedi%d: %s: BUG! cannot determine board type!\n",
1331 dev->minor, DIO200_DRIVER_NAME);
e948cb52
IA
1332 return -EINVAL;
1333 break;
1334 }
1335
1336 devpriv->intr_sd = -1;
1337
1338 /* Enable device and reserve I/O spaces. */
1339#ifdef CONFIG_COMEDI_PCI
1340 if (pci_dev) {
1341 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1342 if (ret < 0) {
1343 printk(KERN_ERR
0a85b6f0
MT
1344 "comedi%d: error! cannot enable PCI device and request regions!\n",
1345 dev->minor);
e948cb52
IA
1346 return ret;
1347 }
1348 iobase = pci_resource_start(pci_dev, 2);
1349 irq = pci_dev->irq;
1350 } else
1351#endif
1352 {
1353 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
669c930c 1354 if (ret < 0)
e948cb52 1355 return ret;
e948cb52
IA
1356 }
1357 dev->iobase = iobase;
1358
1359 layout = thislayout;
c3744138
BP
1360
1361 ret = alloc_subdevices(dev, layout->n_subdevs);
1362 if (ret < 0) {
e948cb52 1363 printk(KERN_ERR "comedi%d: error! out of memory!\n",
0a85b6f0 1364 dev->minor);
e948cb52
IA
1365 return ret;
1366 }
1367
1368 for (n = 0; n < dev->n_subdevices; n++) {
1369 s = &dev->subdevices[n];
1370 switch (layout->sdtype[n]) {
1371 case sd_8254:
1372 /* counter subdevice (8254) */
1373 ret = dio200_subdev_8254_init(dev, s, iobase,
0a85b6f0
MT
1374 layout->sdinfo[n],
1375 layout->has_clk_gat_sce);
669c930c 1376 if (ret < 0)
e948cb52 1377 return ret;
669c930c 1378
e948cb52
IA
1379 break;
1380 case sd_8255:
1381 /* digital i/o subdevice (8255) */
a7f22a84 1382 ret = subdev_8255_init(dev, s, NULL,
0a85b6f0 1383 iobase + layout->sdinfo[n]);
669c930c 1384 if (ret < 0)
e948cb52 1385 return ret;
669c930c 1386
e948cb52
IA
1387 break;
1388 case sd_intr:
1389 /* 'INTERRUPT' subdevice */
1390 if (irq) {
1391 ret = dio200_subdev_intr_init(dev, s,
0a85b6f0
MT
1392 iobase +
1393 DIO200_INT_SCE,
1394 layout->sdinfo[n],
1395 layout->
1396 has_int_sce);
669c930c 1397 if (ret < 0)
e948cb52 1398 return ret;
669c930c 1399
e948cb52
IA
1400 devpriv->intr_sd = n;
1401 } else {
1402 s->type = COMEDI_SUBD_UNUSED;
1403 }
1404 break;
1405 default:
1406 s->type = COMEDI_SUBD_UNUSED;
1407 break;
1408 }
1409 }
1410
1411 sdx = devpriv->intr_sd;
669c930c 1412 if (sdx >= 0 && sdx < dev->n_subdevices)
e948cb52 1413 dev->read_subdev = &dev->subdevices[sdx];
e948cb52
IA
1414
1415 dev->board_name = thisboard->name;
1416
1417 if (irq) {
1418 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1419
5f74ea14 1420 if (request_irq(irq, dio200_interrupt, flags,
e948cb52
IA
1421 DIO200_DRIVER_NAME, dev) >= 0) {
1422 dev->irq = irq;
1423 } else {
1424 printk(KERN_WARNING
0a85b6f0
MT
1425 "comedi%d: warning! irq %u unavailable!\n",
1426 dev->minor, irq);
e948cb52
IA
1427 }
1428 }
1429
1430 printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1431 if (thisboard->bustype == isa_bustype) {
1432 printk("(base %#lx) ", iobase);
1433 } else {
1434#ifdef CONFIG_COMEDI_PCI
1435 printk("(pci %s) ", pci_name(pci_dev));
1436#endif
1437 }
669c930c 1438 if (irq)
e948cb52 1439 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
669c930c 1440 else
e948cb52 1441 printk("(no irq) ");
e948cb52
IA
1442
1443 printk("attached\n");
1444
1445 return 1;
1446}
1447
1448/*
1449 * _detach is called to deconfigure a device. It should deallocate
1450 * resources.
1451 * This function is also called when _attach() fails, so it should be
1452 * careful not to release resources that were not necessarily
1453 * allocated by _attach(). dev->private and dev->subdevices are
1454 * deallocated automatically by the core.
1455 */
da91b269 1456static int dio200_detach(struct comedi_device *dev)
e948cb52 1457{
af105ad3 1458 const struct dio200_layout_struct *layout;
e948cb52
IA
1459 unsigned n;
1460
1461 printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
0a85b6f0 1462 DIO200_DRIVER_NAME);
e948cb52 1463
669c930c 1464 if (dev->irq)
5f74ea14 1465 free_irq(dev->irq, dev);
e948cb52
IA
1466 if (dev->subdevices) {
1467 layout = thislayout;
1468 for (n = 0; n < dev->n_subdevices; n++) {
34c43922 1469 struct comedi_subdevice *s = &dev->subdevices[n];
e948cb52
IA
1470 switch (layout->sdtype[n]) {
1471 case sd_8254:
1472 dio200_subdev_8254_cleanup(dev, s);
1473 break;
1474 case sd_8255:
1475 subdev_8255_cleanup(dev, s);
1476 break;
1477 case sd_intr:
1478 dio200_subdev_intr_cleanup(dev, s);
1479 break;
1480 default:
1481 break;
1482 }
1483 }
1484 }
1485 if (devpriv) {
1486#ifdef CONFIG_COMEDI_PCI
1487 if (devpriv->pci_dev) {
669c930c 1488 if (dev->iobase)
e948cb52 1489 comedi_pci_disable(devpriv->pci_dev);
e948cb52
IA
1490 pci_dev_put(devpriv->pci_dev);
1491 } else
1492#endif
1493 {
669c930c 1494 if (dev->iobase)
e948cb52 1495 release_region(dev->iobase, DIO200_IO_SIZE);
e948cb52
IA
1496 }
1497 }
669c930c 1498 if (dev->board_name)
e948cb52 1499 printk(KERN_INFO "comedi%d: %s removed\n",
0a85b6f0 1500 dev->minor, dev->board_name);
e948cb52
IA
1501
1502 return 0;
1503}