1b9c660740988dd2ffa76042d575d7c874bf3312
[comedi.git] / comedi / drivers / amplc_dio200.c
1 /*
2     comedi/drivers/amplc_dio200.c
3     Driver for various Amplicon 200 series 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-2012 MEV Ltd. <http://www.mev.co.uk/>
8
9     COMEDI - Linux Control and Measurement Device Interface
10     Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
11
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 */
27 /*
28 Driver: amplc_dio200
29 Description: Amplicon 200 Series Digital I/O
30 Author: Ian Abbott <abbotti@mev.co.uk>
31 Devices: [Amplicon] PC212E (pc212e), PC214E (pc214e), PC215E (pc215e),
32   PCI215 (pci215 or amplc_dio200), PCIe215 (pcie215 or amplc_dio200),
33   PC218E (pc218e), PCIe236 (pcie236 or amplc_dio200), PC272E (pc272e),
34   PCI272 (pci272 or amplc_dio200), PCIe296 (pcie296 or amplc_dio200)
35 Updated: Wed, 16 May 2012 13:57:58 +0100
36 Status: works
37
38 Configuration options - PC212E, PC214E, PC215E, PC218E, PC272E:
39   [0] - I/O port base address
40   [1] - IRQ (optional, but commands won't work without it)
41
42 Configuration options - PCI215, PCIe215, PCIe236, PCI272, PCIe296:
43   [0] - PCI bus of device (optional)
44   [1] - PCI slot of device (optional)
45   If bus/slot is not specified, the first available PCI device will
46   be used.
47
48 Passing a zero for an option is the same as leaving it unspecified.
49
50 SUBDEVICES
51
52                     PC212E         PC214E      PC215E/PCI215
53                  -------------  -------------  -------------
54   Subdevices           6              4              5
55    0                 PPI-X          PPI-X          PPI-X
56    1                 CTR-Y1         PPI-Y          PPI-Y
57    2                 CTR-Y2         CTR-Z1*        CTR-Z1
58    3                 CTR-Z1       INTERRUPT*       CTR-Z2
59    4                 CTR-Z2                      INTERRUPT
60    5               INTERRUPT
61
62                     PCIe215        PC218E         PCIe236
63                  -------------  -------------  -------------
64   Subdevices           8              7              8
65    0                 PPI-X          CTR-X1         PPI-X
66    1                 UNUSED         CTR-X2         UNUSED
67    2                 PPI-Y          CTR-Y1         UNUSED
68    3                 UNUSED         CTR-Y2         UNUSED
69    4                 CTR-Z1         CTR-Z1         CTR-Z1
70    5                 CTR-Z2         CTR-Z2         CTR-Z2
71    6                 TIMER        INTERRUPT        TIMER
72    7               INTERRUPT                     INTERRUPT
73
74                  PC272E/PCI272     PCIe296
75                  -------------  -------------
76   Subdevices           4              8
77    0                 PPI-X          PPI-X1
78    1                 PPI-Y          PPI-X2
79    2                 PPI-Z          PPI-Y1
80    3               INTERRUPT        PPI-Y2
81    4                                CTR-Z1
82    5                                CTR-Z2
83    6                                TIMER
84    7                              INTERRUPT
85
86 Each PPI is a 8255 chip providing 24 DIO channels.  The DIO channels
87 are configurable as inputs or outputs in four groups:
88
89   Port A  - channels  0 to  7
90   Port B  - channels  8 to 15
91   Port CL - channels 16 to 19
92   Port CH - channels 20 to 23
93
94 Only mode 0 of the 8255 chips is supported.
95
96 Each CTR is a 8254 chip providing 3 16-bit counter channels.  Each
97 channel is configured individually with INSN_CONFIG instructions.  The
98 specific type of configuration instruction is specified in data[0].
99 Some configuration instructions expect an additional parameter in
100 data[1]; others return a value in data[1].  The following configuration
101 instructions are supported:
102
103   INSN_CONFIG_SET_COUNTER_MODE.  Sets the counter channel's mode and
104     BCD/binary setting specified in data[1].
105
106   INSN_CONFIG_8254_READ_STATUS.  Reads the status register value for the
107     counter channel into data[1].
108
109   INSN_CONFIG_SET_CLOCK_SRC.  Sets the counter channel's clock source as
110     specified in data[1] (this is a hardware-specific value).  Not
111     supported on PC214E.  For the other boards, valid clock sources are
112     0 to 7 as follows:
113
114       0.  CLK n, the counter channel's dedicated CLK input from the SK1
115         connector.  (N.B. for other values, the counter channel's CLKn
116         pin on the SK1 connector is an output!)
117       1.  Internal 10 MHz clock.
118       2.  Internal 1 MHz clock.
119       3.  Internal 100 kHz clock.
120       4.  Internal 10 kHz clock.
121       5.  Internal 1 kHz clock.
122       6.  OUT n-1, the output of counter channel n-1 (see note 1 below).
123       7.  Ext Clock, the counter chip's dedicated Ext Clock input from
124         the SK1 connector.  This pin is shared by all three counter
125         channels on the chip.
126
127   INSN_CONFIG_GET_CLOCK_SRC.  Returns the counter channel's current
128     clock source in data[1].  For internal clock sources, data[2] is set
129     to the period in ns.
130
131   INSN_CONFIG_SET_GATE_SRC.  Sets the counter channel's gate source as
132     specified in data[2] (this is a hardware-specific value).  Not
133     supported on PC214E.  For the other boards, valid gate sources are 0
134     to 7 as follows:
135
136       0.  VCC (internal +5V d.c.), i.e. gate permanently enabled.
137       1.  GND (internal 0V d.c.), i.e. gate permanently disabled.
138       2.  GAT n, the counter channel's dedicated GAT input from the SK1
139         connector.  (N.B. for other values, the counter channel's GATn
140         pin on the SK1 connector is an output!)
141       3.  /OUT n-2, the inverted output of counter channel n-2 (see note
142         2 below).
143       4.  Reserved.
144       5.  Reserved.
145       6.  Reserved.
146       7.  Reserved.
147
148   INSN_CONFIG_GET_GATE_SRC.  Returns the counter channel's current gate
149     source in data[2].
150
151 Clock and gate interconnection notes:
152
153   1.  Clock source OUT n-1 is the output of the preceding channel on the
154   same counter subdevice if n > 0, or the output of channel 2 on the
155   preceding counter subdevice (see note 3) if n = 0.
156
157   2.  Gate source /OUT n-2 is the inverted output of channel 0 on the
158   same counter subdevice if n = 2, or the inverted output of channel n+1
159   on the preceding counter subdevice (see note 3) if n < 2.
160
161   3.  The counter subdevices are connected in a ring, so the highest
162   counter subdevice precedes the lowest.
163
164 The 'TIMER' subdevice is a free-running 32-bit timer subdevice.
165
166 The 'INTERRUPT' subdevice pretends to be a digital input subdevice.  The
167 digital inputs come from the interrupt status register.  The number of
168 channels matches the number of interrupt sources.  The PC214E does not
169 have an interrupt status register; see notes on 'INTERRUPT SOURCES'
170 below.
171
172 INTERRUPT SOURCES
173
174                     PC212E         PC214E      PC215E/PCI215
175                  -------------  -------------  -------------
176   Sources              6              1              6
177    0               PPI-X-C0       JUMPER-J5      PPI-X-C0
178    1               PPI-X-C3                      PPI-X-C3
179    2              CTR-Y1-OUT1                    PPI-Y-C0
180    3              CTR-Y2-OUT1                    PPI-Y-C3
181    4              CTR-Z1-OUT1                   CTR-Z1-OUT1
182    5              CTR-Z2-OUT1                   CTR-Z2-OUT1
183
184                     PCIe215        PC218E         PCIe236
185                  -------------  -------------  -------------
186   Sources              6              6              6
187    0               PPI-X-C0      CTR-X1-OUT1     PPI-X-C0
188    1               PPI-X-C3      CTR-X2-OUT1     PPI-X-C3
189    2               PPI-Y-C0      CTR-Y1-OUT1      unused
190    3               PPI-Y-C3      CTR-Y2-OUT1      unused
191    4              CTR-Z1-OUT1    CTR-Z1-OUT1    CTR-Z1-OUT1
192    5              CTR-Z2-OUT1    CTR-Z2-OUT1    CTR-Z2-OUT1
193
194                  PC272E/PCI272     PCIe296
195                  -------------  -------------
196   Sources              6              6
197    0               PPI-X-C0       PPI-X1-C0
198    1               PPI-X-C3       PPI-X1-C3
199    2               PPI-Y-C0       PPI-Y1-C0
200    3               PPI-Y-C3       PPI-Y2-C3
201    4               PPI-Z-C0      CTR-Z1-OUT1
202    5               PPI-Z-C3      CTR-Z2-OUT1
203
204 When an interrupt source is enabled in the interrupt source enable
205 register, a rising edge on the source signal latches the corresponding
206 bit to 1 in the interrupt status register.
207
208 When the interrupt status register value as a whole (actually, just the
209 6 least significant bits) goes from zero to non-zero, the board will
210 generate an interrupt.  For level-triggered hardware interrupts (PCI
211 card), the interrupt will remain asserted until the interrupt status
212 register is cleared to zero.  For edge-triggered hardware interrupts
213 (ISA card), no further interrupts will occur until the interrupt status
214 register is cleared to zero.  To clear a bit to zero in the interrupt
215 status register, the corresponding interrupt source must be disabled
216 in the interrupt source enable register (there is no separate interrupt
217 clear register).
218
219 The PC214E does not have an interrupt source enable register or an
220 interrupt status register; its 'INTERRUPT' subdevice has a single
221 channel and its interrupt source is selected by the position of jumper
222 J5.
223
224 COMMANDS
225
226 The driver supports a read streaming acquisition command on the
227 'INTERRUPT' subdevice.  The channel list selects the interrupt sources
228 to be enabled.  All channels will be sampled together (convert_src ==
229 TRIG_NOW).  The scan begins a short time after the hardware interrupt
230 occurs, subject to interrupt latencies (scan_begin_src == TRIG_EXT,
231 scan_begin_arg == 0).  The value read from the interrupt status register
232 is packed into a sampl_t value, one bit per requested channel, in the
233 order they appear in the channel list.
234 */
235
236 #include <linux/comedidev.h>
237
238 #include "comedi_pci.h"
239
240 #include "8255.h"
241 #include "8253.h"
242
243 #define DIO200_DRIVER_NAME      "amplc_dio200"
244
245 /* PCI IDs */
246 /* #define PCI_VENDOR_ID_AMPLICON 0x14dc */
247 #define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
248 #define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
249 #define PCI_DEVICE_ID_AMPLICON_PCIE236 0x0011
250 #define PCI_DEVICE_ID_AMPLICON_PCIE215 0x0012
251 #define PCI_DEVICE_ID_AMPLICON_PCIE296 0x0014
252 #define PCI_DEVICE_ID_INVALID 0xffff
253
254 /* 8255 control register bits */
255 #define CR_C_LO_IO      0x01
256 #define CR_B_IO         0x02
257 #define CR_B_MODE       0x04
258 #define CR_C_HI_IO      0x08
259 #define CR_A_IO         0x10
260 #define CR_A_MODE(a)    ((a)<<5)
261 #define CR_CW           0x80
262
263 /* 200 series registers */
264 #define DIO200_IO_SIZE          0x20
265 #define DIO200_PCIE_IO_SIZE     0x4000
266 #define DIO200_XCLK_SCE         0x18    /* Group X clock selection register */
267 #define DIO200_YCLK_SCE         0x19    /* Group Y clock selection register */
268 #define DIO200_ZCLK_SCE         0x1a    /* Group Z clock selection register */
269 #define DIO200_XGAT_SCE         0x1b    /* Group X gate selection register */
270 #define DIO200_YGAT_SCE         0x1c    /* Group Y gate selection register */
271 #define DIO200_ZGAT_SCE         0x1d    /* Group Z gate selection register */
272 #define DIO200_INT_SCE          0x1e    /* Interrupt enable/status register */
273 /* Extra registers for new PCIe boards */
274 #define DIO200_ENHANCE          0x20    /* 1 to enable enhanced features */
275 #define DIO200_VERSION          0x24    /* Hardware version */
276
277 /*
278  * Macros for constructing value for DIO_200_?CLK_SCE and
279  * DIO_200_?GAT_SCE registers:
280  *
281  * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
282  * 'chan' is the channel: 0, 1 or 2.
283  * 'source' is the signal source: 0 to 7, or 0 to 31 for "enhanced" boards.
284  */
285 #define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | \
286                 (((source) & 030) << 3) | ((source) & 007))
287 #define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | \
288                 (((source) & 030) << 3) | ((source) & 007))
289
290 /*
291  * Periods of the internal clock sources in nanoseconds.
292  */
293 static const unsigned clock_period[32] = {
294         0,                      /* dedicated clock input/output pin */
295         100,                    /* 10 MHz */
296         1000,                   /* 1 MHz */
297         10000,                  /* 100 kHz */
298         100000,                 /* 10 kHz */
299         1000000,                /* 1 kHz */
300         0,                      /* OUT N-1 */
301         0,                      /* group clock input pin */
302         0,                      /* HIGH (VCC) (enhanced) */
303         0,                      /* LOW (GND) (enhanced) */
304         0,                      /* pattern present (enhanced) */
305         50,                     /* 20 MHz (enhanced) */
306         /* remaining clock sources reserved (enhanced) */
307 };
308
309 /*
310  * Register region.
311  */
312 enum dio200_regtype { no_regtype, io_regtype, mmio_regtype };
313 struct dio200_region {
314         union {
315                 unsigned long iobase;           /* I/O base address */
316                 unsigned char __iomem *membase; /* Mapped MMIO base address */
317         } u;
318         unsigned char regtype;
319         unsigned char regshift;
320 };
321
322 /*
323  * Board descriptions.
324  */
325
326 enum dio200_bustype { isa_bustype, pci_bustype };
327
328 enum dio200_model {
329         pc212e_model,
330         pc214e_model,
331         pc215e_model, pci215_model, pcie215_model,
332         pc218e_model,
333         pcie236_model,
334         pc272e_model, pci272_model,
335         pcie296_model,
336         anypci_model
337 };
338
339 enum dio200_layout {
340         pc212_layout,
341         pc214_layout,
342         pc215_layout,
343         pc218_layout,
344         pc272_layout,
345 #ifdef CONFIG_COMEDI_PCI
346         pcie215_layout,
347         pcie236_layout,
348         pcie296_layout,
349 #endif
350         num_layouts
351 };
352
353 typedef struct dio200_board_struct {
354         const char *name;
355         unsigned short devid;
356         enum dio200_bustype bustype;
357         enum dio200_model model;
358         enum dio200_layout layout;
359         unsigned char mainbar;
360         unsigned char mainshift;
361         unsigned int mainsize;
362 } dio200_board;
363
364 static const dio200_board dio200_boards[] = {
365         {
366               name:     "pc212e",
367               bustype:  isa_bustype,
368               model:    pc212e_model,
369               layout:   pc212_layout,
370               mainsize: DIO200_IO_SIZE,
371                 },
372         {
373               name:     "pc214e",
374               bustype:  isa_bustype,
375               model:    pc214e_model,
376               layout:   pc214_layout,
377               mainsize: DIO200_IO_SIZE,
378                 },
379         {
380               name:     "pc215e",
381               bustype:  isa_bustype,
382               model:    pc215e_model,
383               layout:   pc215_layout,
384               mainsize: DIO200_IO_SIZE,
385                 },
386 #ifdef CONFIG_COMEDI_PCI
387         {
388               name:     "pci215",
389               devid:    PCI_DEVICE_ID_AMPLICON_PCI215,
390               bustype:  pci_bustype,
391               model:    pci215_model,
392               layout:   pc215_layout,
393               mainsize: DIO200_IO_SIZE,
394               mainbar:  2,
395                 },
396 #endif
397 #ifdef CONFIG_COMEDI_PCI
398         {
399               name:     "pcie215",
400               devid:    PCI_DEVICE_ID_AMPLICON_PCIE215,
401               bustype:  pci_bustype,
402               model:    pcie215_model,
403               layout:   pcie215_layout,
404               mainsize: DIO200_PCIE_IO_SIZE,
405               mainbar:  1,
406               mainshift: 3,
407                 },
408 #endif
409         {
410               name:     "pc218e",
411               bustype:  isa_bustype,
412               model:    pc218e_model,
413               layout:   pc218_layout,
414               mainsize: DIO200_IO_SIZE,
415                 },
416 #ifdef CONFIG_COMEDI_PCI
417         {
418               name:     "pcie236",
419               devid:    PCI_DEVICE_ID_AMPLICON_PCIE236,
420               bustype:  pci_bustype,
421               model:    pcie236_model,
422               layout:   pcie236_layout,
423               mainsize: DIO200_PCIE_IO_SIZE,
424               mainbar:  1,
425               mainshift: 3,
426                 },
427 #endif
428         {
429               name:     "pc272e",
430               bustype:  isa_bustype,
431               model:    pc272e_model,
432               layout:   pc272_layout,
433               mainsize: DIO200_IO_SIZE,
434                 },
435 #ifdef CONFIG_COMEDI_PCI
436         {
437               name:     "pci272",
438               devid:    PCI_DEVICE_ID_AMPLICON_PCI272,
439               bustype:  pci_bustype,
440               model:    pci272_model,
441               layout:   pc272_layout,
442               mainsize: DIO200_IO_SIZE,
443               mainbar:  2,
444                 },
445 #endif
446 #ifdef CONFIG_COMEDI_PCI
447         {
448               name:     "pcie296",
449               devid:    PCI_DEVICE_ID_AMPLICON_PCIE296,
450               bustype:  pci_bustype,
451               model:    pcie296_model,
452               layout:   pcie296_layout,
453               mainsize: DIO200_PCIE_IO_SIZE,
454               mainbar:  1,
455               mainshift: 3,
456                 },
457 #endif
458 #ifdef CONFIG_COMEDI_PCI
459         {
460               name:     DIO200_DRIVER_NAME,
461               devid:    PCI_DEVICE_ID_INVALID,
462               bustype:  pci_bustype,
463               model:    anypci_model,   /* wildcard */
464                 },
465 #endif
466 };
467
468 /*
469  * Layout descriptions - some ISA and PCI board descriptions share the same
470  * layout.
471  */
472
473 enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254, sd_timer };
474
475 #define DIO200_MAX_SUBDEVS      8
476 #define DIO200_MAX_ISNS         6
477
478 typedef struct dio200_layout_struct {
479         unsigned short n_subdevs;       /* number of subdevices */
480         unsigned char sdtype[DIO200_MAX_SUBDEVS];       /* enum dio200_sdtype */
481         unsigned char sdinfo[DIO200_MAX_SUBDEVS];       /* depends on sdtype */
482         char has_int_sce;       /* has interrupt enable/status register */
483         char has_clk_gat_sce;   /* has clock/gate selection registers */
484         char has_enhancements;  /* has enhanced features */
485 } dio200_layout;
486
487 static const dio200_layout dio200_layouts[] = {
488         [pc212_layout] = {
489               n_subdevs:6,
490               sdtype:   {sd_8255, sd_8254, sd_8254, sd_8254,
491                                         sd_8254,
492                                 sd_intr},
493               sdinfo:   {0x00, 0x08, 0x0C, 0x10, 0x14,
494                                 0x3F},
495               has_int_sce:1,
496               has_clk_gat_sce:1,
497               has_enhancements:0,
498                 },
499         [pc214_layout] = {
500               n_subdevs:4,
501               sdtype:   {sd_8255, sd_8255, sd_8254,
502                                 sd_intr},
503               sdinfo:   {0x00, 0x08, 0x10, 0x01},
504               has_int_sce:0,
505               has_clk_gat_sce:0,
506               has_enhancements:0,
507                 },
508         [pc215_layout] = {
509               n_subdevs:5,
510               sdtype:   {sd_8255, sd_8255, sd_8254,
511                                         sd_8254,
512                                 sd_intr},
513               sdinfo:   {0x00, 0x08, 0x10, 0x14, 0x3F},
514               has_int_sce:1,
515               has_clk_gat_sce:1,
516               has_enhancements:0,
517                 },
518         [pc218_layout] = {
519               n_subdevs:7,
520               sdtype:   {sd_8254, sd_8254, sd_8255, sd_8254,
521                                         sd_8254,
522                                 sd_intr},
523               sdinfo:   {0x00, 0x04, 0x08, 0x0C, 0x10,
524                                         0x14,
525                                 0x3F},
526               has_int_sce:1,
527               has_clk_gat_sce:1,
528               has_enhancements:0,
529                 },
530         [pc272_layout] = {
531               n_subdevs:4,
532               sdtype:   {sd_8255, sd_8255, sd_8255,
533                                 sd_intr},
534               sdinfo:   {0x00, 0x08, 0x10, 0x3F},
535               has_int_sce:1,
536               has_clk_gat_sce:0,
537               has_enhancements:0,
538                 },
539 #ifdef CONFIG_COMEDI_PCI
540         [pcie215_layout] = {
541               n_subdevs:8,
542               sdtype:   {sd_8255, sd_none, sd_8255, sd_none, sd_8254, sd_8254,
543                                 sd_timer, sd_intr},
544               sdinfo:   {0x00, 0x00, 0x08, 0x00, 0x10, 0x14, 0x00, 0x3F},
545               has_int_sce:1,
546               has_clk_gat_sce:1,
547               has_enhancements:1,
548                 },
549         [pcie236_layout] = {
550               n_subdevs:8,
551               sdtype:   {sd_8255, sd_none, sd_none, sd_none, sd_8254, sd_8254,
552                                 sd_timer, sd_intr},
553               sdinfo:   {0x00, 0x00, 0x00, 0x00, 0x10, 0x14, 0x00, 0x3F},
554               has_int_sce:1,
555               has_clk_gat_sce:1,
556               has_enhancements:1,
557                 },
558         [pcie296_layout] = {
559               n_subdevs:8,
560               sdtype:   {sd_8255, sd_8255, sd_8255, sd_8255, sd_8254, sd_8254,
561                                 sd_timer, sd_intr},
562               sdinfo:   {0x00, 0x04, 0x08, 0x0C, 0x10, 0x14, 0x00, 0x3F},
563               has_int_sce:1,
564               has_clk_gat_sce:1,
565               has_enhancements:1,
566                 },
567 #endif
568 };
569
570 /*
571  * PCI driver table.
572  */
573
574 #ifdef CONFIG_COMEDI_PCI
575 static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
576         {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215,
577                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
578         {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272,
579                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
580         {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE236,
581                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
582         {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE215,
583                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
584         {PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCIE296,
585                 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
586         {0}
587 };
588
589 MODULE_DEVICE_TABLE(pci, dio200_pci_table);
590 #endif /* CONFIG_COMEDI_PCI */
591
592 /*
593  * Useful for shorthand access to the particular board structure
594  */
595 #define thisboard ((const dio200_board *)dev->board_ptr)
596 #define thislayout (&dio200_layouts[((dio200_board *)dev->board_ptr)->layout])
597
598 /* this structure is for data unique to this hardware driver.  If
599    several hardware drivers keep similar information in this structure,
600    feel free to suggest moving the variable to the comedi_device struct.  */
601 typedef struct {
602 #ifdef CONFIG_COMEDI_PCI
603         struct pci_dev *pci_dev;        /* PCI device */
604 #endif
605         struct dio200_region io;        /* Register region */
606         int intr_sd;
607 } dio200_private;
608
609 #define devpriv ((dio200_private *)dev->private)
610
611 typedef struct {
612         unsigned int ofs;               /* Counter base offset */
613         unsigned int clk_sce_ofs;       /* CLK_SCE base offset */
614         unsigned int gat_sce_ofs;       /* GAT_SCE base offset */
615         int which;                      /* Bit 5 of CLK_SCE or GAT_SCE */
616         unsigned int clock_src[3];      /* Current clock sources */
617         unsigned int gate_src[3];       /* Current gate sources */
618         spinlock_t spinlock;
619 } dio200_subdev_8254;
620
621 typedef struct {
622         unsigned int ofs;               /* DIO base offset */
623 } dio200_subdev_8255;
624
625 typedef struct {
626         unsigned int ofs;
627         spinlock_t spinlock;
628         int active;
629         unsigned int valid_isns;
630         unsigned int enabled_isns;
631         unsigned int stopcount;
632         int continuous;
633 } dio200_subdev_intr;
634
635 /*
636  * The comedi_driver structure tells the Comedi core module
637  * which functions to call to configure/deconfigure (attach/detach)
638  * the board, and also about the kernel module that contains
639  * the device code.
640  */
641 static int dio200_attach(comedi_device * dev, comedi_devconfig * it);
642 static int dio200_detach(comedi_device * dev);
643 static comedi_driver driver_amplc_dio200 = {
644       driver_name:DIO200_DRIVER_NAME,
645       module:THIS_MODULE,
646       attach:dio200_attach,
647       detach:dio200_detach,
648       board_name:&dio200_boards[0].name,
649       offset:sizeof(dio200_board),
650       num_names:sizeof(dio200_boards) / sizeof(dio200_board),
651 };
652
653 #ifdef CONFIG_COMEDI_PCI
654 COMEDI_PCI_INITCLEANUP(driver_amplc_dio200, dio200_pci_table);
655 #else
656 COMEDI_INITCLEANUP(driver_amplc_dio200);
657 #endif
658
659 /*
660  * Read 8-bit register.
661  */
662 static unsigned char dio200_read8(comedi_device * dev, unsigned int offset)
663 {
664         offset <<= devpriv->io.regshift;
665         if (devpriv->io.regtype == io_regtype)
666                 return inb(devpriv->io.u.iobase + offset);
667         else
668                 return readb(devpriv->io.u.membase + offset);
669 }
670
671 /*
672  * Write 8-bit register.
673  */
674 static void dio200_write8(comedi_device * dev, unsigned int offset,
675                 unsigned char val)
676 {
677         offset <<= devpriv->io.regshift;
678         if (devpriv->io.regtype == io_regtype)
679                 outb(val, devpriv->io.u.iobase + offset);
680         else
681                 writeb(val, devpriv->io.u.membase + offset);
682 }
683
684 /*
685  * Read 32-bit register.
686  */
687 #ifdef CONFIG_COMEDI_PCI
688 static unsigned int dio200_read32(comedi_device * dev, unsigned int offset)
689 {
690         offset <<= devpriv->io.regshift;
691         if (devpriv->io.regtype == io_regtype)
692                 return inl(devpriv->io.u.iobase + offset);
693         else
694                 return readl(devpriv->io.u.membase + offset);
695 }
696 #endif
697
698 /*
699  * Write 32-bit register.
700  */
701 #ifdef CONFIG_COMEDI_PCI
702 static void dio200_write32(comedi_device * dev, unsigned int offset,
703                 unsigned int val)
704 {
705         offset <<= devpriv->io.regshift;
706         if (devpriv->io.regtype == io_regtype)
707                 outl(val, devpriv->io.u.iobase + offset);
708         else
709                 writel(val, devpriv->io.u.membase + offset);
710 }
711 #endif
712
713 /*
714  * This function looks for a PCI device matching the requested board name,
715  * bus and slot.
716  */
717 #ifdef CONFIG_COMEDI_PCI
718 static int
719 dio200_find_pci(comedi_device * dev, int bus, int slot,
720         struct pci_dev **pci_dev_p)
721 {
722         struct pci_dev *pci_dev = NULL;
723
724         *pci_dev_p = NULL;
725
726         /* Look for matching PCI device. */
727         for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
728                 pci_dev != NULL;
729                 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
730                         PCI_ANY_ID, pci_dev)) {
731                 /* If bus/slot specified, check them. */
732                 if (bus || slot) {
733                         if (bus != pci_dev->bus->number
734                                 || slot != PCI_SLOT(pci_dev->devfn))
735                                 continue;
736                 }
737                 if (thisboard->model == anypci_model) {
738                         /* Match any supported model. */
739                         int i;
740
741                         for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
742                                 if (dio200_boards[i].bustype != pci_bustype)
743                                         continue;
744                                 if (pci_dev->device == dio200_boards[i].devid) {
745                                         /* Change board_ptr to matched board. */
746                                         dev->board_ptr = &dio200_boards[i];
747                                         break;
748                                 }
749                         }
750                         if (i == ARRAY_SIZE(dio200_boards))
751                                 continue;
752                 } else {
753                         /* Match specific model name. */
754                         if (pci_dev->device != thisboard->devid)
755                                 continue;
756                 }
757
758                 /* Found a match. */
759                 *pci_dev_p = pci_dev;
760                 return 0;
761         }
762         /* No match found. */
763         if (bus || slot) {
764                 printk(KERN_ERR
765                         "comedi%d: error! no %s found at pci %02x:%02x!\n",
766                         dev->minor, thisboard->name, bus, slot);
767         } else {
768                 printk(KERN_ERR "comedi%d: error! no %s found!\n",
769                         dev->minor, thisboard->name);
770         }
771         return -EIO;
772 }
773 #endif
774
775 /*
776  * This function checks and requests an I/O region, reporting an error
777  * if there is a conflict.
778  */
779 static int
780 dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
781 {
782         if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
783                 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
784                         minor, from, extent);
785                 return -EIO;
786         }
787         return 0;
788 }
789
790 /*
791  * 'insn_bits' function for an 'INTERRUPT' subdevice.
792  */
793 static int
794 dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
795         comedi_insn * insn, lsampl_t * data)
796 {
797         dio200_subdev_intr *subpriv = s->private;
798
799         if (thislayout->has_int_sce) {
800                 /* Just read the interrupt status register.  */
801                 data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
802         } else {
803                 /* No interrupt status register. */
804                 data[0] = 0;
805         }
806
807         return 2;
808 }
809
810 /*
811  * Called to stop acquisition for an 'INTERRUPT' subdevice.
812  */
813 static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
814 {
815         dio200_subdev_intr *subpriv = s->private;
816
817         subpriv->active = 0;
818         subpriv->enabled_isns = 0;
819         if (thislayout->has_int_sce) {
820                 dio200_write8(dev, subpriv->ofs, 0);
821         }
822 }
823
824 /*
825  * Called to start acquisition for an 'INTERRUPT' subdevice.
826  */
827 static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
828 {
829         unsigned int n;
830         unsigned isn_bits;
831         dio200_subdev_intr *subpriv = s->private;
832         comedi_cmd *cmd = &s->async->cmd;
833         int retval = 0;
834
835         if (!subpriv->continuous && subpriv->stopcount == 0) {
836                 /* An empty acquisition! */
837                 s->async->events |= COMEDI_CB_EOA;
838                 subpriv->active = 0;
839                 retval = 1;
840         } else {
841                 /* Determine interrupt sources to enable. */
842                 isn_bits = 0;
843                 if (cmd->chanlist) {
844                         for (n = 0; n < cmd->chanlist_len; n++) {
845                                 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
846                         }
847                 }
848                 isn_bits &= subpriv->valid_isns;
849                 /* Enable interrupt sources. */
850                 subpriv->enabled_isns = isn_bits;
851                 if (thislayout->has_int_sce) {
852                         dio200_write8(dev, subpriv->ofs, isn_bits);
853                 }
854         }
855
856         return retval;
857 }
858
859 /*
860  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
861  */
862 static int
863 dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
864         unsigned int trignum)
865 {
866         dio200_subdev_intr *subpriv;
867         unsigned long flags;
868         int event = 0;
869
870         if (trignum != 0)
871                 return -EINVAL;
872
873         subpriv = s->private;
874
875         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
876         s->async->inttrig = 0;
877         if (subpriv->active) {
878                 event = dio200_start_intr(dev, s);
879         }
880         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
881
882         if (event) {
883                 comedi_event(dev, s);
884         }
885
886         return 1;
887 }
888
889 /*
890  * This is called from the interrupt service routine to handle a read
891  * scan on an 'INTERRUPT' subdevice.
892  */
893 static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
894 {
895         dio200_subdev_intr *subpriv = s->private;
896         unsigned triggered;
897         unsigned intstat;
898         unsigned cur_enabled;
899         unsigned int oldevents;
900         unsigned long flags;
901         unsigned int int_sce_ofs;
902
903         int_sce_ofs = subpriv->ofs;
904         triggered = 0;
905
906         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
907         oldevents = s->async->events;
908         if (thislayout->has_int_sce) {
909                 /*
910                  * Collect interrupt sources that have triggered and disable
911                  * them temporarily.  Loop around until no extra interrupt
912                  * sources have triggered, at which point, the valid part of
913                  * the interrupt status register will read zero, clearing the
914                  * cause of the interrupt.
915                  *
916                  * Mask off interrupt sources already seen to avoid infinite
917                  * loop in case of misconfiguration.
918                  */
919                 cur_enabled = subpriv->enabled_isns;
920                 while ((intstat = (dio200_read8(dev, int_sce_ofs)
921                                         & subpriv->valid_isns & ~triggered))
922                                 != 0) {
923                         triggered |= intstat;
924                         cur_enabled &= ~triggered;
925                         dio200_write8(dev, int_sce_ofs, cur_enabled);
926                 }
927         } else {
928                 /*
929                  * No interrupt status register.  Assume the single interrupt
930                  * source has triggered.
931                  */
932                 triggered = subpriv->enabled_isns;
933         }
934
935         if (triggered) {
936                 /*
937                  * Some interrupt sources have triggered and have been
938                  * temporarily disabled to clear the cause of the interrupt.
939                  *
940                  * Reenable them NOW to minimize the time they are disabled.
941                  */
942                 cur_enabled = subpriv->enabled_isns;
943                 if (thislayout->has_int_sce) {
944                         dio200_write8(dev, int_sce_ofs, cur_enabled);
945                 }
946
947                 if (subpriv->active) {
948                         /*
949                          * The command is still active.
950                          *
951                          * Ignore interrupt sources that the command isn't
952                          * interested in (just in case there's a race
953                          * condition).
954                          */
955                         if (triggered & subpriv->enabled_isns) {
956                                 /* Collect scan data. */
957                                 sampl_t val;
958                                 unsigned int n, ch, len;
959
960                                 val = 0;
961                                 len = s->async->cmd.chanlist_len;
962                                 for (n = 0; n < len; n++) {
963                                         ch = CR_CHAN(s->async->cmd.chanlist[n]);
964                                         if (triggered & (1U << ch)) {
965                                                 val |= (1U << n);
966                                         }
967                                 }
968                                 /* Write the scan to the buffer. */
969                                 if (comedi_buf_put(s->async, val)) {
970                                         s->async->events |= (COMEDI_CB_BLOCK |
971                                                 COMEDI_CB_EOS);
972                                 } else {
973                                         /* Error!  Stop acquisition.  */
974                                         dio200_stop_intr(dev, s);
975                                         s->async->events |= COMEDI_CB_ERROR
976                                                 | COMEDI_CB_OVERFLOW;
977                                         comedi_error(dev, "buffer overflow");
978                                 }
979
980                                 /* Check for end of acquisition. */
981                                 if (!subpriv->continuous) {
982                                         /* stop_src == TRIG_COUNT */
983                                         if (subpriv->stopcount > 0) {
984                                                 subpriv->stopcount--;
985                                                 if (subpriv->stopcount == 0) {
986                                                         s->async->events |=
987                                                                 COMEDI_CB_EOA;
988                                                         dio200_stop_intr(dev,
989                                                                 s);
990                                                 }
991                                         }
992                                 }
993                         }
994                 }
995         }
996         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
997
998         if (oldevents != s->async->events) {
999                 comedi_event(dev, s);
1000         }
1001
1002         return (triggered != 0);
1003 }
1004
1005 /*
1006  * 'cancel' function for an 'INTERRUPT' subdevice.
1007  */
1008 static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
1009 {
1010         dio200_subdev_intr *subpriv = s->private;
1011         unsigned long flags;
1012
1013         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1014         if (subpriv->active) {
1015                 dio200_stop_intr(dev, s);
1016         }
1017         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1018
1019         return 0;
1020 }
1021
1022 /*
1023  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
1024  */
1025 static int
1026 dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
1027         comedi_cmd * cmd)
1028 {
1029         int err = 0;
1030         unsigned int tmp;
1031
1032         /* step 1: make sure trigger sources are trivially valid */
1033
1034         tmp = cmd->start_src;
1035         cmd->start_src &= (TRIG_NOW | TRIG_INT);
1036         if (!cmd->start_src || tmp != cmd->start_src)
1037                 err++;
1038
1039         tmp = cmd->scan_begin_src;
1040         cmd->scan_begin_src &= TRIG_EXT;
1041         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1042                 err++;
1043
1044         tmp = cmd->convert_src;
1045         cmd->convert_src &= TRIG_NOW;
1046         if (!cmd->convert_src || tmp != cmd->convert_src)
1047                 err++;
1048
1049         tmp = cmd->scan_end_src;
1050         cmd->scan_end_src &= TRIG_COUNT;
1051         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1052                 err++;
1053
1054         tmp = cmd->stop_src;
1055         cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
1056         if (!cmd->stop_src || tmp != cmd->stop_src)
1057                 err++;
1058
1059         if (err)
1060                 return 1;
1061
1062         /* step 2: make sure trigger sources are unique and mutually compatible */
1063
1064         /* these tests are true if more than one _src bit is set */
1065         if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1066                 err++;
1067         if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1068                 err++;
1069         if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1070                 err++;
1071         if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1072                 err++;
1073         if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1074                 err++;
1075
1076         if (err)
1077                 return 2;
1078
1079         /* step 3: make sure arguments are trivially compatible */
1080
1081         /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
1082         if (cmd->start_arg != 0) {
1083                 cmd->start_arg = 0;
1084                 err++;
1085         }
1086
1087         /* cmd->scan_begin_src == TRIG_EXT */
1088         if (cmd->scan_begin_arg != 0) {
1089                 cmd->scan_begin_arg = 0;
1090                 err++;
1091         }
1092
1093         /* cmd->convert_src == TRIG_NOW */
1094         if (cmd->convert_arg != 0) {
1095                 cmd->convert_arg = 0;
1096                 err++;
1097         }
1098
1099         /* cmd->scan_end_src == TRIG_COUNT */
1100         if (cmd->scan_end_arg != cmd->chanlist_len) {
1101                 cmd->scan_end_arg = cmd->chanlist_len;
1102                 err++;
1103         }
1104
1105         switch (cmd->stop_src) {
1106         case TRIG_COUNT:
1107                 /* any count allowed */
1108                 break;
1109         case TRIG_NONE:
1110                 if (cmd->stop_arg != 0) {
1111                         cmd->stop_arg = 0;
1112                         err++;
1113                 }
1114                 break;
1115         default:
1116                 break;
1117         }
1118
1119         if (err)
1120                 return 3;
1121
1122         /* step 4: fix up any arguments */
1123
1124         /* if (err) return 4; */
1125
1126         return 0;
1127 }
1128
1129 /*
1130  * 'do_cmd' function for an 'INTERRUPT' subdevice.
1131  */
1132 static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
1133 {
1134         comedi_cmd *cmd = &s->async->cmd;
1135         dio200_subdev_intr *subpriv = s->private;
1136         unsigned long flags;
1137         int event = 0;
1138
1139         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1140         subpriv->active = 1;
1141
1142         /* Set up end of acquisition. */
1143         switch (cmd->stop_src) {
1144         case TRIG_COUNT:
1145                 subpriv->continuous = 0;
1146                 subpriv->stopcount = cmd->stop_arg;
1147                 break;
1148         default:
1149                 /* TRIG_NONE */
1150                 subpriv->continuous = 1;
1151                 subpriv->stopcount = 0;
1152                 break;
1153         }
1154
1155         /* Set up start of acquisition. */
1156         switch (cmd->start_src) {
1157         case TRIG_INT:
1158                 s->async->inttrig = dio200_inttrig_start_intr;
1159                 break;
1160         default:
1161                 /* TRIG_NOW */
1162                 event = dio200_start_intr(dev, s);
1163                 break;
1164         }
1165         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1166
1167         if (event) {
1168                 comedi_event(dev, s);
1169         }
1170
1171         return 0;
1172 }
1173
1174 /*
1175  * This function initializes an 'INTERRUPT' subdevice.
1176  */
1177 static int
1178 dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
1179         unsigned int offset, unsigned valid_isns)
1180 {
1181         dio200_subdev_intr *subpriv;
1182
1183         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1184         if (!subpriv) {
1185                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1186                         dev->minor);
1187                 return -ENOMEM;
1188         }
1189         subpriv->ofs = offset;
1190         subpriv->valid_isns = valid_isns;
1191         spin_lock_init(&subpriv->spinlock);
1192
1193         if (thislayout->has_int_sce) {
1194                 /* Disable interrupt sources. */
1195                 dio200_write8(dev, subpriv->ofs, 0);
1196         }
1197
1198         s->private = subpriv;
1199         s->type = COMEDI_SUBD_DI;
1200         s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1201         if (thislayout->has_int_sce) {
1202                 s->n_chan = DIO200_MAX_ISNS;
1203                 s->len_chanlist = DIO200_MAX_ISNS;
1204         } else {
1205                 /* No interrupt source register.  Support single channel. */
1206                 s->n_chan = 1;
1207                 s->len_chanlist = 1;
1208         }
1209         s->range_table = &range_digital;
1210         s->maxdata = 1;
1211         s->insn_bits = dio200_subdev_intr_insn_bits;
1212         s->do_cmdtest = dio200_subdev_intr_cmdtest;
1213         s->do_cmd = dio200_subdev_intr_cmd;
1214         s->cancel = dio200_subdev_intr_cancel;
1215
1216         return 0;
1217 }
1218
1219 /*
1220  * This function cleans up an 'INTERRUPT' subdevice.
1221  */
1222 static void
1223 dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
1224 {
1225         dio200_subdev_intr *subpriv = s->private;
1226
1227         if (subpriv) {
1228                 kfree(subpriv);
1229         }
1230 }
1231
1232 /*
1233  * Interrupt service routine.
1234  */
1235 static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
1236 {
1237         comedi_device *dev = d;
1238         int handled;
1239
1240         if (!dev->attached) {
1241                 return IRQ_NONE;
1242         }
1243
1244         if (devpriv->intr_sd >= 0) {
1245                 handled = dio200_handle_read_intr(dev,
1246                         dev->subdevices + devpriv->intr_sd);
1247         } else {
1248                 handled = 0;
1249         }
1250
1251         return IRQ_RETVAL(handled);
1252 }
1253
1254 /*
1255  * Read an '8254' counter subdevice channel.
1256  */
1257 static inline unsigned int
1258 dio200_subdev_8254_read_chan(comedi_device * dev, comedi_subdevice * s,
1259         unsigned int chan)
1260 {
1261         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1262         unsigned int val;
1263
1264         /* latch counter */
1265         val = chan << 6;
1266         dio200_write8(dev, i8254_ofs + i8254_control_reg, val);
1267
1268         /* read lsb */
1269         val = dio200_read8(dev, i8254_ofs + chan);
1270         /* read msb */
1271         val += dio200_read8(dev, i8254_ofs + chan) << 8;
1272
1273         return val;
1274 }
1275
1276 /*
1277  * Write an '8254' counter subdevice channel.
1278  */
1279 static inline void
1280 dio200_subdev_8254_write_chan(comedi_device * dev, comedi_subdevice * s,
1281         unsigned int chan, unsigned int count)
1282 {
1283         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1284
1285         /* write lsb */
1286         dio200_write8(dev, i8254_ofs + chan, count & 0xff);
1287         /* write msb */
1288         dio200_write8(dev, i8254_ofs + chan, (count >> 8) & 0xff);
1289 }
1290
1291 /*
1292  * Set mode of an '8254' counter subdevice channel.
1293  */
1294 static inline void
1295 dio200_subdev_8254_set_mode(comedi_device * dev, comedi_subdevice * s,
1296         unsigned int chan, unsigned int mode)
1297 {
1298         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1299         unsigned int byte;
1300
1301         byte = chan << 6;
1302         byte |= 0x30;           /* load lsb then msb */
1303         byte |= (mode & 0xf);   /* set counter mode and BCD|binary */
1304         dio200_write8(dev, i8254_ofs + i8254_control_reg, byte);
1305 }
1306
1307 /*
1308  * Read status byte of an '8254' counter subdevice channel.
1309  */
1310 static inline unsigned int
1311 dio200_subdev_8254_status(comedi_device * dev, comedi_subdevice * s,
1312         unsigned int chan)
1313 {
1314         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1315
1316         dio200_write8(dev, i8254_ofs + i8254_control_reg, (0xE0 | 2 << chan));
1317         return dio200_read8(dev, i8254_ofs + chan);
1318 }
1319
1320 /*
1321  * Handle 'insn_read' for an '8254' counter subdevice.
1322  */
1323 static int
1324 dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
1325         comedi_insn * insn, lsampl_t * data)
1326 {
1327         dio200_subdev_8254 *subpriv = s->private;
1328         int chan = CR_CHAN(insn->chanspec);
1329         unsigned long flags;
1330
1331         if (insn->n == 0)
1332                 return 0;
1333
1334         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1335         data[0] = dio200_subdev_8254_read_chan(dev, s, chan);
1336         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1337
1338         return 1;
1339 }
1340
1341 /*
1342  * Handle 'insn_write' for an '8254' counter subdevice.
1343  */
1344 static int
1345 dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
1346         comedi_insn * insn, lsampl_t * data)
1347 {
1348         dio200_subdev_8254 *subpriv = s->private;
1349         int chan = CR_CHAN(insn->chanspec);
1350         unsigned long flags;
1351
1352         if (insn->n == 0)
1353                 return 0;
1354
1355         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1356         dio200_subdev_8254_write_chan(dev, s, chan, data[0]);
1357         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1358
1359         return 1;
1360 }
1361
1362 /*
1363  * Set gate source for an '8254' counter subdevice channel.
1364  */
1365 static int
1366 dio200_subdev_8254_set_gate_src(comedi_device * dev, comedi_subdevice *s,
1367         unsigned int counter_number, unsigned int gate_src)
1368 {
1369         dio200_subdev_8254 *subpriv = s->private;
1370         unsigned char byte;
1371
1372         if (!thislayout->has_clk_gat_sce)
1373                 return -1;
1374         if (counter_number > 2)
1375                 return -1;
1376         if (gate_src > (thislayout->has_enhancements ? 31 : 7))
1377                 return -1;
1378
1379         subpriv->gate_src[counter_number] = gate_src;
1380         byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1381         dio200_write8(dev, subpriv->gat_sce_ofs, byte);
1382
1383         return 0;
1384 }
1385
1386 /*
1387  * Get gate source for an '8254' counter subdevice channel.
1388  */
1389 static int
1390 dio200_subdev_8254_get_gate_src(comedi_device * dev, comedi_subdevice *s,
1391         unsigned int counter_number)
1392 {
1393         dio200_subdev_8254 *subpriv = s->private;
1394
1395         if (!thislayout->has_clk_gat_sce)
1396                 return -1;
1397         if (counter_number > 2)
1398                 return -1;
1399
1400         return subpriv->gate_src[counter_number];
1401 }
1402
1403 /*
1404  * Set clock source for an '8254' counter subdevice channel.
1405  */
1406 static int
1407 dio200_subdev_8254_set_clock_src(comedi_device * dev, comedi_subdevice *s,
1408         unsigned int counter_number, unsigned int clock_src)
1409 {
1410         dio200_subdev_8254 *subpriv = s->private;
1411         unsigned char byte;
1412
1413         if (!thislayout->has_clk_gat_sce)
1414                 return -1;
1415         if (counter_number > 2)
1416                 return -1;
1417         if (clock_src > (thislayout->has_enhancements ? 31 : 7))
1418                 return -1;
1419
1420         subpriv->clock_src[counter_number] = clock_src;
1421         byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1422         dio200_write8(dev, subpriv->clk_sce_ofs, byte);
1423
1424         return 0;
1425 }
1426
1427 /*
1428  * Get clock source for an '8254' counter subdevice channel.
1429  */
1430 static int
1431 dio200_subdev_8254_get_clock_src(comedi_device * dev, comedi_subdevice *s,
1432         unsigned int counter_number, lsampl_t * period_ns)
1433 {
1434         dio200_subdev_8254 *subpriv = s->private;
1435         unsigned clock_src;
1436
1437         if (!thislayout->has_clk_gat_sce)
1438                 return -1;
1439         if (counter_number > 2)
1440                 return -1;
1441
1442         clock_src = subpriv->clock_src[counter_number];
1443         *period_ns = clock_period[clock_src];
1444         return clock_src;
1445 }
1446
1447 /*
1448  * Handle 'insn_config' for an '8254' counter subdevice.
1449  */
1450 static int
1451 dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
1452         comedi_insn * insn, lsampl_t * data)
1453 {
1454         dio200_subdev_8254 *subpriv = s->private;
1455         int ret = 0;
1456         int chan = CR_CHAN(insn->chanspec);
1457         unsigned long flags;
1458
1459         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1460         switch (data[0]) {
1461         case INSN_CONFIG_SET_COUNTER_MODE:
1462                 if (data[1] > (I8254_MODE5 | I8254_BINARY))
1463                         ret = -EINVAL;
1464                 else
1465                         dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
1466                 break;
1467         case INSN_CONFIG_8254_READ_STATUS:
1468                 data[1] = dio200_subdev_8254_status(dev, s, chan);
1469                 break;
1470         case INSN_CONFIG_SET_GATE_SRC:
1471                 ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
1472                 if (ret < 0)
1473                         ret = -EINVAL;
1474                 break;
1475         case INSN_CONFIG_GET_GATE_SRC:
1476                 ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
1477                 if (ret < 0) {
1478                         ret = -EINVAL;
1479                         break;
1480                 }
1481                 data[2] = ret;
1482                 break;
1483         case INSN_CONFIG_SET_CLOCK_SRC:
1484                 ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
1485                 if (ret < 0)
1486                         ret = -EINVAL;
1487                 break;
1488         case INSN_CONFIG_GET_CLOCK_SRC:
1489                 ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
1490                 if (ret < 0) {
1491                         ret = -EINVAL;
1492                         break;
1493                 }
1494                 data[1] = ret;
1495                 break;
1496         default:
1497                 ret = -EINVAL;
1498                 break;
1499         }
1500         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1501         return ret < 0 ? ret : insn->n;
1502 }
1503
1504 /*
1505  * This function initializes an '8254' counter subdevice.
1506  *
1507  * offset is the offset to the 8254 chip.
1508  */
1509 static int
1510 dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
1511         unsigned int offset)
1512 {
1513         dio200_subdev_8254 *subpriv;
1514         unsigned int chan;
1515
1516         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1517         if (!subpriv) {
1518                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1519                         dev->minor);
1520                 return -ENOMEM;
1521         }
1522
1523         s->private = subpriv;
1524         s->type = COMEDI_SUBD_COUNTER;
1525         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1526         s->n_chan = 3;
1527         s->maxdata = 0xFFFF;
1528         s->insn_read = dio200_subdev_8254_read;
1529         s->insn_write = dio200_subdev_8254_write;
1530         s->insn_config = dio200_subdev_8254_config;
1531
1532         spin_lock_init(&subpriv->spinlock);
1533         subpriv->ofs = offset;
1534         if (thislayout->has_clk_gat_sce) {
1535                 /* Derive CLK_SCE and GAT_SCE register offsets from
1536                  * 8254 offset. */
1537                 subpriv->clk_sce_ofs =
1538                         DIO200_XCLK_SCE + (offset >> 3);
1539                 subpriv->gat_sce_ofs =
1540                         DIO200_XGAT_SCE + (offset >> 3);
1541                 subpriv->which = (offset >> 2) & 1;
1542         }
1543
1544         /* Initialize channels. */
1545         for (chan = 0; chan < 3; chan++) {
1546                 dio200_subdev_8254_set_mode(dev, s, chan,
1547                         (I8254_MODE0 | I8254_BINARY));
1548                 if (thislayout->has_clk_gat_sce) {
1549                         /* Gate source 0 is VCC (logic 1). */
1550                         dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
1551                         /* Clock source 0 is the dedicated clock input. */
1552                         dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
1553                 }
1554         }
1555
1556         return 0;
1557 }
1558
1559 /*
1560  * This function cleans up an '8254' counter subdevice.
1561  */
1562 static void
1563 dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
1564 {
1565         dio200_subdev_8254 *subpriv = s->private;
1566
1567         if (subpriv) {
1568                 kfree(subpriv);
1569         }
1570 }
1571
1572 /*
1573  * This function sets I/O directions for an '8255' DIO subdevice.
1574  */
1575 static void
1576 dio200_subdev_8255_set_dir(comedi_device * dev, comedi_subdevice * s)
1577 {
1578         dio200_subdev_8255 *subpriv = s->private;
1579         int config;
1580
1581         config = CR_CW;
1582         /* 1 in io_bits indicates output, 1 in config indicates input */
1583         if (!(s->io_bits & 0x0000ff))
1584                 config |= CR_A_IO;
1585         if (!(s->io_bits & 0x00ff00))
1586                 config |= CR_B_IO;
1587         if (!(s->io_bits & 0x0f0000))
1588                 config |= CR_C_LO_IO;
1589         if (!(s->io_bits & 0xf00000))
1590                 config |= CR_C_HI_IO;
1591
1592         dio200_write8(dev, subpriv->ofs + 3, config);
1593 }
1594
1595 /*
1596  * Handle 'insn_bits' for an '8255' DIO subdevice.
1597  */
1598 static int
1599 dio200_subdev_8255_bits(comedi_device * dev, comedi_subdevice * s,
1600         comedi_insn * insn, lsampl_t * data)
1601 {
1602         unsigned int i8255_ofs = ((dio200_subdev_8255 *)s->private)->ofs;
1603
1604         if (data[0]) {
1605                 s->state &= ~data[0];
1606                 s->state |= (data[0] & data[1]);
1607
1608                 if (data[0] & 0xff) {
1609                         dio200_write8(dev, i8255_ofs, s->state & 0xff);
1610                 }
1611                 if (data[0] & 0xff00) {
1612                         dio200_write8(dev, i8255_ofs + 1,
1613                                 (s->state >> 8) & 0xff);
1614                 }
1615                 if (data[0] & 0xff0000) {
1616                         dio200_write8(dev, i8255_ofs + 2,
1617                                 (s->state >> 16) & 0xff);
1618                 }
1619         }
1620
1621         data[1] = dio200_read8(dev, i8255_ofs);
1622         data[1] |= dio200_read8(dev, i8255_ofs + 1) << 8;
1623         data[1] |= dio200_read8(dev, i8255_ofs + 2) << 16;
1624
1625         return 2;
1626 }
1627
1628 /*
1629  * Handle 'insn_config' for an '8255' DIO subdevice.
1630  */
1631 static int
1632 dio200_subdev_8255_config(comedi_device * dev, comedi_subdevice * s,
1633         comedi_insn * insn, lsampl_t * data)
1634 {
1635         unsigned int mask;
1636         unsigned int bits;
1637
1638         mask = 1 << CR_CHAN(insn->chanspec);
1639         if (mask & 0x0000ff) {
1640                 bits = 0x0000ff;
1641         } else if (mask & 0x00ff00) {
1642                 bits = 0x00ff00;
1643         } else if (mask & 0x0f0000) {
1644                 bits = 0x0f0000;
1645         } else {
1646                 bits = 0xf00000;
1647         }
1648
1649         switch (data[0]) {
1650         case INSN_CONFIG_DIO_INPUT:
1651                 s->io_bits &= ~bits;
1652                 break;
1653         case INSN_CONFIG_DIO_OUTPUT:
1654                 s->io_bits |= bits;
1655                 break;
1656         case INSN_CONFIG_DIO_QUERY:
1657                 data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
1658                 return insn->n;
1659                 break;
1660         default:
1661                 return -EINVAL;
1662         }
1663
1664         dio200_subdev_8255_set_dir(dev, s);
1665
1666         return 1;
1667 }
1668
1669 /*
1670  * This function initializes an '8255' DIO subdevice.
1671  *
1672  * offset is the offset to the 8255 chip.
1673  */
1674 static int
1675 dio200_subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
1676         unsigned int offset)
1677 {
1678         dio200_subdev_8255 *subpriv;
1679
1680         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1681         if (!subpriv) {
1682                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1683                         dev->minor);
1684                 return -ENOMEM;
1685         }
1686
1687         subpriv->ofs = offset;
1688
1689         s->private = subpriv;
1690         s->type = COMEDI_SUBD_DIO;
1691         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1692         s->n_chan = 24;
1693         s->range_table = &range_digital;
1694         s->maxdata = 1;
1695         s->insn_bits = dio200_subdev_8255_bits;
1696         s->insn_config = dio200_subdev_8255_config;
1697
1698         s->state = 0;
1699         s->io_bits = 0;
1700         dio200_subdev_8255_set_dir(dev, s);
1701
1702         return 0;
1703 }
1704
1705 /*
1706  * This function cleans up an '8255' DIO subdevice.
1707  */
1708 static void
1709 dio200_subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s)
1710 {
1711         dio200_subdev_8255 *subpriv = s->private;
1712
1713         if (subpriv) {
1714                 kfree(subpriv);
1715         }
1716 }
1717
1718 #ifdef CONFIG_COMEDI_PCI
1719 /*
1720  * This function does some special set-up for the PCIe boards
1721  * PCIe215, PCIe236, PCIe296.
1722  */
1723 static int
1724 dio200_pcie_board_setup(comedi_device * dev)
1725 {
1726         struct pci_dev *pci_dev = devpriv->pci_dev;
1727         unsigned char __iomem *brbase;
1728         resource_size_t brlen;
1729
1730         /*
1731          * The board uses Altera Cyclone IV with PCI-Express hard IP.
1732          * The FPGA configuration has the PCI-Express Avalon-MM Bridge
1733          * Control registers in PCI BAR 0, offset 0, and the length of
1734          * these registers is 0x4000.
1735          *
1736          * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
1737          * Enable" register at offset 0x50 to allow generation of PCIe
1738          * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
1739          */
1740         brlen = pci_resource_len(pci_dev, 0);
1741         if (brlen < 0x4000 ||
1742                         !(pci_resource_flags(pci_dev, 0) & IORESOURCE_MEM)) {
1743                 printk(KERN_ERR "comedi%d: error! bad PCI region!\n",
1744                         dev->minor);
1745                 return -EINVAL;
1746         }
1747         brbase = ioremap_nocache(pci_resource_start(pci_dev, 0), brlen);
1748         if (!brbase) {
1749                 printk(KERN_ERR "comedi%d: error! failed to map registers!\n",
1750                         dev->minor);
1751                 return -ENOMEM;
1752         }
1753         writel(0x80, brbase + 0x50);
1754         iounmap(brbase);
1755         /*
1756          * Enable "enhanced" features of board.
1757          */
1758         dio200_write8(dev, DIO200_ENHANCE, 1);
1759         return 0;
1760 }
1761 #endif
1762
1763 /*
1764  * Attach is called by the Comedi core to configure the driver
1765  * for a particular board.  If you specified a board_name array
1766  * in the driver structure, dev->board_ptr contains that
1767  * address.
1768  */
1769 static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
1770 {
1771         comedi_subdevice *s;
1772         unsigned long iobase = 0;
1773         unsigned int irq = 0;
1774 #ifdef CONFIG_COMEDI_PCI
1775         struct pci_dev *pci_dev = NULL;
1776         int bus = 0, slot = 0;
1777 #endif
1778         const dio200_layout *layout;
1779         int share_irq = 0;
1780         int sdx;
1781         unsigned n;
1782         int ret;
1783
1784         printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1785                 DIO200_DRIVER_NAME);
1786
1787         if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
1788                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1789                         dev->minor);
1790                 return ret;
1791         }
1792
1793         /* Process options. */
1794         switch (thisboard->bustype) {
1795         case isa_bustype:
1796                 iobase = it->options[0];
1797                 irq = it->options[1];
1798                 share_irq = 0;
1799                 break;
1800 #ifdef CONFIG_COMEDI_PCI
1801         case pci_bustype:
1802                 bus = it->options[0];
1803                 slot = it->options[1];
1804                 share_irq = 1;
1805
1806                 if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
1807                         return ret;
1808                 devpriv->pci_dev = pci_dev;
1809                 break;
1810 #endif
1811         default:
1812                 printk(KERN_ERR
1813                         "comedi%d: %s: BUG! cannot determine board type!\n",
1814                         dev->minor, DIO200_DRIVER_NAME);
1815                 return -EINVAL;
1816                 break;
1817         }
1818
1819         devpriv->intr_sd = -1;
1820         devpriv->io.regtype = no_regtype;
1821         devpriv->io.regshift = thisboard->mainshift;
1822
1823         /* Enable device and reserve I/O spaces. */
1824 #ifdef CONFIG_COMEDI_PCI
1825         if (pci_dev) {
1826                 resource_size_t base, len;
1827                 unsigned int bar;
1828
1829                 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1830                 if (ret < 0) {
1831                         printk(KERN_ERR
1832                                 "comedi%d: error! cannot enable PCI device and request regions!\n",
1833                                 dev->minor);
1834                         return ret;
1835                 }
1836                 bar = thisboard->mainbar;
1837                 base = pci_resource_start(pci_dev, bar);
1838                 len = pci_resource_len(pci_dev, bar);
1839                 if (len < thisboard->mainsize) {
1840                         printk(KERN_ERR
1841                                 "comedi%d: error! PCI region size too small!\n",
1842                                 dev->minor);
1843                         return -EINVAL;
1844                 }
1845                 if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
1846                         devpriv->io.u.membase = ioremap_nocache(base, len);
1847                         if (!devpriv->io.u.membase) {
1848                                 printk(KERN_ERR
1849                                         "comedi%d: error! cannot remap registers!\n",
1850                                         dev->minor);
1851                                 return -ENOMEM;
1852                         }
1853                         devpriv->io.regtype = mmio_regtype;
1854                 } else {
1855                         devpriv->io.u.iobase = (unsigned long)base;
1856                         devpriv->io.regtype = io_regtype;
1857                 }
1858                 irq = pci_dev->irq;
1859         } else
1860 #endif
1861         {
1862                 ret = dio200_request_region(dev->minor, iobase,
1863                         thisboard->mainsize);
1864                 if (ret < 0) {
1865                         return ret;
1866                 }
1867                 devpriv->io.u.iobase = iobase;
1868                 devpriv->io.regtype = io_regtype;
1869         }
1870
1871         switch (thisboard->model) {
1872 #ifdef CONFIG_COMEDI_PCI
1873         case pcie215_model:
1874         case pcie236_model:
1875         case pcie296_model:
1876                 ret = dio200_pcie_board_setup(dev);
1877                 if (ret < 0) {
1878                         return ret;
1879                 }
1880                 break;
1881 #endif
1882         default:
1883                 break;
1884         }
1885
1886         layout = thislayout;
1887         if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
1888                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1889                         dev->minor);
1890                 return ret;
1891         }
1892
1893         for (n = 0; n < dev->n_subdevices; n++) {
1894                 s = &dev->subdevices[n];
1895                 switch (layout->sdtype[n]) {
1896                 case sd_8254:
1897                         /* counter subdevice (8254) */
1898                         ret = dio200_subdev_8254_init(dev, s,
1899                                 layout->sdinfo[n]);
1900                         if (ret < 0) {
1901                                 return ret;
1902                         }
1903                         break;
1904                 case sd_8255:
1905                         /* digital i/o subdevice (8255) */
1906                         ret = dio200_subdev_8255_init(dev, s,
1907                                 layout->sdinfo[n]);
1908                         if (ret < 0) {
1909                                 return ret;
1910                         }
1911                         break;
1912                 case sd_intr:
1913                         /* 'INTERRUPT' subdevice */
1914                         if (irq) {
1915                                 ret = dio200_subdev_intr_init(dev, s,
1916                                         DIO200_INT_SCE, layout->sdinfo[n]);
1917                                 if (ret < 0) {
1918                                         return ret;
1919                                 }
1920                                 devpriv->intr_sd = n;
1921                         } else {
1922                                 s->type = COMEDI_SUBD_UNUSED;
1923                         }
1924                         break;
1925                 case sd_timer:
1926                         /* TODO.  Fall-thru to default for now. */
1927                 default:
1928                         s->type = COMEDI_SUBD_UNUSED;
1929                         break;
1930                 }
1931         }
1932
1933         sdx = devpriv->intr_sd;
1934         if (sdx >= 0 && sdx < dev->n_subdevices) {
1935                 dev->read_subdev = &dev->subdevices[sdx];
1936         }
1937
1938         dev->board_name = thisboard->name;
1939
1940         if (irq) {
1941                 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1942
1943                 if (comedi_request_irq(irq, dio200_interrupt, flags,
1944                                 DIO200_DRIVER_NAME, dev) >= 0) {
1945                         dev->irq = irq;
1946                 } else {
1947                         printk(KERN_WARNING
1948                                 "comedi%d: warning! irq %u unavailable!\n",
1949                                 dev->minor, irq);
1950                 }
1951         }
1952
1953         printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1954         if (thisboard->bustype == isa_bustype) {
1955                 printk("(base %#lx) ", iobase);
1956         } else {
1957 #ifdef CONFIG_COMEDI_PCI
1958                 printk("(pci %s) ", pci_name(pci_dev));
1959 #endif
1960         }
1961         if (irq) {
1962                 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1963         } else {
1964                 printk("(no irq) ");
1965         }
1966
1967         printk("attached\n");
1968
1969         return 1;
1970 }
1971
1972 /*
1973  * _detach is called to deconfigure a device.  It should deallocate
1974  * resources.
1975  * This function is also called when _attach() fails, so it should be
1976  * careful not to release resources that were not necessarily
1977  * allocated by _attach().  dev->private and dev->subdevices are
1978  * deallocated automatically by the core.
1979  */
1980 static int dio200_detach(comedi_device * dev)
1981 {
1982         const dio200_layout *layout;
1983         unsigned n;
1984
1985         printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1986                 DIO200_DRIVER_NAME);
1987
1988         if (dev->irq) {
1989                 comedi_free_irq(dev->irq, dev);
1990         }
1991         if (dev->subdevices) {
1992                 layout = thislayout;
1993                 for (n = 0; n < dev->n_subdevices; n++) {
1994                         comedi_subdevice *s = &dev->subdevices[n];
1995                         switch (layout->sdtype[n]) {
1996                         case sd_8254:
1997                                 dio200_subdev_8254_cleanup(dev, s);
1998                                 break;
1999                         case sd_8255:
2000                                 dio200_subdev_8255_cleanup(dev, s);
2001                                 break;
2002                         case sd_intr:
2003                                 dio200_subdev_intr_cleanup(dev, s);
2004                                 break;
2005                         default:
2006                                 break;
2007                         }
2008                 }
2009         }
2010         if (devpriv) {
2011                 if (devpriv->io.regtype == mmio_regtype) {
2012                         iounmap(devpriv->io.u.membase);
2013                 }
2014 #ifdef CONFIG_COMEDI_PCI
2015                 if (devpriv->pci_dev) {
2016                         if (devpriv->io.regtype != no_regtype) {
2017                                 comedi_pci_disable(devpriv->pci_dev);
2018                         }
2019                         pci_dev_put(devpriv->pci_dev);
2020                 } else
2021 #endif
2022                 {
2023                         if (devpriv->io.regtype == io_regtype) {
2024                                 release_region(devpriv->io.u.iobase,
2025                                         thisboard->mainsize);
2026                         }
2027                 }
2028         }
2029         if (dev->board_name) {
2030                 printk(KERN_INFO "comedi%d: %s removed\n",
2031                         dev->minor, dev->board_name);
2032         }
2033
2034         return 0;
2035 }