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