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