amplc_dio200: Eliminate 'has_clk_gat_sce' from 'dio200_subdev_8254'.
[comedi.git] / 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 sampl_t value, one bit per requested channel, in the
205 order they appear in the channel list.
206 */
207
208 #include <linux/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 typedef struct dio200_board_struct {
282         const char *name;
283         unsigned short devid;
284         enum dio200_bustype bustype;
285         enum dio200_model model;
286         enum dio200_layout layout;
287 } dio200_board;
288
289 static const 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 typedef 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 } dio200_layout;
365
366 static const dio200_layout 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 dio200_board *)dev->board_ptr)
435 #define thislayout (&dio200_layouts[((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 comedi_device struct.  */
440 typedef struct {
441 #ifdef CONFIG_COMEDI_PCI
442         struct pci_dev *pci_dev;        /* PCI device */
443 #endif
444         int intr_sd;
445 } dio200_private;
446
447 #define devpriv ((dio200_private *)dev->private)
448
449 typedef struct {
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         unsigned clock_src[3];  /* Current clock sources */
455         unsigned gate_src[3];   /* Current gate sources */
456         spinlock_t spinlock;
457 } dio200_subdev_8254;
458
459 typedef struct {
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 } dio200_subdev_intr;
469
470 /*
471  * The 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(comedi_device * dev, comedi_devconfig * it);
477 static int dio200_detach(comedi_device * dev);
478 static 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(dio200_board),
485       num_names:sizeof(dio200_boards) / sizeof(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(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(comedi_device * dev, comedi_subdevice * s,
576         comedi_insn * insn, lsampl_t * data)
577 {
578         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(comedi_device * dev, comedi_subdevice * s)
595 {
596         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(comedi_device * dev, comedi_subdevice * s)
609 {
610         unsigned int n;
611         unsigned isn_bits;
612         dio200_subdev_intr *subpriv = s->private;
613         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(comedi_device * dev, comedi_subdevice * s,
645         unsigned int trignum)
646 {
647         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(comedi_device * dev, comedi_subdevice * s)
675 {
676         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                                 sampl_t 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(comedi_device * dev, comedi_subdevice * s)
787 {
788         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(comedi_device * dev, comedi_subdevice * s,
805         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(comedi_device * dev, comedi_subdevice * s)
911 {
912         comedi_cmd *cmd = &s->async->cmd;
913         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(comedi_device * dev, comedi_subdevice * s,
957         unsigned long iobase, unsigned valid_isns, int has_int_sce)
958 {
959         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(comedi_device * dev, comedi_subdevice * s)
1002 {
1003         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         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(comedi_device * dev, comedi_subdevice * s,
1037         comedi_insn * insn, lsampl_t * data)
1038 {
1039         dio200_subdev_8254 *subpriv = s->private;
1040         int chan = CR_CHAN(insn->chanspec);
1041         unsigned long flags;
1042
1043         if (insn->n == 0)
1044                 return 0;
1045
1046         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1047         data[0] = i8254_read(subpriv->iobase, 0, chan);
1048         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1049
1050         return 1;
1051 }
1052
1053 /*
1054  * Handle 'insn_write' for an '8254' counter subdevice.
1055  */
1056 static int
1057 dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
1058         comedi_insn * insn, lsampl_t * data)
1059 {
1060         dio200_subdev_8254 *subpriv = s->private;
1061         int chan = CR_CHAN(insn->chanspec);
1062         unsigned long flags;
1063
1064         if (insn->n == 0)
1065                 return 0;
1066
1067         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1068         i8254_write(subpriv->iobase, 0, chan, data[0]);
1069         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1070
1071         return 1;
1072 }
1073
1074 /*
1075  * Set gate source for an '8254' counter subdevice channel.
1076  */
1077 static int
1078 dio200_subdev_8254_set_gate_src(comedi_device * dev, comedi_subdevice *s,
1079         unsigned int counter_number, unsigned int gate_src)
1080 {
1081         dio200_subdev_8254 *subpriv = s->private;
1082         unsigned char byte;
1083
1084         if (!thislayout->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_subdev_8254_get_gate_src(comedi_device * dev, comedi_subdevice *s,
1103         unsigned int counter_number)
1104 {
1105         dio200_subdev_8254 *subpriv = s->private;
1106
1107         if (!thislayout->has_clk_gat_sce)
1108                 return -1;
1109         if (counter_number > 2)
1110                 return -1;
1111
1112         return subpriv->gate_src[counter_number];
1113 }
1114
1115 /*
1116  * Set clock source for an '8254' counter subdevice channel.
1117  */
1118 static int
1119 dio200_subdev_8254_set_clock_src(comedi_device * dev, comedi_subdevice *s,
1120         unsigned int counter_number, unsigned int clock_src)
1121 {
1122         dio200_subdev_8254 *subpriv = s->private;
1123         unsigned char byte;
1124
1125         if (!thislayout->has_clk_gat_sce)
1126                 return -1;
1127         if (counter_number > 2)
1128                 return -1;
1129         if (clock_src > 7)
1130                 return -1;
1131
1132         subpriv->clock_src[counter_number] = clock_src;
1133         byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1134         outb(byte, subpriv->clk_sce_iobase);
1135
1136         return 0;
1137 }
1138
1139 /*
1140  * Get clock source for an '8254' counter subdevice channel.
1141  */
1142 static int
1143 dio200_subdev_8254_get_clock_src(comedi_device * dev, comedi_subdevice *s,
1144         unsigned int counter_number, lsampl_t * period_ns)
1145 {
1146         dio200_subdev_8254 *subpriv = s->private;
1147         unsigned clock_src;
1148
1149         if (!thislayout->has_clk_gat_sce)
1150                 return -1;
1151         if (counter_number > 2)
1152                 return -1;
1153
1154         clock_src = subpriv->clock_src[counter_number];
1155         *period_ns = clock_period[clock_src];
1156         return clock_src;
1157 }
1158
1159 /*
1160  * Handle 'insn_config' for an '8254' counter subdevice.
1161  */
1162 static int
1163 dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
1164         comedi_insn * insn, lsampl_t * data)
1165 {
1166         dio200_subdev_8254 *subpriv = s->private;
1167         int ret = 0;
1168         int chan = CR_CHAN(insn->chanspec);
1169         unsigned long flags;
1170
1171         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1172         switch (data[0]) {
1173         case INSN_CONFIG_SET_COUNTER_MODE:
1174                 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1175                 if (ret < 0)
1176                         ret = -EINVAL;
1177                 break;
1178         case INSN_CONFIG_8254_READ_STATUS:
1179                 data[1] = i8254_status(subpriv->iobase, 0, chan);
1180                 break;
1181         case INSN_CONFIG_SET_GATE_SRC:
1182                 ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
1183                 if (ret < 0)
1184                         ret = -EINVAL;
1185                 break;
1186         case INSN_CONFIG_GET_GATE_SRC:
1187                 ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
1188                 if (ret < 0) {
1189                         ret = -EINVAL;
1190                         break;
1191                 }
1192                 data[2] = ret;
1193                 break;
1194         case INSN_CONFIG_SET_CLOCK_SRC:
1195                 ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
1196                 if (ret < 0)
1197                         ret = -EINVAL;
1198                 break;
1199         case INSN_CONFIG_GET_CLOCK_SRC:
1200                 ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
1201                 if (ret < 0) {
1202                         ret = -EINVAL;
1203                         break;
1204                 }
1205                 data[1] = ret;
1206                 break;
1207         default:
1208                 ret = -EINVAL;
1209                 break;
1210         }
1211         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1212         return ret < 0 ? ret : insn->n;
1213 }
1214
1215 /*
1216  * This function initializes an '8254' counter subdevice.
1217  *
1218  * Note: iobase is the base address of the board, not the subdevice;
1219  * offset is the offset to the 8254 chip.
1220  */
1221 static int
1222 dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
1223         unsigned long iobase, unsigned offset)
1224 {
1225         dio200_subdev_8254 *subpriv;
1226         unsigned int chan;
1227
1228         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1229         if (!subpriv) {
1230                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1231                         dev->minor);
1232                 return -ENOMEM;
1233         }
1234
1235         s->private = subpriv;
1236         s->type = COMEDI_SUBD_COUNTER;
1237         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1238         s->n_chan = 3;
1239         s->maxdata = 0xFFFF;
1240         s->insn_read = dio200_subdev_8254_read;
1241         s->insn_write = dio200_subdev_8254_write;
1242         s->insn_config = dio200_subdev_8254_config;
1243
1244         spin_lock_init(&subpriv->spinlock);
1245         subpriv->iobase = offset + iobase;
1246         if (thislayout->has_clk_gat_sce) {
1247                 /* Derive CLK_SCE and GAT_SCE register offsets from
1248                  * 8254 offset. */
1249                 subpriv->clk_sce_iobase =
1250                         DIO200_XCLK_SCE + (offset >> 3) + iobase;
1251                 subpriv->gat_sce_iobase =
1252                         DIO200_XGAT_SCE + (offset >> 3) + iobase;
1253                 subpriv->which = (offset >> 2) & 1;
1254         }
1255
1256         /* Initialize channels. */
1257         for (chan = 0; chan < 3; chan++) {
1258                 i8254_set_mode(subpriv->iobase, 0, chan,
1259                         I8254_MODE0 | I8254_BINARY);
1260                 if (thislayout->has_clk_gat_sce) {
1261                         /* Gate source 0 is VCC (logic 1). */
1262                         dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
1263                         /* Clock source 0 is the dedicated clock input. */
1264                         dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
1265                 }
1266         }
1267
1268         return 0;
1269 }
1270
1271 /*
1272  * This function cleans up an '8254' counter subdevice.
1273  */
1274 static void
1275 dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
1276 {
1277         dio200_subdev_8254 *subpriv = s->private;
1278
1279         if (subpriv) {
1280                 kfree(subpriv);
1281         }
1282 }
1283
1284 /*
1285  * Attach is called by the Comedi core to configure the driver
1286  * for a particular board.  If you specified a board_name array
1287  * in the driver structure, dev->board_ptr contains that
1288  * address.
1289  */
1290 static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
1291 {
1292         comedi_subdevice *s;
1293         unsigned long iobase = 0;
1294         unsigned int irq = 0;
1295 #ifdef CONFIG_COMEDI_PCI
1296         struct pci_dev *pci_dev = NULL;
1297         int bus = 0, slot = 0;
1298 #endif
1299         const dio200_layout *layout;
1300         int share_irq = 0;
1301         int sdx;
1302         unsigned n;
1303         int ret;
1304
1305         printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1306                 DIO200_DRIVER_NAME);
1307
1308         if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
1309                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1310                         dev->minor);
1311                 return ret;
1312         }
1313
1314         /* Process options. */
1315         switch (thisboard->bustype) {
1316         case isa_bustype:
1317                 iobase = it->options[0];
1318                 irq = it->options[1];
1319                 share_irq = 0;
1320                 break;
1321 #ifdef CONFIG_COMEDI_PCI
1322         case pci_bustype:
1323                 bus = it->options[0];
1324                 slot = it->options[1];
1325                 share_irq = 1;
1326
1327                 if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
1328                         return ret;
1329                 devpriv->pci_dev = pci_dev;
1330                 break;
1331 #endif
1332         default:
1333                 printk(KERN_ERR
1334                         "comedi%d: %s: BUG! cannot determine board type!\n",
1335                         dev->minor, DIO200_DRIVER_NAME);
1336                 return -EINVAL;
1337                 break;
1338         }
1339
1340         devpriv->intr_sd = -1;
1341
1342         /* Enable device and reserve I/O spaces. */
1343 #ifdef CONFIG_COMEDI_PCI
1344         if (pci_dev) {
1345                 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1346                 if (ret < 0) {
1347                         printk(KERN_ERR
1348                                 "comedi%d: error! cannot enable PCI device and request regions!\n",
1349                                 dev->minor);
1350                         return ret;
1351                 }
1352                 iobase = pci_resource_start(pci_dev, 2);
1353                 irq = pci_dev->irq;
1354         } else
1355 #endif
1356         {
1357                 ret = dio200_request_region(dev->minor, iobase, DIO200_IO_SIZE);
1358                 if (ret < 0) {
1359                         return ret;
1360                 }
1361         }
1362         dev->iobase = iobase;
1363
1364         layout = thislayout;
1365         if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
1366                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1367                         dev->minor);
1368                 return ret;
1369         }
1370
1371         for (n = 0; n < dev->n_subdevices; n++) {
1372                 s = &dev->subdevices[n];
1373                 switch (layout->sdtype[n]) {
1374                 case sd_8254:
1375                         /* counter subdevice (8254) */
1376                         ret = dio200_subdev_8254_init(dev, s, iobase,
1377                                 layout->sdinfo[n]);
1378                         if (ret < 0) {
1379                                 return ret;
1380                         }
1381                         break;
1382                 case sd_8255:
1383                         /* digital i/o subdevice (8255) */
1384                         ret = subdev_8255_init(dev, s, 0,
1385                                 iobase + layout->sdinfo[n]);
1386                         if (ret < 0) {
1387                                 return ret;
1388                         }
1389                         break;
1390                 case sd_intr:
1391                         /* 'INTERRUPT' subdevice */
1392                         if (irq) {
1393                                 ret = dio200_subdev_intr_init(dev, s,
1394                                         iobase + DIO200_INT_SCE,
1395                                         layout->sdinfo[n], layout->has_int_sce);
1396                                 if (ret < 0) {
1397                                         return ret;
1398                                 }
1399                                 devpriv->intr_sd = n;
1400                         } else {
1401                                 s->type = COMEDI_SUBD_UNUSED;
1402                         }
1403                         break;
1404                 default:
1405                         s->type = COMEDI_SUBD_UNUSED;
1406                         break;
1407                 }
1408         }
1409
1410         sdx = devpriv->intr_sd;
1411         if (sdx >= 0 && sdx < dev->n_subdevices) {
1412                 dev->read_subdev = &dev->subdevices[sdx];
1413         }
1414
1415         dev->board_name = thisboard->name;
1416
1417         if (irq) {
1418                 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1419
1420                 if (comedi_request_irq(irq, dio200_interrupt, flags,
1421                                 DIO200_DRIVER_NAME, dev) >= 0) {
1422                         dev->irq = irq;
1423                 } else {
1424                         printk(KERN_WARNING
1425                                 "comedi%d: warning! irq %u unavailable!\n",
1426                                 dev->minor, irq);
1427                 }
1428         }
1429
1430         printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1431         if (thisboard->bustype == isa_bustype) {
1432                 printk("(base %#lx) ", iobase);
1433         } else {
1434 #ifdef CONFIG_COMEDI_PCI
1435                 printk("(pci %s) ", pci_name(pci_dev));
1436 #endif
1437         }
1438         if (irq) {
1439                 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1440         } else {
1441                 printk("(no irq) ");
1442         }
1443
1444         printk("attached\n");
1445
1446         return 1;
1447 }
1448
1449 /*
1450  * _detach is called to deconfigure a device.  It should deallocate
1451  * resources.
1452  * This function is also called when _attach() fails, so it should be
1453  * careful not to release resources that were not necessarily
1454  * allocated by _attach().  dev->private and dev->subdevices are
1455  * deallocated automatically by the core.
1456  */
1457 static int dio200_detach(comedi_device * dev)
1458 {
1459         const dio200_layout *layout;
1460         unsigned n;
1461
1462         printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1463                 DIO200_DRIVER_NAME);
1464
1465         if (dev->irq) {
1466                 comedi_free_irq(dev->irq, dev);
1467         }
1468         if (dev->subdevices) {
1469                 layout = thislayout;
1470                 for (n = 0; n < dev->n_subdevices; n++) {
1471                         comedi_subdevice *s = &dev->subdevices[n];
1472                         switch (layout->sdtype[n]) {
1473                         case sd_8254:
1474                                 dio200_subdev_8254_cleanup(dev, s);
1475                                 break;
1476                         case sd_8255:
1477                                 subdev_8255_cleanup(dev, s);
1478                                 break;
1479                         case sd_intr:
1480                                 dio200_subdev_intr_cleanup(dev, s);
1481                                 break;
1482                         default:
1483                                 break;
1484                         }
1485                 }
1486         }
1487         if (devpriv) {
1488 #ifdef CONFIG_COMEDI_PCI
1489                 if (devpriv->pci_dev) {
1490                         if (dev->iobase) {
1491                                 comedi_pci_disable(devpriv->pci_dev);
1492                         }
1493                         pci_dev_put(devpriv->pci_dev);
1494                 } else
1495 #endif
1496                 {
1497                         if (dev->iobase) {
1498                                 release_region(dev->iobase, DIO200_IO_SIZE);
1499                         }
1500                 }
1501         }
1502         if (dev->board_name) {
1503                 printk(KERN_INFO "comedi%d: %s removed\n",
1504                         dev->minor, dev->board_name);
1505         }
1506
1507         return 0;
1508 }