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