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