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