amplc_dio200.c revision 7114a28011f9d5f3d981731ad341177c21f9d948
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	{
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}
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 */
438#define thisboard ((const struct dio200_board *)dev->board_ptr)
439#define thislayout (&dio200_layouts[((struct dio200_board *) \
440		    dev->board_ptr)->layout])
441
442/* this structure is for data unique to this hardware driver.  If
443   several hardware drivers keep similar information in this structure,
444   feel free to suggest moving the variable to the struct comedi_device struct.
445 */
446struct dio200_private {
447#ifdef CONFIG_COMEDI_PCI
448	struct pci_dev *pci_dev;	/* PCI device */
449#endif
450	int intr_sd;
451};
452
453#define devpriv ((struct dio200_private *)dev->private)
454
455struct dio200_subdev_8254 {
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 */
463	spinlock_t spinlock;
464};
465
466struct dio200_subdev_intr {
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;
475};
476
477/*
478 * The struct comedi_driver structure tells the Comedi core module
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 */
483static int dio200_attach(struct comedi_device *dev,
484			 struct comedi_devconfig *it);
485static int dio200_detach(struct comedi_device *dev);
486static struct comedi_driver driver_amplc_dio200 = {
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),
493	.num_names = ARRAY_SIZE(dio200_boards),
494};
495
496#ifdef CONFIG_COMEDI_PCI
497COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
498#else
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);
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
519dio200_find_pci(struct comedi_device *dev, int bus, int slot,
520		struct pci_dev **pci_dev_p)
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);
528	     pci_dev != NULL;
529	     pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
530				      PCI_ANY_ID, pci_dev)) {
531		/* If bus/slot specified, check them. */
532		if (bus || slot) {
533			if (bus != pci_dev->bus->number
534			    || slot != PCI_SLOT(pci_dev->devfn))
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
565		       "comedi%d: error! no %s found at pci %02x:%02x!\n",
566		       dev->minor, thisboard->name, bus, slot);
567	} else {
568		printk(KERN_ERR "comedi%d: error! no %s found!\n",
569		       dev->minor, thisboard->name);
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",
584		       minor, from, extent);
585		return -EIO;
586	}
587	return 0;
588}
589
590/*
591 * 'insn_bits' function for an 'INTERRUPT' subdevice.
592 */
593static int
594dio200_subdev_intr_insn_bits(struct comedi_device *dev,
595			     struct comedi_subdevice *s,
596			     struct comedi_insn *insn, unsigned int *data)
597{
598	struct dio200_subdev_intr *subpriv = s->private;
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 */
614static void dio200_stop_intr(struct comedi_device *dev,
615			     struct comedi_subdevice *s)
616{
617	struct dio200_subdev_intr *subpriv = s->private;
618
619	subpriv->active = 0;
620	subpriv->enabled_isns = 0;
621	if (subpriv->has_int_sce)
622		outb(0, subpriv->iobase);
623}
624
625/*
626 * Called to start acquisition for an 'INTERRUPT' subdevice.
627 */
628static int dio200_start_intr(struct comedi_device *dev,
629			     struct comedi_subdevice *s)
630{
631	unsigned int n;
632	unsigned isn_bits;
633	struct dio200_subdev_intr *subpriv = s->private;
634	struct comedi_cmd *cmd = &s->async->cmd;
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) {
646			for (n = 0; n < cmd->chanlist_len; n++)
647				isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
648		}
649		isn_bits &= subpriv->valid_isns;
650		/* Enable interrupt sources. */
651		subpriv->enabled_isns = isn_bits;
652		if (subpriv->has_int_sce)
653			outb(isn_bits, subpriv->iobase);
654	}
655
656	return retval;
657}
658
659/*
660 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
661 */
662static int
663dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
664			  unsigned int trignum)
665{
666	struct dio200_subdev_intr *subpriv;
667	unsigned long flags;
668	int event = 0;
669
670	if (trignum != 0)
671		return -EINVAL;
672
673	subpriv = s->private;
674
675	spin_lock_irqsave(&subpriv->spinlock, flags);
676	s->async->inttrig = NULL;
677	if (subpriv->active)
678		event = dio200_start_intr(dev, s);
679
680	spin_unlock_irqrestore(&subpriv->spinlock, flags);
681
682	if (event)
683		comedi_event(dev, s);
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 */
692static int dio200_handle_read_intr(struct comedi_device *dev,
693				   struct comedi_subdevice *s)
694{
695	struct dio200_subdev_intr *subpriv = s->private;
696	unsigned triggered;
697	unsigned intstat;
698	unsigned cur_enabled;
699	unsigned int oldevents;
700	unsigned long flags;
701
702	triggered = 0;
703
704	spin_lock_irqsave(&subpriv->spinlock, flags);
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
719				   & ~triggered)) != 0) {
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;
740		if (subpriv->has_int_sce)
741			outb(cur_enabled, subpriv->iobase);
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. */
753				short val;
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]);
760					if (triggered & (1U << ch))
761						val |= (1U << n);
762				}
763				/* Write the scan to the buffer. */
764				if (comedi_buf_put(s->async, val)) {
765					s->async->events |= (COMEDI_CB_BLOCK |
766							     COMEDI_CB_EOS);
767				} else {
768					/* Error!  Stop acquisition.  */
769					dio200_stop_intr(dev, s);
770					s->async->events |= COMEDI_CB_ERROR
771					    | COMEDI_CB_OVERFLOW;
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 |=
782							    COMEDI_CB_EOA;
783							dio200_stop_intr(dev,
784									 s);
785						}
786					}
787				}
788			}
789		}
790	}
791	spin_unlock_irqrestore(&subpriv->spinlock, flags);
792
793	if (oldevents != s->async->events)
794		comedi_event(dev, s);
795
796	return (triggered != 0);
797}
798
799/*
800 * 'cancel' function for an 'INTERRUPT' subdevice.
801 */
802static int dio200_subdev_intr_cancel(struct comedi_device *dev,
803				     struct comedi_subdevice *s)
804{
805	struct dio200_subdev_intr *subpriv = s->private;
806	unsigned long flags;
807
808	spin_lock_irqsave(&subpriv->spinlock, flags);
809	if (subpriv->active)
810		dio200_stop_intr(dev, s);
811
812	spin_unlock_irqrestore(&subpriv->spinlock, flags);
813
814	return 0;
815}
816
817/*
818 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
819 */
820static int
821dio200_subdev_intr_cmdtest(struct comedi_device *dev,
822			   struct comedi_subdevice *s, struct comedi_cmd *cmd)
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
857	/* step 2: make sure trigger sources are unique and mutually
858		   compatible */
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 */
928static int dio200_subdev_intr_cmd(struct comedi_device *dev,
929				  struct comedi_subdevice *s)
930{
931	struct comedi_cmd *cmd = &s->async->cmd;
932	struct dio200_subdev_intr *subpriv = s->private;
933	unsigned long flags;
934	int event = 0;
935
936	spin_lock_irqsave(&subpriv->spinlock, flags);
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	}
962	spin_unlock_irqrestore(&subpriv->spinlock, flags);
963
964	if (event)
965		comedi_event(dev, s);
966
967	return 0;
968}
969
970/*
971 * This function initializes an 'INTERRUPT' subdevice.
972 */
973static int
974dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
975			unsigned long iobase, unsigned valid_isns,
976			int has_int_sce)
977{
978	struct dio200_subdev_intr *subpriv;
979
980	subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
981	if (!subpriv) {
982		printk(KERN_ERR "comedi%d: error! out of memory!\n",
983		       dev->minor);
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
991	if (has_int_sce)
992		outb(0, subpriv->iobase);	/* Disable interrupt sources. */
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
1019dio200_subdev_intr_cleanup(struct comedi_device *dev,
1020			   struct comedi_subdevice *s)
1021{
1022	struct dio200_subdev_intr *subpriv = s->private;
1023	kfree(subpriv);
1024}
1025
1026/*
1027 * Interrupt service routine.
1028 */
1029static irqreturn_t dio200_interrupt(int irq, void *d)
1030{
1031	struct comedi_device *dev = d;
1032	int handled;
1033
1034	if (!dev->attached)
1035		return IRQ_NONE;
1036
1037	if (devpriv->intr_sd >= 0) {
1038		handled = dio200_handle_read_intr(dev,
1039						  dev->subdevices +
1040						  devpriv->intr_sd);
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
1052dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
1053			struct comedi_insn *insn, unsigned int *data)
1054{
1055	struct dio200_subdev_8254 *subpriv = s->private;
1056	int chan = CR_CHAN(insn->chanspec);
1057	unsigned long flags;
1058
1059	spin_lock_irqsave(&subpriv->spinlock, flags);
1060	data[0] = i8254_read(subpriv->iobase, 0, chan);
1061	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1062
1063	return 1;
1064}
1065
1066/*
1067 * Handle 'insn_write' for an '8254' counter subdevice.
1068 */
1069static int
1070dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
1071			 struct comedi_insn *insn, unsigned int *data)
1072{
1073	struct dio200_subdev_8254 *subpriv = s->private;
1074	int chan = CR_CHAN(insn->chanspec);
1075	unsigned long flags;
1076
1077	spin_lock_irqsave(&subpriv->spinlock, flags);
1078	i8254_write(subpriv->iobase, 0, chan, data[0]);
1079	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1080
1081	return 1;
1082}
1083
1084/*
1085 * Set gate source for an '8254' counter subdevice channel.
1086 */
1087static int
1088dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1089		    unsigned int counter_number, unsigned int gate_src)
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
1111dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1112		    unsigned int counter_number)
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
1126dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1127		     unsigned int counter_number, unsigned int clock_src)
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
1149dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1150		     unsigned int counter_number, unsigned int *period_ns)
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
1168dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
1169			  struct comedi_insn *insn, unsigned int *data)
1170{
1171	struct dio200_subdev_8254 *subpriv = s->private;
1172	int ret = 0;
1173	int chan = CR_CHAN(insn->chanspec);
1174	unsigned long flags;
1175
1176	spin_lock_irqsave(&subpriv->spinlock, flags);
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)
1181			ret = -EINVAL;
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)
1189			ret = -EINVAL;
1190		break;
1191	case INSN_CONFIG_GET_GATE_SRC:
1192		ret = dio200_get_gate_src(subpriv, chan);
1193		if (ret < 0) {
1194			ret = -EINVAL;
1195			break;
1196		}
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)
1202			ret = -EINVAL;
1203		break;
1204	case INSN_CONFIG_GET_CLOCK_SRC:
1205		ret = dio200_get_clock_src(subpriv, chan, &data[2]);
1206		if (ret < 0) {
1207			ret = -EINVAL;
1208			break;
1209		}
1210		data[1] = ret;
1211		break;
1212	default:
1213		ret = -EINVAL;
1214		break;
1215	}
1216	spin_unlock_irqrestore(&subpriv->spinlock, flags);
1217	return ret < 0 ? ret : insn->n;
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
1227dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
1228			unsigned long iobase, unsigned offset,
1229			int has_clk_gat_sce)
1230{
1231	struct dio200_subdev_8254 *subpriv;
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",
1237		       dev->minor);
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
1250	spin_lock_init(&subpriv->spinlock);
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 =
1257		    DIO200_XCLK_SCE + (offset >> 3) + iobase;
1258		subpriv->gat_sce_iobase =
1259		    DIO200_XGAT_SCE + (offset >> 3) + iobase;
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,
1266			       I8254_MODE0 | I8254_BINARY);
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
1282dio200_subdev_8254_cleanup(struct comedi_device *dev,
1283			   struct comedi_subdevice *s)
1284{
1285	struct dio200_subdev_intr *subpriv = s->private;
1286	kfree(subpriv);
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 */
1295static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1296{
1297	struct comedi_subdevice *s;
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
1304	const struct dio200_layout_struct *layout;
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,
1311	       DIO200_DRIVER_NAME);
1312
1313	ret = alloc_private(dev, sizeof(struct dio200_private));
1314	if (ret < 0) {
1315		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1316		       dev->minor);
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
1333		ret = dio200_find_pci(dev, bus, slot, &pci_dev);
1334		if (ret < 0)
1335			return ret;
1336		devpriv->pci_dev = pci_dev;
1337		break;
1338#endif
1339	default:
1340		printk(KERN_ERR
1341		       "comedi%d: %s: BUG! cannot determine board type!\n",
1342		       dev->minor, DIO200_DRIVER_NAME);
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
1355			       "comedi%d: error! cannot enable PCI device and request regions!\n",
1356			       dev->minor);
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);
1365		if (ret < 0)
1366			return ret;
1367	}
1368	dev->iobase = iobase;
1369
1370	layout = thislayout;
1371
1372	ret = alloc_subdevices(dev, layout->n_subdevs);
1373	if (ret < 0) {
1374		printk(KERN_ERR "comedi%d: error! out of memory!\n",
1375		       dev->minor);
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,
1385						      layout->sdinfo[n],
1386						      layout->has_clk_gat_sce);
1387			if (ret < 0)
1388				return ret;
1389
1390			break;
1391		case sd_8255:
1392			/* digital i/o subdevice (8255) */
1393			ret = subdev_8255_init(dev, s, NULL,
1394					       iobase + layout->sdinfo[n]);
1395			if (ret < 0)
1396				return ret;
1397
1398			break;
1399		case sd_intr:
1400			/* 'INTERRUPT' subdevice */
1401			if (irq) {
1402				ret = dio200_subdev_intr_init(dev, s,
1403							      iobase +
1404							      DIO200_INT_SCE,
1405							      layout->sdinfo[n],
1406							      layout->
1407							      has_int_sce);
1408				if (ret < 0)
1409					return ret;
1410
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;
1423	if (sdx >= 0 && sdx < dev->n_subdevices)
1424		dev->read_subdev = &dev->subdevices[sdx];
1425
1426	dev->board_name = thisboard->name;
1427
1428	if (irq) {
1429		unsigned long flags = share_irq ? IRQF_SHARED : 0;
1430
1431		if (request_irq(irq, dio200_interrupt, flags,
1432				DIO200_DRIVER_NAME, dev) >= 0) {
1433			dev->irq = irq;
1434		} else {
1435			printk(KERN_WARNING
1436			       "comedi%d: warning! irq %u unavailable!\n",
1437			       dev->minor, irq);
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	}
1449	if (irq)
1450		printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1451	else
1452		printk("(no irq) ");
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 */
1467static int dio200_detach(struct comedi_device *dev)
1468{
1469	const struct dio200_layout_struct *layout;
1470	unsigned n;
1471
1472	printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1473	       DIO200_DRIVER_NAME);
1474
1475	if (dev->irq)
1476		free_irq(dev->irq, dev);
1477	if (dev->subdevices) {
1478		layout = thislayout;
1479		for (n = 0; n < dev->n_subdevices; n++) {
1480			struct comedi_subdevice *s = &dev->subdevices[n];
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) {
1499			if (dev->iobase)
1500				comedi_pci_disable(devpriv->pci_dev);
1501			pci_dev_put(devpriv->pci_dev);
1502		} else
1503#endif
1504		{
1505			if (dev->iobase)
1506				release_region(dev->iobase, DIO200_IO_SIZE);
1507		}
1508	}
1509	if (dev->board_name)
1510		printk(KERN_INFO "comedi%d: %s removed\n",
1511		       dev->minor, dev->board_name);
1512
1513	return 0;
1514}
1515
1516MODULE_AUTHOR("Comedi http://www.comedi.org");
1517MODULE_DESCRIPTION("Comedi low-level driver");
1518MODULE_LICENSE("GPL");
1519