amplc_dio200.c revision 7b0be12b26d86ea2bd5079f0d723289e2f5a43a9
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
51		    PC218E         PC212E      PC215E/PCI215
52		 -------------  -------------  -------------
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
62		    PC214E      PC272E/PCI272
63		 -------------  -------------
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
99	connector.  (N.B. for other values, the counter channel's CLKn
100	pin on the SK1 connector is an output!)
101      1.  Internal 10 MHz clock.
102      2.  Internal 1 MHz clock.
103      3.  Internal 100 kHz clock.
104      4.  Internal 10 kHz clock.
105      5.  Internal 1 kHz clock.
106      6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
107      7.  Ext Clock, the counter chip's dedicated Ext Clock input from
108	the SK1 connector.  This pin is shared by all three counter
109	channels on the chip.
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
123	connector.  (N.B. for other values, the counter channel's GATn
124	pin on the SK1 connector is an output!)
125      3.  /OUT n-2, the inverted output of counter channel n-2 (see note
126	2 below).
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
156		    PC218E         PC212E      PC215E/PCI215
157		 -------------  -------------  -------------
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
166		    PC214E      PC272E/PCI272
167		 -------------  -------------
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
204is packed into a short value, one bit per requested channel, in the
205order they appear in the channel list.
206*/
207
208#include <linux/interrupt.h>
209#include <linux/slab.h>
210
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 */
221#define PCI_VENDOR_ID_AMPLICON 0x14dc
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
284struct dio200_board {
285	const char *name;
286	unsigned short devid;
287	enum dio200_bustype bustype;
288	enum dio200_model model;
289	enum dio200_layout layout;
290};
291
292static const struct dio200_board dio200_boards[] = {
293	{
294	 .name = "pc212e",
295	 .bustype = isa_bustype,
296	 .model = pc212e_model,
297	 .layout = pc212_layout,
298	 },
299	{
300	 .name = "pc214e",
301	 .bustype = isa_bustype,
302	 .model = pc214e_model,
303	 .layout = pc214_layout,
304	 },
305	{
306	 .name = "pc215e",
307	 .bustype = isa_bustype,
308	 .model = pc215e_model,
309	 .layout = pc215_layout,
310	 },
311#ifdef CONFIG_COMEDI_PCI
312	{
313	 .name = "pci215",
314	 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
315	 .bustype = pci_bustype,
316	 .model = pci215_model,
317	 .layout = pc215_layout,
318	 },
319#endif
320	{
321	 .name = "pc218e",
322	 .bustype = isa_bustype,
323	 .model = pc218e_model,
324	 .layout = pc218_layout,
325	 },
326	{
327	 .name = "pc272e",
328	 .bustype = isa_bustype,
329	 .model = pc272e_model,
330	 .layout = pc272_layout,
331	 },
332#ifdef CONFIG_COMEDI_PCI
333	{
334	 .name = "pci272",
335	 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
336	 .bustype = pci_bustype,
337	 .model = pci272_model,
338	 .layout = pc272_layout,
339	 },
340#endif
341#ifdef CONFIG_COMEDI_PCI
342	{
343	 .name = DIO200_DRIVER_NAME,
344	 .devid = PCI_DEVICE_ID_INVALID,
345	 .bustype = pci_bustype,
346	 .model = anypci_model,	/* wildcard */
347	 },
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
361struct dio200_layout_struct {
362	unsigned short n_subdevs;	/* number of subdevices */
363	unsigned char sdtype[DIO200_MAX_SUBDEVS];	/* enum dio200_sdtype */
364	unsigned char sdinfo[DIO200_MAX_SUBDEVS];	/* depends on sdtype */
365	char has_int_sce;	/* has interrupt enable/status register */
366	char has_clk_gat_sce;	/* has clock/gate selection registers */
367};
368
369static const struct dio200_layout_struct dio200_layouts[] = {
370	[pc212_layout] = {
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			  },
380	[pc214_layout] = {
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			  },
388	[pc215_layout] = {
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			  },
397	[pc218_layout] = {
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			  },
408	[pc272_layout] = {
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			  },
416};
417
418/*
419 * PCI driver table.
420 */
421
422#ifdef CONFIG_COMEDI_PCI
423static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
424	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
425	{ PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
426	{0}
427};
428
429MODULE_DEVICE_TABLE(pci, dio200_pci_table);
430#endif /* CONFIG_COMEDI_PCI */
431
432/*
433 * Useful for shorthand access to the particular board structure
434 */
435#define thisboard ((const struct dio200_board *)dev->board_ptr)
436#define thislayout (&dio200_layouts[((struct dio200_board *) \
437		    dev->board_ptr)->layout])
438
439/* this structure is for data unique to this hardware driver.  If
440   several hardware drivers keep similar information in this structure,
441   feel free to suggest moving the variable to the struct comedi_device struct.
442 */
443struct dio200_private {
444#ifdef CONFIG_COMEDI_PCI
445	struct pci_dev *pci_dev;	/* PCI device */
446#endif
447	int intr_sd;
448};
449
450#define devpriv ((struct dio200_private *)dev->private)
451
452struct dio200_subdev_8254 {
453	unsigned long iobase;	/* Counter base address */
454	unsigned long clk_sce_iobase;	/* CLK_SCE base address */
455	unsigned long gat_sce_iobase;	/* GAT_SCE base address */
456	int which;		/* Bit 5 of CLK_SCE or GAT_SCE */
457	int has_clk_gat_sce;
458	unsigned clock_src[3];	/* Current clock sources */
459	unsigned gate_src[3];	/* Current gate sources */
460	spinlock_t spinlock;
461};
462
463struct dio200_subdev_intr {
464	unsigned long iobase;
465	spinlock_t spinlock;
466	int active;
467	int has_int_sce;
468	unsigned int valid_isns;
469	unsigned int enabled_isns;
470	unsigned int stopcount;
471	int continuous;
472};
473
474/*
475 * The struct comedi_driver structure tells the Comedi core module
476 * which functions to call to configure/deconfigure (attach/detach)
477 * the board, and also about the kernel module that contains
478 * the device code.
479 */
480static int dio200_attach(struct comedi_device *dev,
481			 struct comedi_devconfig *it);
482static int dio200_detach(struct comedi_device *dev);
483static struct comedi_driver driver_amplc_dio200 = {
484	.driver_name = DIO200_DRIVER_NAME,
485	.module = THIS_MODULE,
486	.attach = dio200_attach,
487	.detach = dio200_detach,
488	.board_name = &dio200_boards[0].name,
489	.offset = sizeof(struct dio200_board),
490	.num_names = ARRAY_SIZE(dio200_boards),
491};
492
493#ifdef CONFIG_COMEDI_PCI
494static int __devinit driver_amplc_dio200_pci_probe(struct pci_dev *dev,
495						   const struct pci_device_id
496						   *ent)
497{
498	return comedi_pci_auto_config(dev, driver_amplc_dio200.driver_name);
499}
500
501static void __devexit driver_amplc_dio200_pci_remove(struct pci_dev *dev)
502{
503	comedi_pci_auto_unconfig(dev);
504}
505
506static struct pci_driver driver_amplc_dio200_pci_driver = {
507	.id_table = dio200_pci_table,
508	.probe = &driver_amplc_dio200_pci_probe,
509	.remove = __devexit_p(&driver_amplc_dio200_pci_remove)
510};
511
512static int __init driver_amplc_dio200_init_module(void)
513{
514	int retval;
515
516	retval = comedi_driver_register(&driver_amplc_dio200);
517	if (retval < 0)
518		return retval;
519
520	driver_amplc_dio200_pci_driver.name =
521	    (char *)driver_amplc_dio200.driver_name;
522	return pci_register_driver(&driver_amplc_dio200_pci_driver);
523}
524
525static void __exit driver_amplc_dio200_cleanup_module(void)
526{
527	pci_unregister_driver(&driver_amplc_dio200_pci_driver);
528	comedi_driver_unregister(&driver_amplc_dio200);
529}
530
531module_init(driver_amplc_dio200_init_module);
532module_exit(driver_amplc_dio200_cleanup_module);
533#else
534static int __init driver_amplc_dio200_init_module(void)
535{
536	return comedi_driver_register(&driver_amplc_dio200);
537}
538
539static void __exit driver_amplc_dio200_cleanup_module(void)
540{
541	comedi_driver_unregister(&driver_amplc_dio200);
542}
543
544module_init(driver_amplc_dio200_init_module);
545module_exit(driver_amplc_dio200_cleanup_module);
546#endif
547
548/*
549 * This function looks for a PCI device matching the requested board name,
550 * bus and slot.
551 */
552#ifdef CONFIG_COMEDI_PCI
553static int
554dio200_find_pci(struct comedi_device *dev, int bus, int slot,
555		struct pci_dev **pci_dev_p)
556{
557	struct pci_dev *pci_dev = NULL;
558
559	*pci_dev_p = NULL;
560
561	/* Look for matching PCI device. */
562	for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
563	     pci_dev != NULL;
564	     pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
565				      PCI_ANY_ID, pci_dev)) {
566		/* If bus/slot specified, check them. */
567		if (bus || slot) {
568			if (bus != pci_dev->bus->number
569			    || slot != PCI_SLOT(pci_dev->devfn))
570				continue;
571		}
572		if (thisboard->model == anypci_model) {
573			/* Match any supported model. */
574			int i;
575
576			for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
577				if (dio200_boards[i].bustype != pci_bustype)
578					continue;
579				if (pci_dev->device == dio200_boards[i].devid) {
580					/* Change board_ptr to matched board. */
581					dev->board_ptr = &dio200_boards[i];
582					break;
583				}
584			}
585			if (i == ARRAY_SIZE(dio200_boards))
586				continue;
587		} else {
588			/* Match specific model name. */
589			if (pci_dev->device != thisboard->devid)
590				continue;
591		}
592
593		/* Found a match. */
594		*pci_dev_p = pci_dev;
595		return 0;
596	}
597	/* No match found. */
598	if (bus || slot) {
599		printk(KERN_ERR
600		       "comedi%d: error! no %s found at pci %02x:%02x!\n",
601		       dev->minor, thisboard->name, bus, slot);
602	} else {
603		printk(KERN_ERR "comedi%d: error! no %s found!\n",
604		       dev->minor, thisboard->name);
605	}
606	return -EIO;
607}
608#endif
609
610/*
611 * This function checks and requests an I/O region, reporting an error
612 * if there is a conflict.
613 */
614static int
615dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
616{
617	if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
618		printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
619		       minor, from, extent);
620		return -EIO;
621	}
622	return 0;
623}
624
625/*
626 * 'insn_bits' function for an 'INTERRUPT' subdevice.
627 */
628static int
629dio200_subdev_intr_insn_bits(struct comedi_device *dev,
630			     struct comedi_subdevice *s,
631			     struct comedi_insn *insn, unsigned int *data)
632{
633	struct dio200_subdev_intr *subpriv = s->private;
634
635	if (subpriv->has_int_sce) {
636		/* Just read the interrupt status register.  */
637		data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
638	} else {
639		/* No interrupt status register. */
640		data[0] = 0;
641	}
642
643	return 2;
644}
645
646/*
647 * Called to stop acquisition for an 'INTERRUPT' subdevice.
648 */
649static void dio200_stop_intr(struct comedi_device *dev,
650			     struct comedi_subdevice *s)
651{
652	struct dio200_subdev_intr *subpriv = s->private;
653
654	subpriv->active = 0;
655	subpriv->enabled_isns = 0;
656	if (subpriv->has_int_sce)
657		outb(0, subpriv->iobase);
658}
659
660/*
661 * Called to start acquisition for an 'INTERRUPT' subdevice.
662 */
663static int dio200_start_intr(struct comedi_device *dev,
664			     struct comedi_subdevice *s)
665{
666	unsigned int n;
667	unsigned isn_bits;
668	struct dio200_subdev_intr *subpriv = s->private;
669	struct comedi_cmd *cmd = &s->async->cmd;
670	int retval = 0;
671
672	if (!subpriv->continuous && subpriv->stopcount == 0) {
673		/* An empty acquisition! */
674		s->async->events |= COMEDI_CB_EOA;
675		subpriv->active = 0;
676		retval = 1;
677	} else {
678		/* Determine interrupt sources to enable. */
679		isn_bits = 0;
680		if (cmd->chanlist) {
681			for (n = 0; n < cmd->chanlist_len; n++)
682				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
683		}
684		isn_bits &= subpriv->valid_isns;
685		/* Enable interrupt sources. */
686		subpriv->enabled_isns = isn_bits;
687		if (subpriv->has_int_sce)
688			outb(isn_bits, subpriv->iobase);
689	}
690
691	return retval;
692}
693
694/*
695 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
696 */
697static int
698dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
699			  unsigned int trignum)
700{
701	struct dio200_subdev_intr *subpriv;
702	unsigned long flags;
703	int event = 0;
704
705	if (trignum != 0)
706		return -EINVAL;
707
708	subpriv = s->private;
709
710	spin_lock_irqsave(&subpriv->spinlock, flags);
711	s->async->inttrig = NULL;
712	if (subpriv->active)
713		event = dio200_start_intr(dev, s);
714
715	spin_unlock_irqrestore(&subpriv->spinlock, flags);
716
717	if (event)
718		comedi_event(dev, s);
719
720	return 1;
721}
722
723/*
724 * This is called from the interrupt service routine to handle a read
725 * scan on an 'INTERRUPT' subdevice.
726 */
727static int dio200_handle_read_intr(struct comedi_device *dev,
728				   struct comedi_subdevice *s)
729{
730	struct dio200_subdev_intr *subpriv = s->private;
731	unsigned triggered;
732	unsigned intstat;
733	unsigned cur_enabled;
734	unsigned int oldevents;
735	unsigned long flags;
736
737	triggered = 0;
738
739	spin_lock_irqsave(&subpriv->spinlock, flags);
740	oldevents = s->async->events;
741	if (subpriv->has_int_sce) {
742		/*
743		 * Collect interrupt sources that have triggered and disable
744		 * them temporarily.  Loop around until no extra interrupt
745		 * sources have triggered, at which point, the valid part of
746		 * the interrupt status register will read zero, clearing the
747		 * cause of the interrupt.
748		 *
749		 * Mask off interrupt sources already seen to avoid infinite
750		 * loop in case of misconfiguration.
751		 */
752		cur_enabled = subpriv->enabled_isns;
753		while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
754				   & ~triggered)) != 0) {
755			triggered |= intstat;
756			cur_enabled &= ~triggered;
757			outb(cur_enabled, subpriv->iobase);
758		}
759	} else {
760		/*
761		 * No interrupt status register.  Assume the single interrupt
762		 * source has triggered.
763		 */
764		triggered = subpriv->enabled_isns;
765	}
766
767	if (triggered) {
768		/*
769		 * Some interrupt sources have triggered and have been
770		 * temporarily disabled to clear the cause of the interrupt.
771		 *
772		 * Reenable them NOW to minimize the time they are disabled.
773		 */
774		cur_enabled = subpriv->enabled_isns;
775		if (subpriv->has_int_sce)
776			outb(cur_enabled, subpriv->iobase);
777
778		if (subpriv->active) {
779			/*
780			 * The command is still active.
781			 *
782			 * Ignore interrupt sources that the command isn't
783			 * interested in (just in case there's a race
784			 * condition).
785			 */
786			if (triggered & subpriv->enabled_isns) {
787				/* Collect scan data. */
788				short val;
789				unsigned int n, ch, len;
790
791				val = 0;
792				len = s->async->cmd.chanlist_len;
793				for (n = 0; n < len; n++) {
794					ch = CR_CHAN(s->async->cmd.chanlist[n]);
795					if (triggered & (1U << ch))
796						val |= (1U << n);
797				}
798				/* Write the scan to the buffer. */
799				if (comedi_buf_put(s->async, val)) {
800					s->async->events |= (COMEDI_CB_BLOCK |
801							     COMEDI_CB_EOS);
802				} else {
803					/* Error!  Stop acquisition.  */
804					dio200_stop_intr(dev, s);
805					s->async->events |= COMEDI_CB_ERROR
806					    | COMEDI_CB_OVERFLOW;
807					comedi_error(dev, "buffer overflow");
808				}
809
810				/* Check for end of acquisition. */
811				if (!subpriv->continuous) {
812					/* stop_src == TRIG_COUNT */
813					if (subpriv->stopcount > 0) {
814						subpriv->stopcount--;
815						if (subpriv->stopcount == 0) {
816							s->async->events |=
817							    COMEDI_CB_EOA;
818							dio200_stop_intr(dev,
819									 s);
820						}
821					}
822				}
823			}
824		}
825	}
826	spin_unlock_irqrestore(&subpriv->spinlock, flags);
827
828	if (oldevents != s->async->events)
829		comedi_event(dev, s);
830
831	return (triggered != 0);
832}
833
834/*
835 * 'cancel' function for an 'INTERRUPT' subdevice.
836 */
837static int dio200_subdev_intr_cancel(struct comedi_device *dev,
838				     struct comedi_subdevice *s)
839{
840	struct dio200_subdev_intr *subpriv = s->private;
841	unsigned long flags;
842
843	spin_lock_irqsave(&subpriv->spinlock, flags);
844	if (subpriv->active)
845		dio200_stop_intr(dev, s);
846
847	spin_unlock_irqrestore(&subpriv->spinlock, flags);
848
849	return 0;
850}
851
852/*
853 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
854 */
855static int
856dio200_subdev_intr_cmdtest(struct comedi_device *dev,
857			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
858{
859	int err = 0;
860	unsigned int tmp;
861
862	/* step 1: make sure trigger sources are trivially valid */
863
864	tmp = cmd->start_src;
865	cmd->start_src &= (TRIG_NOW | TRIG_INT);
866	if (!cmd->start_src || tmp != cmd->start_src)
867		err++;
868
869	tmp = cmd->scan_begin_src;
870	cmd->scan_begin_src &= TRIG_EXT;
871	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
872		err++;
873
874	tmp = cmd->convert_src;
875	cmd->convert_src &= TRIG_NOW;
876	if (!cmd->convert_src || tmp != cmd->convert_src)
877		err++;
878
879	tmp = cmd->scan_end_src;
880	cmd->scan_end_src &= TRIG_COUNT;
881	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
882		err++;
883
884	tmp = cmd->stop_src;
885	cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
886	if (!cmd->stop_src || tmp != cmd->stop_src)
887		err++;
888
889	if (err)
890		return 1;
891
892	/* step 2: make sure trigger sources are unique and mutually
893		   compatible */
894
895	/* these tests are true if more than one _src bit is set */
896	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
897		err++;
898	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
899		err++;
900	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
901		err++;
902	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
903		err++;
904	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
905		err++;
906
907	if (err)
908		return 2;
909
910	/* step 3: make sure arguments are trivially compatible */
911
912	/* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
913	if (cmd->start_arg != 0) {
914		cmd->start_arg = 0;
915		err++;
916	}
917
918	/* cmd->scan_begin_src == TRIG_EXT */
919	if (cmd->scan_begin_arg != 0) {
920		cmd->scan_begin_arg = 0;
921		err++;
922	}
923
924	/* cmd->convert_src == TRIG_NOW */
925	if (cmd->convert_arg != 0) {
926		cmd->convert_arg = 0;
927		err++;
928	}
929
930	/* cmd->scan_end_src == TRIG_COUNT */
931	if (cmd->scan_end_arg != cmd->chanlist_len) {
932		cmd->scan_end_arg = cmd->chanlist_len;
933		err++;
934	}
935
936	switch (cmd->stop_src) {
937	case TRIG_COUNT:
938		/* any count allowed */
939		break;
940	case TRIG_NONE:
941		if (cmd->stop_arg != 0) {
942			cmd->stop_arg = 0;
943			err++;
944		}
945		break;
946	default:
947		break;
948	}
949
950	if (err)
951		return 3;
952
953	/* step 4: fix up any arguments */
954
955	/* if (err) return 4; */
956
957	return 0;
958}
959
960/*
961 * 'do_cmd' function for an 'INTERRUPT' subdevice.
962 */
963static int dio200_subdev_intr_cmd(struct comedi_device *dev,
964				  struct comedi_subdevice *s)
965{
966	struct comedi_cmd *cmd = &s->async->cmd;
967	struct dio200_subdev_intr *subpriv = s->private;
968	unsigned long flags;
969	int event = 0;
970
971	spin_lock_irqsave(&subpriv->spinlock, flags);
972	subpriv->active = 1;
973
974	/* Set up end of acquisition. */
975	switch (cmd->stop_src) {
976	case TRIG_COUNT:
977		subpriv->continuous = 0;
978		subpriv->stopcount = cmd->stop_arg;
979		break;
980	default:
981		/* TRIG_NONE */
982		subpriv->continuous = 1;
983		subpriv->stopcount = 0;
984		break;
985	}
986
987	/* Set up start of acquisition. */
988	switch (cmd->start_src) {
989	case TRIG_INT:
990		s->async->inttrig = dio200_inttrig_start_intr;
991		break;
992	default:
993		/* TRIG_NOW */
994		event = dio200_start_intr(dev, s);
995		break;
996	}
997	spin_unlock_irqrestore(&subpriv->spinlock, flags);
998
999	if (event)
1000		comedi_event(dev, s);
1001
1002	return 0;
1003}
1004
1005/*
1006 * This function initializes an 'INTERRUPT' subdevice.
1007 */
1008static int
1009dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
1010			unsigned long iobase, unsigned valid_isns,
1011			int has_int_sce)
1012{
1013	struct dio200_subdev_intr *subpriv;
1014
1015	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1016	if (!subpriv) {
1017		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1018		       dev->minor);
1019		return -ENOMEM;
1020	}
1021	subpriv->iobase = iobase;
1022	subpriv->has_int_sce = has_int_sce;
1023	subpriv->valid_isns = valid_isns;
1024	spin_lock_init(&subpriv->spinlock);
1025
1026	if (has_int_sce)
1027		outb(0, subpriv->iobase);	/* Disable interrupt sources. */
1028
1029	s->private = subpriv;
1030	s->type = COMEDI_SUBD_DI;
1031	s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1032	if (has_int_sce) {
1033		s->n_chan = DIO200_MAX_ISNS;
1034		s->len_chanlist = DIO200_MAX_ISNS;
1035	} else {
1036		/* No interrupt source register.  Support single channel. */
1037		s->n_chan = 1;
1038		s->len_chanlist = 1;
1039	}
1040	s->range_table = &range_digital;
1041	s->maxdata = 1;
1042	s->insn_bits = dio200_subdev_intr_insn_bits;
1043	s->do_cmdtest = dio200_subdev_intr_cmdtest;
1044	s->do_cmd = dio200_subdev_intr_cmd;
1045	s->cancel = dio200_subdev_intr_cancel;
1046
1047	return 0;
1048}
1049
1050/*
1051 * This function cleans up an 'INTERRUPT' subdevice.
1052 */
1053static void
1054dio200_subdev_intr_cleanup(struct comedi_device *dev,
1055			   struct comedi_subdevice *s)
1056{
1057	struct dio200_subdev_intr *subpriv = s->private;
1058	kfree(subpriv);
1059}
1060
1061/*
1062 * Interrupt service routine.
1063 */
1064static irqreturn_t dio200_interrupt(int irq, void *d)
1065{
1066	struct comedi_device *dev = d;
1067	int handled;
1068
1069	if (!dev->attached)
1070		return IRQ_NONE;
1071
1072	if (devpriv->intr_sd >= 0) {
1073		handled = dio200_handle_read_intr(dev,
1074						  dev->subdevices +
1075						  devpriv->intr_sd);
1076	} else {
1077		handled = 0;
1078	}
1079
1080	return IRQ_RETVAL(handled);
1081}
1082
1083/*
1084 * Handle 'insn_read' for an '8254' counter subdevice.
1085 */
1086static int
1087dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1088			struct comedi_insn *insn, unsigned int *data)
1089{
1090	struct dio200_subdev_8254 *subpriv = s->private;
1091	int chan = CR_CHAN(insn->chanspec);
1092	unsigned long flags;
1093
1094	spin_lock_irqsave(&subpriv->spinlock, flags);
1095	data[0] = i8254_read(subpriv->iobase, 0, chan);
1096	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1097
1098	return 1;
1099}
1100
1101/*
1102 * Handle 'insn_write' for an '8254' counter subdevice.
1103 */
1104static int
1105dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1106			 struct comedi_insn *insn, unsigned int *data)
1107{
1108	struct dio200_subdev_8254 *subpriv = s->private;
1109	int chan = CR_CHAN(insn->chanspec);
1110	unsigned long flags;
1111
1112	spin_lock_irqsave(&subpriv->spinlock, flags);
1113	i8254_write(subpriv->iobase, 0, chan, data[0]);
1114	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1115
1116	return 1;
1117}
1118
1119/*
1120 * Set gate source for an '8254' counter subdevice channel.
1121 */
1122static int
1123dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1124		    unsigned int counter_number, unsigned int gate_src)
1125{
1126	unsigned char byte;
1127
1128	if (!subpriv->has_clk_gat_sce)
1129		return -1;
1130	if (counter_number > 2)
1131		return -1;
1132	if (gate_src > 7)
1133		return -1;
1134
1135	subpriv->gate_src[counter_number] = gate_src;
1136	byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1137	outb(byte, subpriv->gat_sce_iobase);
1138
1139	return 0;
1140}
1141
1142/*
1143 * Get gate source for an '8254' counter subdevice channel.
1144 */
1145static int
1146dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1147		    unsigned int counter_number)
1148{
1149	if (!subpriv->has_clk_gat_sce)
1150		return -1;
1151	if (counter_number > 2)
1152		return -1;
1153
1154	return subpriv->gate_src[counter_number];
1155}
1156
1157/*
1158 * Set clock source for an '8254' counter subdevice channel.
1159 */
1160static int
1161dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1162		     unsigned int counter_number, unsigned int clock_src)
1163{
1164	unsigned char byte;
1165
1166	if (!subpriv->has_clk_gat_sce)
1167		return -1;
1168	if (counter_number > 2)
1169		return -1;
1170	if (clock_src > 7)
1171		return -1;
1172
1173	subpriv->clock_src[counter_number] = clock_src;
1174	byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1175	outb(byte, subpriv->clk_sce_iobase);
1176
1177	return 0;
1178}
1179
1180/*
1181 * Get clock source for an '8254' counter subdevice channel.
1182 */
1183static int
1184dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1185		     unsigned int counter_number, unsigned int *period_ns)
1186{
1187	unsigned clock_src;
1188
1189	if (!subpriv->has_clk_gat_sce)
1190		return -1;
1191	if (counter_number > 2)
1192		return -1;
1193
1194	clock_src = subpriv->clock_src[counter_number];
1195	*period_ns = clock_period[clock_src];
1196	return clock_src;
1197}
1198
1199/*
1200 * Handle 'insn_config' for an '8254' counter subdevice.
1201 */
1202static int
1203dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1204			  struct comedi_insn *insn, unsigned int *data)
1205{
1206	struct dio200_subdev_8254 *subpriv = s->private;
1207	int ret = 0;
1208	int chan = CR_CHAN(insn->chanspec);
1209	unsigned long flags;
1210
1211	spin_lock_irqsave(&subpriv->spinlock, flags);
1212	switch (data[0]) {
1213	case INSN_CONFIG_SET_COUNTER_MODE:
1214		ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1215		if (ret < 0)
1216			ret = -EINVAL;
1217		break;
1218	case INSN_CONFIG_8254_READ_STATUS:
1219		data[1] = i8254_status(subpriv->iobase, 0, chan);
1220		break;
1221	case INSN_CONFIG_SET_GATE_SRC:
1222		ret = dio200_set_gate_src(subpriv, chan, data[2]);
1223		if (ret < 0)
1224			ret = -EINVAL;
1225		break;
1226	case INSN_CONFIG_GET_GATE_SRC:
1227		ret = dio200_get_gate_src(subpriv, chan);
1228		if (ret < 0) {
1229			ret = -EINVAL;
1230			break;
1231		}
1232		data[2] = ret;
1233		break;
1234	case INSN_CONFIG_SET_CLOCK_SRC:
1235		ret = dio200_set_clock_src(subpriv, chan, data[1]);
1236		if (ret < 0)
1237			ret = -EINVAL;
1238		break;
1239	case INSN_CONFIG_GET_CLOCK_SRC:
1240		ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1241		if (ret < 0) {
1242			ret = -EINVAL;
1243			break;
1244		}
1245		data[1] = ret;
1246		break;
1247	default:
1248		ret = -EINVAL;
1249		break;
1250	}
1251	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1252	return ret < 0 ? ret : insn->n;
1253}
1254
1255/*
1256 * This function initializes an '8254' counter subdevice.
1257 *
1258 * Note: iobase is the base address of the board, not the subdevice;
1259 * offset is the offset to the 8254 chip.
1260 */
1261static int
1262dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1263			unsigned long iobase, unsigned offset,
1264			int has_clk_gat_sce)
1265{
1266	struct dio200_subdev_8254 *subpriv;
1267	unsigned int chan;
1268
1269	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1270	if (!subpriv) {
1271		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1272		       dev->minor);
1273		return -ENOMEM;
1274	}
1275
1276	s->private = subpriv;
1277	s->type = COMEDI_SUBD_COUNTER;
1278	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1279	s->n_chan = 3;
1280	s->maxdata = 0xFFFF;
1281	s->insn_read = dio200_subdev_8254_read;
1282	s->insn_write = dio200_subdev_8254_write;
1283	s->insn_config = dio200_subdev_8254_config;
1284
1285	spin_lock_init(&subpriv->spinlock);
1286	subpriv->iobase = offset + iobase;
1287	subpriv->has_clk_gat_sce = has_clk_gat_sce;
1288	if (has_clk_gat_sce) {
1289		/* Derive CLK_SCE and GAT_SCE register offsets from
1290		 * 8254 offset. */
1291		subpriv->clk_sce_iobase =
1292		    DIO200_XCLK_SCE + (offset >> 3) + iobase;
1293		subpriv->gat_sce_iobase =
1294		    DIO200_XGAT_SCE + (offset >> 3) + iobase;
1295		subpriv->which = (offset >> 2) & 1;
1296	}
1297
1298	/* Initialize channels. */
1299	for (chan = 0; chan < 3; chan++) {
1300		i8254_set_mode(subpriv->iobase, 0, chan,
1301			       I8254_MODE0 | I8254_BINARY);
1302		if (subpriv->has_clk_gat_sce) {
1303			/* Gate source 0 is VCC (logic 1). */
1304			dio200_set_gate_src(subpriv, chan, 0);
1305			/* Clock source 0 is the dedicated clock input. */
1306			dio200_set_clock_src(subpriv, chan, 0);
1307		}
1308	}
1309
1310	return 0;
1311}
1312
1313/*
1314 * This function cleans up an '8254' counter subdevice.
1315 */
1316static void
1317dio200_subdev_8254_cleanup(struct comedi_device *dev,
1318			   struct comedi_subdevice *s)
1319{
1320	struct dio200_subdev_intr *subpriv = s->private;
1321	kfree(subpriv);
1322}
1323
1324/*
1325 * Attach is called by the Comedi core to configure the driver
1326 * for a particular board.  If you specified a board_name array
1327 * in the driver structure, dev->board_ptr contains that
1328 * address.
1329 */
1330static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1331{
1332	struct comedi_subdevice *s;
1333	unsigned long iobase = 0;
1334	unsigned int irq = 0;
1335#ifdef CONFIG_COMEDI_PCI
1336	struct pci_dev *pci_dev = NULL;
1337	int bus = 0, slot = 0;
1338#endif
1339	const struct dio200_layout_struct *layout;
1340	int share_irq = 0;
1341	int sdx;
1342	unsigned n;
1343	int ret;
1344
1345	printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1346	       DIO200_DRIVER_NAME);
1347
1348	ret = alloc_private(dev, sizeof(struct dio200_private));
1349	if (ret < 0) {
1350		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1351		       dev->minor);
1352		return ret;
1353	}
1354
1355	/* Process options. */
1356	switch (thisboard->bustype) {
1357	case isa_bustype:
1358		iobase = it->options[0];
1359		irq = it->options[1];
1360		share_irq = 0;
1361		break;
1362#ifdef CONFIG_COMEDI_PCI
1363	case pci_bustype:
1364		bus = it->options[0];
1365		slot = it->options[1];
1366		share_irq = 1;
1367
1368		ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1369		if (ret < 0)
1370			return ret;
1371		devpriv->pci_dev = pci_dev;
1372		break;
1373#endif
1374	default:
1375		printk(KERN_ERR
1376		       "comedi%d: %s: BUG! cannot determine board type!\n",
1377		       dev->minor, DIO200_DRIVER_NAME);
1378		return -EINVAL;
1379		break;
1380	}
1381
1382	devpriv->intr_sd = -1;
1383
1384	/* Enable device and reserve I/O spaces. */
1385#ifdef CONFIG_COMEDI_PCI
1386	if (pci_dev) {
1387		ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1388		if (ret < 0) {
1389			printk(KERN_ERR
1390			       "comedi%d: error! cannot enable PCI device and request regions!\n",
1391			       dev->minor);
1392			return ret;
1393		}
1394		iobase = pci_resource_start(pci_dev, 2);
1395		irq = pci_dev->irq;
1396	} else
1397#endif
1398	{
1399		ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1400		if (ret < 0)
1401			return ret;
1402	}
1403	dev->iobase = iobase;
1404
1405	layout = thislayout;
1406
1407	ret = alloc_subdevices(dev, layout->n_subdevs);
1408	if (ret < 0) {
1409		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1410		       dev->minor);
1411		return ret;
1412	}
1413
1414	for (n = 0; n < dev->n_subdevices; n++) {
1415		s = &dev->subdevices[n];
1416		switch (layout->sdtype[n]) {
1417		case sd_8254:
1418			/* counter subdevice (8254) */
1419			ret = dio200_subdev_8254_init(dev, s, iobase,
1420						      layout->sdinfo[n],
1421						      layout->has_clk_gat_sce);
1422			if (ret < 0)
1423				return ret;
1424
1425			break;
1426		case sd_8255:
1427			/* digital i/o subdevice (8255) */
1428			ret = subdev_8255_init(dev, s, NULL,
1429					       iobase + layout->sdinfo[n]);
1430			if (ret < 0)
1431				return ret;
1432
1433			break;
1434		case sd_intr:
1435			/* 'INTERRUPT' subdevice */
1436			if (irq) {
1437				ret = dio200_subdev_intr_init(dev, s,
1438							      iobase +
1439							      DIO200_INT_SCE,
1440							      layout->sdinfo[n],
1441							      layout->
1442							      has_int_sce);
1443				if (ret < 0)
1444					return ret;
1445
1446				devpriv->intr_sd = n;
1447			} else {
1448				s->type = COMEDI_SUBD_UNUSED;
1449			}
1450			break;
1451		default:
1452			s->type = COMEDI_SUBD_UNUSED;
1453			break;
1454		}
1455	}
1456
1457	sdx = devpriv->intr_sd;
1458	if (sdx >= 0 && sdx < dev->n_subdevices)
1459		dev->read_subdev = &dev->subdevices[sdx];
1460
1461	dev->board_name = thisboard->name;
1462
1463	if (irq) {
1464		unsigned long flags = share_irq ? IRQF_SHARED : 0;
1465
1466		if (request_irq(irq, dio200_interrupt, flags,
1467				DIO200_DRIVER_NAME, dev) >= 0) {
1468			dev->irq = irq;
1469		} else {
1470			printk(KERN_WARNING
1471			       "comedi%d: warning! irq %u unavailable!\n",
1472			       dev->minor, irq);
1473		}
1474	}
1475
1476	printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1477	if (thisboard->bustype == isa_bustype) {
1478		printk("(base %#lx) ", iobase);
1479	} else {
1480#ifdef CONFIG_COMEDI_PCI
1481		printk("(pci %s) ", pci_name(pci_dev));
1482#endif
1483	}
1484	if (irq)
1485		printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1486	else
1487		printk("(no irq) ");
1488
1489	printk("attached\n");
1490
1491	return 1;
1492}
1493
1494/*
1495 * _detach is called to deconfigure a device.  It should deallocate
1496 * resources.
1497 * This function is also called when _attach() fails, so it should be
1498 * careful not to release resources that were not necessarily
1499 * allocated by _attach().  dev->private and dev->subdevices are
1500 * deallocated automatically by the core.
1501 */
1502static int dio200_detach(struct comedi_device *dev)
1503{
1504	const struct dio200_layout_struct *layout;
1505	unsigned n;
1506
1507	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1508	       DIO200_DRIVER_NAME);
1509
1510	if (dev->irq)
1511		free_irq(dev->irq, dev);
1512	if (dev->subdevices) {
1513		layout = thislayout;
1514		for (n = 0; n < dev->n_subdevices; n++) {
1515			struct comedi_subdevice *s = &dev->subdevices[n];
1516			switch (layout->sdtype[n]) {
1517			case sd_8254:
1518				dio200_subdev_8254_cleanup(dev, s);
1519				break;
1520			case sd_8255:
1521				subdev_8255_cleanup(dev, s);
1522				break;
1523			case sd_intr:
1524				dio200_subdev_intr_cleanup(dev, s);
1525				break;
1526			default:
1527				break;
1528			}
1529		}
1530	}
1531	if (devpriv) {
1532#ifdef CONFIG_COMEDI_PCI
1533		if (devpriv->pci_dev) {
1534			if (dev->iobase)
1535				comedi_pci_disable(devpriv->pci_dev);
1536			pci_dev_put(devpriv->pci_dev);
1537		} else
1538#endif
1539		{
1540			if (dev->iobase)
1541				release_region(dev->iobase, DIO200_IO_SIZE);
1542		}
1543	}
1544	if (dev->board_name)
1545		printk(KERN_INFO "comedi%d: %s removed\n",
1546		       dev->minor, dev->board_name);
1547
1548	return 0;
1549}
1550
1551MODULE_AUTHOR("Comedi http://www.comedi.org");
1552MODULE_DESCRIPTION("Comedi low-level driver");
1553MODULE_LICENSE("GPL");
1554