amplc_dio200: Allow extra clock and gate sources for PCIe boards.
[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-OUT                     PPI-Y-C0
180    3              CTR-Y2-OUT                     PPI-Y-C3
181    4              CTR-Z1-OUT                    CTR-Z1-OUT
182    5              CTR-Z2-OUT                    CTR-Z2-OUT
183
184                     PCIe215        PC218E         PCIe236
185                  -------------  -------------  -------------
186   Sources              6              6              6
187    0               PPI-X-C0      CTR-X1-OUT      PPI-X-C0
188    1               PPI-X-C3      CTR-X2-OUT      PPI-X-C3
189    2               PPI-Y-C0      CTR-Y1-OUT       unused
190    3               PPI-Y-C3      CTR-Y2-OUT       unused
191    4              CTR-Z1-OUT     CTR-Z1-OUT     CTR-Z1-OUT
192    5              CTR-Z2-OUT     CTR-Z2-OUT     CTR-Z2-OUT
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-OUT
202    5               PPI-Z-C3      CTR-Z2-OUT
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  * This function looks for a PCI device matching the requested board name,
686  * bus and slot.
687  */
688 #ifdef CONFIG_COMEDI_PCI
689 static int
690 dio200_find_pci(comedi_device * dev, int bus, int slot,
691         struct pci_dev **pci_dev_p)
692 {
693         struct pci_dev *pci_dev = NULL;
694
695         *pci_dev_p = NULL;
696
697         /* Look for matching PCI device. */
698         for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
699                 pci_dev != NULL;
700                 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
701                         PCI_ANY_ID, pci_dev)) {
702                 /* If bus/slot specified, check them. */
703                 if (bus || slot) {
704                         if (bus != pci_dev->bus->number
705                                 || slot != PCI_SLOT(pci_dev->devfn))
706                                 continue;
707                 }
708                 if (thisboard->model == anypci_model) {
709                         /* Match any supported model. */
710                         int i;
711
712                         for (i = 0; i < ARRAY_SIZE(dio200_boards); i++) {
713                                 if (dio200_boards[i].bustype != pci_bustype)
714                                         continue;
715                                 if (pci_dev->device == dio200_boards[i].devid) {
716                                         /* Change board_ptr to matched board. */
717                                         dev->board_ptr = &dio200_boards[i];
718                                         break;
719                                 }
720                         }
721                         if (i == ARRAY_SIZE(dio200_boards))
722                                 continue;
723                 } else {
724                         /* Match specific model name. */
725                         if (pci_dev->device != thisboard->devid)
726                                 continue;
727                 }
728
729                 /* Found a match. */
730                 *pci_dev_p = pci_dev;
731                 return 0;
732         }
733         /* No match found. */
734         if (bus || slot) {
735                 printk(KERN_ERR
736                         "comedi%d: error! no %s found at pci %02x:%02x!\n",
737                         dev->minor, thisboard->name, bus, slot);
738         } else {
739                 printk(KERN_ERR "comedi%d: error! no %s found!\n",
740                         dev->minor, thisboard->name);
741         }
742         return -EIO;
743 }
744 #endif
745
746 /*
747  * This function checks and requests an I/O region, reporting an error
748  * if there is a conflict.
749  */
750 static int
751 dio200_request_region(unsigned minor, unsigned long from, unsigned long extent)
752 {
753         if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
754                 printk(KERN_ERR "comedi%d: I/O port conflict (%#lx,%lu)!\n",
755                         minor, from, extent);
756                 return -EIO;
757         }
758         return 0;
759 }
760
761 /*
762  * 'insn_bits' function for an 'INTERRUPT' subdevice.
763  */
764 static int
765 dio200_subdev_intr_insn_bits(comedi_device * dev, comedi_subdevice * s,
766         comedi_insn * insn, lsampl_t * data)
767 {
768         dio200_subdev_intr *subpriv = s->private;
769
770         if (thislayout->has_int_sce) {
771                 /* Just read the interrupt status register.  */
772                 data[1] = dio200_read8(dev, subpriv->ofs) & subpriv->valid_isns;
773         } else {
774                 /* No interrupt status register. */
775                 data[0] = 0;
776         }
777
778         return 2;
779 }
780
781 /*
782  * Called to stop acquisition for an 'INTERRUPT' subdevice.
783  */
784 static void dio200_stop_intr(comedi_device * dev, comedi_subdevice * s)
785 {
786         dio200_subdev_intr *subpriv = s->private;
787
788         subpriv->active = 0;
789         subpriv->enabled_isns = 0;
790         if (thislayout->has_int_sce) {
791                 dio200_write8(dev, subpriv->ofs, 0);
792         }
793 }
794
795 /*
796  * Called to start acquisition for an 'INTERRUPT' subdevice.
797  */
798 static int dio200_start_intr(comedi_device * dev, comedi_subdevice * s)
799 {
800         unsigned int n;
801         unsigned isn_bits;
802         dio200_subdev_intr *subpriv = s->private;
803         comedi_cmd *cmd = &s->async->cmd;
804         int retval = 0;
805
806         if (!subpriv->continuous && subpriv->stopcount == 0) {
807                 /* An empty acquisition! */
808                 s->async->events |= COMEDI_CB_EOA;
809                 subpriv->active = 0;
810                 retval = 1;
811         } else {
812                 /* Determine interrupt sources to enable. */
813                 isn_bits = 0;
814                 if (cmd->chanlist) {
815                         for (n = 0; n < cmd->chanlist_len; n++) {
816                                 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
817                         }
818                 }
819                 isn_bits &= subpriv->valid_isns;
820                 /* Enable interrupt sources. */
821                 subpriv->enabled_isns = isn_bits;
822                 if (thislayout->has_int_sce) {
823                         dio200_write8(dev, subpriv->ofs, isn_bits);
824                 }
825         }
826
827         return retval;
828 }
829
830 /*
831  * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
832  */
833 static int
834 dio200_inttrig_start_intr(comedi_device * dev, comedi_subdevice * s,
835         unsigned int trignum)
836 {
837         dio200_subdev_intr *subpriv;
838         unsigned long flags;
839         int event = 0;
840
841         if (trignum != 0)
842                 return -EINVAL;
843
844         subpriv = s->private;
845
846         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
847         s->async->inttrig = 0;
848         if (subpriv->active) {
849                 event = dio200_start_intr(dev, s);
850         }
851         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
852
853         if (event) {
854                 comedi_event(dev, s);
855         }
856
857         return 1;
858 }
859
860 /*
861  * This is called from the interrupt service routine to handle a read
862  * scan on an 'INTERRUPT' subdevice.
863  */
864 static int dio200_handle_read_intr(comedi_device * dev, comedi_subdevice * s)
865 {
866         dio200_subdev_intr *subpriv = s->private;
867         unsigned triggered;
868         unsigned intstat;
869         unsigned cur_enabled;
870         unsigned int oldevents;
871         unsigned long flags;
872         unsigned int int_sce_ofs;
873
874         int_sce_ofs = subpriv->ofs;
875         triggered = 0;
876
877         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
878         oldevents = s->async->events;
879         if (thislayout->has_int_sce) {
880                 /*
881                  * Collect interrupt sources that have triggered and disable
882                  * them temporarily.  Loop around until no extra interrupt
883                  * sources have triggered, at which point, the valid part of
884                  * the interrupt status register will read zero, clearing the
885                  * cause of the interrupt.
886                  *
887                  * Mask off interrupt sources already seen to avoid infinite
888                  * loop in case of misconfiguration.
889                  */
890                 cur_enabled = subpriv->enabled_isns;
891                 while ((intstat = (dio200_read8(dev, int_sce_ofs)
892                                         & subpriv->valid_isns & ~triggered))
893                                 != 0) {
894                         triggered |= intstat;
895                         cur_enabled &= ~triggered;
896                         dio200_write8(dev, int_sce_ofs, cur_enabled);
897                 }
898         } else {
899                 /*
900                  * No interrupt status register.  Assume the single interrupt
901                  * source has triggered.
902                  */
903                 triggered = subpriv->enabled_isns;
904         }
905
906         if (triggered) {
907                 /*
908                  * Some interrupt sources have triggered and have been
909                  * temporarily disabled to clear the cause of the interrupt.
910                  *
911                  * Reenable them NOW to minimize the time they are disabled.
912                  */
913                 cur_enabled = subpriv->enabled_isns;
914                 if (thislayout->has_int_sce) {
915                         dio200_write8(dev, int_sce_ofs, cur_enabled);
916                 }
917
918                 if (subpriv->active) {
919                         /*
920                          * The command is still active.
921                          *
922                          * Ignore interrupt sources that the command isn't
923                          * interested in (just in case there's a race
924                          * condition).
925                          */
926                         if (triggered & subpriv->enabled_isns) {
927                                 /* Collect scan data. */
928                                 sampl_t val;
929                                 unsigned int n, ch, len;
930
931                                 val = 0;
932                                 len = s->async->cmd.chanlist_len;
933                                 for (n = 0; n < len; n++) {
934                                         ch = CR_CHAN(s->async->cmd.chanlist[n]);
935                                         if (triggered & (1U << ch)) {
936                                                 val |= (1U << n);
937                                         }
938                                 }
939                                 /* Write the scan to the buffer. */
940                                 if (comedi_buf_put(s->async, val)) {
941                                         s->async->events |= (COMEDI_CB_BLOCK |
942                                                 COMEDI_CB_EOS);
943                                 } else {
944                                         /* Error!  Stop acquisition.  */
945                                         dio200_stop_intr(dev, s);
946                                         s->async->events |= COMEDI_CB_ERROR
947                                                 | COMEDI_CB_OVERFLOW;
948                                         comedi_error(dev, "buffer overflow");
949                                 }
950
951                                 /* Check for end of acquisition. */
952                                 if (!subpriv->continuous) {
953                                         /* stop_src == TRIG_COUNT */
954                                         if (subpriv->stopcount > 0) {
955                                                 subpriv->stopcount--;
956                                                 if (subpriv->stopcount == 0) {
957                                                         s->async->events |=
958                                                                 COMEDI_CB_EOA;
959                                                         dio200_stop_intr(dev,
960                                                                 s);
961                                                 }
962                                         }
963                                 }
964                         }
965                 }
966         }
967         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
968
969         if (oldevents != s->async->events) {
970                 comedi_event(dev, s);
971         }
972
973         return (triggered != 0);
974 }
975
976 /*
977  * 'cancel' function for an 'INTERRUPT' subdevice.
978  */
979 static int dio200_subdev_intr_cancel(comedi_device * dev, comedi_subdevice * s)
980 {
981         dio200_subdev_intr *subpriv = s->private;
982         unsigned long flags;
983
984         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
985         if (subpriv->active) {
986                 dio200_stop_intr(dev, s);
987         }
988         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
989
990         return 0;
991 }
992
993 /*
994  * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
995  */
996 static int
997 dio200_subdev_intr_cmdtest(comedi_device * dev, comedi_subdevice * s,
998         comedi_cmd * cmd)
999 {
1000         int err = 0;
1001         unsigned int tmp;
1002
1003         /* step 1: make sure trigger sources are trivially valid */
1004
1005         tmp = cmd->start_src;
1006         cmd->start_src &= (TRIG_NOW | TRIG_INT);
1007         if (!cmd->start_src || tmp != cmd->start_src)
1008                 err++;
1009
1010         tmp = cmd->scan_begin_src;
1011         cmd->scan_begin_src &= TRIG_EXT;
1012         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1013                 err++;
1014
1015         tmp = cmd->convert_src;
1016         cmd->convert_src &= TRIG_NOW;
1017         if (!cmd->convert_src || tmp != cmd->convert_src)
1018                 err++;
1019
1020         tmp = cmd->scan_end_src;
1021         cmd->scan_end_src &= TRIG_COUNT;
1022         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1023                 err++;
1024
1025         tmp = cmd->stop_src;
1026         cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
1027         if (!cmd->stop_src || tmp != cmd->stop_src)
1028                 err++;
1029
1030         if (err)
1031                 return 1;
1032
1033         /* step 2: make sure trigger sources are unique and mutually compatible */
1034
1035         /* these tests are true if more than one _src bit is set */
1036         if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1037                 err++;
1038         if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1039                 err++;
1040         if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1041                 err++;
1042         if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1043                 err++;
1044         if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1045                 err++;
1046
1047         if (err)
1048                 return 2;
1049
1050         /* step 3: make sure arguments are trivially compatible */
1051
1052         /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
1053         if (cmd->start_arg != 0) {
1054                 cmd->start_arg = 0;
1055                 err++;
1056         }
1057
1058         /* cmd->scan_begin_src == TRIG_EXT */
1059         if (cmd->scan_begin_arg != 0) {
1060                 cmd->scan_begin_arg = 0;
1061                 err++;
1062         }
1063
1064         /* cmd->convert_src == TRIG_NOW */
1065         if (cmd->convert_arg != 0) {
1066                 cmd->convert_arg = 0;
1067                 err++;
1068         }
1069
1070         /* cmd->scan_end_src == TRIG_COUNT */
1071         if (cmd->scan_end_arg != cmd->chanlist_len) {
1072                 cmd->scan_end_arg = cmd->chanlist_len;
1073                 err++;
1074         }
1075
1076         switch (cmd->stop_src) {
1077         case TRIG_COUNT:
1078                 /* any count allowed */
1079                 break;
1080         case TRIG_NONE:
1081                 if (cmd->stop_arg != 0) {
1082                         cmd->stop_arg = 0;
1083                         err++;
1084                 }
1085                 break;
1086         default:
1087                 break;
1088         }
1089
1090         if (err)
1091                 return 3;
1092
1093         /* step 4: fix up any arguments */
1094
1095         /* if (err) return 4; */
1096
1097         return 0;
1098 }
1099
1100 /*
1101  * 'do_cmd' function for an 'INTERRUPT' subdevice.
1102  */
1103 static int dio200_subdev_intr_cmd(comedi_device * dev, comedi_subdevice * s)
1104 {
1105         comedi_cmd *cmd = &s->async->cmd;
1106         dio200_subdev_intr *subpriv = s->private;
1107         unsigned long flags;
1108         int event = 0;
1109
1110         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1111         subpriv->active = 1;
1112
1113         /* Set up end of acquisition. */
1114         switch (cmd->stop_src) {
1115         case TRIG_COUNT:
1116                 subpriv->continuous = 0;
1117                 subpriv->stopcount = cmd->stop_arg;
1118                 break;
1119         default:
1120                 /* TRIG_NONE */
1121                 subpriv->continuous = 1;
1122                 subpriv->stopcount = 0;
1123                 break;
1124         }
1125
1126         /* Set up start of acquisition. */
1127         switch (cmd->start_src) {
1128         case TRIG_INT:
1129                 s->async->inttrig = dio200_inttrig_start_intr;
1130                 break;
1131         default:
1132                 /* TRIG_NOW */
1133                 event = dio200_start_intr(dev, s);
1134                 break;
1135         }
1136         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1137
1138         if (event) {
1139                 comedi_event(dev, s);
1140         }
1141
1142         return 0;
1143 }
1144
1145 /*
1146  * This function initializes an 'INTERRUPT' subdevice.
1147  */
1148 static int
1149 dio200_subdev_intr_init(comedi_device * dev, comedi_subdevice * s,
1150         unsigned int offset, unsigned valid_isns)
1151 {
1152         dio200_subdev_intr *subpriv;
1153
1154         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1155         if (!subpriv) {
1156                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1157                         dev->minor);
1158                 return -ENOMEM;
1159         }
1160         subpriv->ofs = offset;
1161         subpriv->valid_isns = valid_isns;
1162         spin_lock_init(&subpriv->spinlock);
1163
1164         if (thislayout->has_int_sce) {
1165                 /* Disable interrupt sources. */
1166                 dio200_write8(dev, subpriv->ofs, 0);
1167         }
1168
1169         s->private = subpriv;
1170         s->type = COMEDI_SUBD_DI;
1171         s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1172         if (thislayout->has_int_sce) {
1173                 s->n_chan = DIO200_MAX_ISNS;
1174                 s->len_chanlist = DIO200_MAX_ISNS;
1175         } else {
1176                 /* No interrupt source register.  Support single channel. */
1177                 s->n_chan = 1;
1178                 s->len_chanlist = 1;
1179         }
1180         s->range_table = &range_digital;
1181         s->maxdata = 1;
1182         s->insn_bits = dio200_subdev_intr_insn_bits;
1183         s->do_cmdtest = dio200_subdev_intr_cmdtest;
1184         s->do_cmd = dio200_subdev_intr_cmd;
1185         s->cancel = dio200_subdev_intr_cancel;
1186
1187         return 0;
1188 }
1189
1190 /*
1191  * This function cleans up an 'INTERRUPT' subdevice.
1192  */
1193 static void
1194 dio200_subdev_intr_cleanup(comedi_device * dev, comedi_subdevice * s)
1195 {
1196         dio200_subdev_intr *subpriv = s->private;
1197
1198         if (subpriv) {
1199                 kfree(subpriv);
1200         }
1201 }
1202
1203 /*
1204  * Interrupt service routine.
1205  */
1206 static irqreturn_t dio200_interrupt(int irq, void *d PT_REGS_ARG)
1207 {
1208         comedi_device *dev = d;
1209         int handled;
1210
1211         if (!dev->attached) {
1212                 return IRQ_NONE;
1213         }
1214
1215         if (devpriv->intr_sd >= 0) {
1216                 handled = dio200_handle_read_intr(dev,
1217                         dev->subdevices + devpriv->intr_sd);
1218         } else {
1219                 handled = 0;
1220         }
1221
1222         return IRQ_RETVAL(handled);
1223 }
1224
1225 /*
1226  * Read an '8254' counter subdevice channel.
1227  */
1228 static inline unsigned int
1229 dio200_subdev_8254_read_chan(comedi_device * dev, comedi_subdevice * s,
1230         unsigned int chan)
1231 {
1232         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1233         unsigned int val;
1234
1235         /* latch counter */
1236         val = chan << 6;
1237         dio200_write8(dev, i8254_ofs + i8254_control_reg, val);
1238
1239         /* read lsb */
1240         val = dio200_read8(dev, i8254_ofs + chan);
1241         /* read msb */
1242         val += dio200_read8(dev, i8254_ofs + chan) << 8;
1243
1244         return val;
1245 }
1246
1247 /*
1248  * Write an '8254' counter subdevice channel.
1249  */
1250 static inline void
1251 dio200_subdev_8254_write_chan(comedi_device * dev, comedi_subdevice * s,
1252         unsigned int chan, unsigned int count)
1253 {
1254         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1255
1256         /* write lsb */
1257         dio200_write8(dev, i8254_ofs + chan, count & 0xff);
1258         /* write msb */
1259         dio200_write8(dev, i8254_ofs + chan, (count >> 8) & 0xff);
1260 }
1261
1262 /*
1263  * Set mode of an '8254' counter subdevice channel.
1264  */
1265 static inline void
1266 dio200_subdev_8254_set_mode(comedi_device * dev, comedi_subdevice * s,
1267         unsigned int chan, unsigned int mode)
1268 {
1269         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1270         unsigned int byte;
1271
1272         byte = chan << 6;
1273         byte |= 0x30;           /* load lsb then msb */
1274         byte |= (mode & 0xf);   /* set counter mode and BCD|binary */
1275         dio200_write8(dev, i8254_ofs + i8254_control_reg, byte);
1276 }
1277
1278 /*
1279  * Read status byte of an '8254' counter subdevice channel.
1280  */
1281 static inline unsigned int
1282 dio200_subdev_8254_status(comedi_device * dev, comedi_subdevice * s,
1283         unsigned int chan)
1284 {
1285         unsigned int i8254_ofs = ((dio200_subdev_8254 *)s->private)->ofs;
1286
1287         dio200_write8(dev, i8254_ofs + i8254_control_reg, (0xE0 | 2 << chan));
1288         return dio200_read8(dev, i8254_ofs + chan);
1289 }
1290
1291 /*
1292  * Handle 'insn_read' for an '8254' counter subdevice.
1293  */
1294 static int
1295 dio200_subdev_8254_read(comedi_device * dev, comedi_subdevice * s,
1296         comedi_insn * insn, lsampl_t * data)
1297 {
1298         dio200_subdev_8254 *subpriv = s->private;
1299         int chan = CR_CHAN(insn->chanspec);
1300         unsigned long flags;
1301
1302         if (insn->n == 0)
1303                 return 0;
1304
1305         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1306         data[0] = dio200_subdev_8254_read_chan(dev, s, chan);
1307         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1308
1309         return 1;
1310 }
1311
1312 /*
1313  * Handle 'insn_write' for an '8254' counter subdevice.
1314  */
1315 static int
1316 dio200_subdev_8254_write(comedi_device * dev, comedi_subdevice * s,
1317         comedi_insn * insn, lsampl_t * data)
1318 {
1319         dio200_subdev_8254 *subpriv = s->private;
1320         int chan = CR_CHAN(insn->chanspec);
1321         unsigned long flags;
1322
1323         if (insn->n == 0)
1324                 return 0;
1325
1326         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1327         dio200_subdev_8254_write_chan(dev, s, chan, data[0]);
1328         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1329
1330         return 1;
1331 }
1332
1333 /*
1334  * Set gate source for an '8254' counter subdevice channel.
1335  */
1336 static int
1337 dio200_subdev_8254_set_gate_src(comedi_device * dev, comedi_subdevice *s,
1338         unsigned int counter_number, unsigned int gate_src)
1339 {
1340         dio200_subdev_8254 *subpriv = s->private;
1341         unsigned char byte;
1342
1343         if (!thislayout->has_clk_gat_sce)
1344                 return -1;
1345         if (counter_number > 2)
1346                 return -1;
1347         if (gate_src > (thislayout->has_enhancements ? 31 : 7))
1348                 return -1;
1349
1350         subpriv->gate_src[counter_number] = gate_src;
1351         byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1352         dio200_write8(dev, subpriv->gat_sce_ofs, byte);
1353
1354         return 0;
1355 }
1356
1357 /*
1358  * Get gate source for an '8254' counter subdevice channel.
1359  */
1360 static int
1361 dio200_subdev_8254_get_gate_src(comedi_device * dev, comedi_subdevice *s,
1362         unsigned int counter_number)
1363 {
1364         dio200_subdev_8254 *subpriv = s->private;
1365
1366         if (!thislayout->has_clk_gat_sce)
1367                 return -1;
1368         if (counter_number > 2)
1369                 return -1;
1370
1371         return subpriv->gate_src[counter_number];
1372 }
1373
1374 /*
1375  * Set clock source for an '8254' counter subdevice channel.
1376  */
1377 static int
1378 dio200_subdev_8254_set_clock_src(comedi_device * dev, comedi_subdevice *s,
1379         unsigned int counter_number, unsigned int clock_src)
1380 {
1381         dio200_subdev_8254 *subpriv = s->private;
1382         unsigned char byte;
1383
1384         if (!thislayout->has_clk_gat_sce)
1385                 return -1;
1386         if (counter_number > 2)
1387                 return -1;
1388         if (clock_src > (thislayout->has_enhancements ? 31 : 7))
1389                 return -1;
1390
1391         subpriv->clock_src[counter_number] = clock_src;
1392         byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1393         dio200_write8(dev, subpriv->clk_sce_ofs, byte);
1394
1395         return 0;
1396 }
1397
1398 /*
1399  * Get clock source for an '8254' counter subdevice channel.
1400  */
1401 static int
1402 dio200_subdev_8254_get_clock_src(comedi_device * dev, comedi_subdevice *s,
1403         unsigned int counter_number, lsampl_t * period_ns)
1404 {
1405         dio200_subdev_8254 *subpriv = s->private;
1406         unsigned clock_src;
1407
1408         if (!thislayout->has_clk_gat_sce)
1409                 return -1;
1410         if (counter_number > 2)
1411                 return -1;
1412
1413         clock_src = subpriv->clock_src[counter_number];
1414         *period_ns = clock_period[clock_src];
1415         return clock_src;
1416 }
1417
1418 /*
1419  * Handle 'insn_config' for an '8254' counter subdevice.
1420  */
1421 static int
1422 dio200_subdev_8254_config(comedi_device * dev, comedi_subdevice * s,
1423         comedi_insn * insn, lsampl_t * data)
1424 {
1425         dio200_subdev_8254 *subpriv = s->private;
1426         int ret = 0;
1427         int chan = CR_CHAN(insn->chanspec);
1428         unsigned long flags;
1429
1430         comedi_spin_lock_irqsave(&subpriv->spinlock, flags);
1431         switch (data[0]) {
1432         case INSN_CONFIG_SET_COUNTER_MODE:
1433                 if (data[1] > (I8254_MODE5 | I8254_BINARY))
1434                         ret = -EINVAL;
1435                 else
1436                         dio200_subdev_8254_set_mode(dev, s, chan, data[1]);
1437                 break;
1438         case INSN_CONFIG_8254_READ_STATUS:
1439                 data[1] = dio200_subdev_8254_status(dev, s, chan);
1440                 break;
1441         case INSN_CONFIG_SET_GATE_SRC:
1442                 ret = dio200_subdev_8254_set_gate_src(dev, s, chan, data[2]);
1443                 if (ret < 0)
1444                         ret = -EINVAL;
1445                 break;
1446         case INSN_CONFIG_GET_GATE_SRC:
1447                 ret = dio200_subdev_8254_get_gate_src(dev, s, chan);
1448                 if (ret < 0) {
1449                         ret = -EINVAL;
1450                         break;
1451                 }
1452                 data[2] = ret;
1453                 break;
1454         case INSN_CONFIG_SET_CLOCK_SRC:
1455                 ret = dio200_subdev_8254_set_clock_src(dev, s, chan, data[1]);
1456                 if (ret < 0)
1457                         ret = -EINVAL;
1458                 break;
1459         case INSN_CONFIG_GET_CLOCK_SRC:
1460                 ret = dio200_subdev_8254_get_clock_src(dev, s, chan, &data[2]);
1461                 if (ret < 0) {
1462                         ret = -EINVAL;
1463                         break;
1464                 }
1465                 data[1] = ret;
1466                 break;
1467         default:
1468                 ret = -EINVAL;
1469                 break;
1470         }
1471         comedi_spin_unlock_irqrestore(&subpriv->spinlock, flags);
1472         return ret < 0 ? ret : insn->n;
1473 }
1474
1475 /*
1476  * This function initializes an '8254' counter subdevice.
1477  *
1478  * offset is the offset to the 8254 chip.
1479  */
1480 static int
1481 dio200_subdev_8254_init(comedi_device * dev, comedi_subdevice * s,
1482         unsigned int offset)
1483 {
1484         dio200_subdev_8254 *subpriv;
1485         unsigned int chan;
1486
1487         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1488         if (!subpriv) {
1489                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1490                         dev->minor);
1491                 return -ENOMEM;
1492         }
1493
1494         s->private = subpriv;
1495         s->type = COMEDI_SUBD_COUNTER;
1496         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1497         s->n_chan = 3;
1498         s->maxdata = 0xFFFF;
1499         s->insn_read = dio200_subdev_8254_read;
1500         s->insn_write = dio200_subdev_8254_write;
1501         s->insn_config = dio200_subdev_8254_config;
1502
1503         spin_lock_init(&subpriv->spinlock);
1504         subpriv->ofs = offset;
1505         if (thislayout->has_clk_gat_sce) {
1506                 /* Derive CLK_SCE and GAT_SCE register offsets from
1507                  * 8254 offset. */
1508                 subpriv->clk_sce_ofs =
1509                         DIO200_XCLK_SCE + (offset >> 3);
1510                 subpriv->gat_sce_ofs =
1511                         DIO200_XGAT_SCE + (offset >> 3);
1512                 subpriv->which = (offset >> 2) & 1;
1513         }
1514
1515         /* Initialize channels. */
1516         for (chan = 0; chan < 3; chan++) {
1517                 dio200_subdev_8254_set_mode(dev, s, chan,
1518                         (I8254_MODE0 | I8254_BINARY));
1519                 if (thislayout->has_clk_gat_sce) {
1520                         /* Gate source 0 is VCC (logic 1). */
1521                         dio200_subdev_8254_set_gate_src(dev, s, chan, 0);
1522                         /* Clock source 0 is the dedicated clock input. */
1523                         dio200_subdev_8254_set_clock_src(dev, s, chan, 0);
1524                 }
1525         }
1526
1527         return 0;
1528 }
1529
1530 /*
1531  * This function cleans up an '8254' counter subdevice.
1532  */
1533 static void
1534 dio200_subdev_8254_cleanup(comedi_device * dev, comedi_subdevice * s)
1535 {
1536         dio200_subdev_8254 *subpriv = s->private;
1537
1538         if (subpriv) {
1539                 kfree(subpriv);
1540         }
1541 }
1542
1543 /*
1544  * This function sets I/O directions for an '8255' DIO subdevice.
1545  */
1546 static void
1547 dio200_subdev_8255_set_dir(comedi_device * dev, comedi_subdevice * s)
1548 {
1549         dio200_subdev_8255 *subpriv = s->private;
1550         int config;
1551
1552         config = CR_CW;
1553         /* 1 in io_bits indicates output, 1 in config indicates input */
1554         if (!(s->io_bits & 0x0000ff))
1555                 config |= CR_A_IO;
1556         if (!(s->io_bits & 0x00ff00))
1557                 config |= CR_B_IO;
1558         if (!(s->io_bits & 0x0f0000))
1559                 config |= CR_C_LO_IO;
1560         if (!(s->io_bits & 0xf00000))
1561                 config |= CR_C_HI_IO;
1562
1563         dio200_write8(dev, subpriv->ofs + 3, config);
1564 }
1565
1566 /*
1567  * Handle 'insn_bits' for an '8255' DIO subdevice.
1568  */
1569 static int
1570 dio200_subdev_8255_bits(comedi_device * dev, comedi_subdevice * s,
1571         comedi_insn * insn, lsampl_t * data)
1572 {
1573         unsigned int i8255_ofs = ((dio200_subdev_8255 *)s->private)->ofs;
1574
1575         if (data[0]) {
1576                 s->state &= ~data[0];
1577                 s->state |= (data[0] & data[1]);
1578
1579                 if (data[0] & 0xff) {
1580                         dio200_write8(dev, i8255_ofs, s->state & 0xff);
1581                 }
1582                 if (data[0] & 0xff00) {
1583                         dio200_write8(dev, i8255_ofs + 1,
1584                                 (s->state >> 8) & 0xff);
1585                 }
1586                 if (data[0] & 0xff0000) {
1587                         dio200_write8(dev, i8255_ofs + 2,
1588                                 (s->state >> 16) & 0xff);
1589                 }
1590         }
1591
1592         data[1] = dio200_read8(dev, i8255_ofs);
1593         data[1] |= dio200_read8(dev, i8255_ofs + 1) << 8;
1594         data[1] |= dio200_read8(dev, i8255_ofs + 2) << 16;
1595
1596         return 2;
1597 }
1598
1599 /*
1600  * Handle 'insn_config' for an '8255' DIO subdevice.
1601  */
1602 static int
1603 dio200_subdev_8255_config(comedi_device * dev, comedi_subdevice * s,
1604         comedi_insn * insn, lsampl_t * data)
1605 {
1606         unsigned int mask;
1607         unsigned int bits;
1608
1609         mask = 1 << CR_CHAN(insn->chanspec);
1610         if (mask & 0x0000ff) {
1611                 bits = 0x0000ff;
1612         } else if (mask & 0x00ff00) {
1613                 bits = 0x00ff00;
1614         } else if (mask & 0x0f0000) {
1615                 bits = 0x0f0000;
1616         } else {
1617                 bits = 0xf00000;
1618         }
1619
1620         switch (data[0]) {
1621         case INSN_CONFIG_DIO_INPUT:
1622                 s->io_bits &= ~bits;
1623                 break;
1624         case INSN_CONFIG_DIO_OUTPUT:
1625                 s->io_bits |= bits;
1626                 break;
1627         case INSN_CONFIG_DIO_QUERY:
1628                 data[1] = (s->io_bits & bits) ? COMEDI_OUTPUT : COMEDI_INPUT;
1629                 return insn->n;
1630                 break;
1631         default:
1632                 return -EINVAL;
1633         }
1634
1635         dio200_subdev_8255_set_dir(dev, s);
1636
1637         return 1;
1638 }
1639
1640 /*
1641  * This function initializes an '8255' DIO subdevice.
1642  *
1643  * offset is the offset to the 8255 chip.
1644  */
1645 static int
1646 dio200_subdev_8255_init(comedi_device * dev, comedi_subdevice * s,
1647         unsigned int offset)
1648 {
1649         dio200_subdev_8255 *subpriv;
1650
1651         subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1652         if (!subpriv) {
1653                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1654                         dev->minor);
1655                 return -ENOMEM;
1656         }
1657
1658         subpriv->ofs = offset;
1659
1660         s->private = subpriv;
1661         s->type = COMEDI_SUBD_DIO;
1662         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1663         s->n_chan = 24;
1664         s->range_table = &range_digital;
1665         s->maxdata = 1;
1666         s->insn_bits = dio200_subdev_8255_bits;
1667         s->insn_config = dio200_subdev_8255_config;
1668
1669         s->state = 0;
1670         s->io_bits = 0;
1671         dio200_subdev_8255_set_dir(dev, s);
1672
1673         return 0;
1674 }
1675
1676 /*
1677  * This function cleans up an '8255' DIO subdevice.
1678  */
1679 static void
1680 dio200_subdev_8255_cleanup(comedi_device * dev, comedi_subdevice * s)
1681 {
1682         dio200_subdev_8255 *subpriv = s->private;
1683
1684         if (subpriv) {
1685                 kfree(subpriv);
1686         }
1687 }
1688
1689 #ifdef CONFIG_COMEDI_PCI
1690 /*
1691  * This function does some special set-up for the PCIe boards
1692  * PCIe215, PCIe236, PCIe296.
1693  */
1694 static int
1695 dio200_pcie_board_setup(comedi_device * dev)
1696 {
1697         struct pci_dev *pci_dev = devpriv->pci_dev;
1698         unsigned char __iomem *brbase;
1699         resource_size_t brlen;
1700
1701         /*
1702          * The board uses Altera Cyclone IV with PCI-Express hard IP.
1703          * The FPGA configuration has the PCI-Express Avalon-MM Bridge
1704          * Control registers in PCI BAR 0, offset 0, and the length of
1705          * these registers is 0x4000.
1706          *
1707          * We need to write 0x80 to the "Avalon-MM to PCI-Express Interrupt
1708          * Enable" register at offset 0x50 to allow generation of PCIe
1709          * interrupts when RXmlrq_i is asserted in the SOPC Builder system.
1710          */
1711         brlen = pci_resource_len(pci_dev, 0);
1712         if (brlen < 0x4000 ||
1713                         !(pci_resource_flags(pci_dev, 0) & IORESOURCE_MEM)) {
1714                 printk(KERN_ERR "comedi%d: error! bad PCI region!\n",
1715                         dev->minor);
1716                 return -EINVAL;
1717         }
1718         brbase = ioremap_nocache(pci_resource_start(pci_dev, 0), brlen);
1719         if (!brbase) {
1720                 printk(KERN_ERR "comedi%d: error! failed to map registers!\n",
1721                         dev->minor);
1722                 return -ENOMEM;
1723         }
1724         writel(0x80, brbase + 0x50);
1725         iounmap(brbase);
1726         /*
1727          * Enable "enhanced" features of board.
1728          */
1729         dio200_write8(dev, DIO200_ENHANCE, 1);
1730         return 0;
1731 }
1732 #endif
1733
1734 /*
1735  * Attach is called by the Comedi core to configure the driver
1736  * for a particular board.  If you specified a board_name array
1737  * in the driver structure, dev->board_ptr contains that
1738  * address.
1739  */
1740 static int dio200_attach(comedi_device * dev, comedi_devconfig * it)
1741 {
1742         comedi_subdevice *s;
1743         unsigned long iobase = 0;
1744         unsigned int irq = 0;
1745 #ifdef CONFIG_COMEDI_PCI
1746         struct pci_dev *pci_dev = NULL;
1747         int bus = 0, slot = 0;
1748 #endif
1749         const dio200_layout *layout;
1750         int share_irq = 0;
1751         int sdx;
1752         unsigned n;
1753         int ret;
1754
1755         printk(KERN_DEBUG "comedi%d: %s: attach\n", dev->minor,
1756                 DIO200_DRIVER_NAME);
1757
1758         if ((ret = alloc_private(dev, sizeof(dio200_private))) < 0) {
1759                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1760                         dev->minor);
1761                 return ret;
1762         }
1763
1764         /* Process options. */
1765         switch (thisboard->bustype) {
1766         case isa_bustype:
1767                 iobase = it->options[0];
1768                 irq = it->options[1];
1769                 share_irq = 0;
1770                 break;
1771 #ifdef CONFIG_COMEDI_PCI
1772         case pci_bustype:
1773                 bus = it->options[0];
1774                 slot = it->options[1];
1775                 share_irq = 1;
1776
1777                 if ((ret = dio200_find_pci(dev, bus, slot, &pci_dev)) < 0)
1778                         return ret;
1779                 devpriv->pci_dev = pci_dev;
1780                 break;
1781 #endif
1782         default:
1783                 printk(KERN_ERR
1784                         "comedi%d: %s: BUG! cannot determine board type!\n",
1785                         dev->minor, DIO200_DRIVER_NAME);
1786                 return -EINVAL;
1787                 break;
1788         }
1789
1790         devpriv->intr_sd = -1;
1791         devpriv->io.regtype = no_regtype;
1792         devpriv->io.regshift = thisboard->mainshift;
1793
1794         /* Enable device and reserve I/O spaces. */
1795 #ifdef CONFIG_COMEDI_PCI
1796         if (pci_dev) {
1797                 resource_size_t base, len;
1798                 unsigned int bar;
1799
1800                 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1801                 if (ret < 0) {
1802                         printk(KERN_ERR
1803                                 "comedi%d: error! cannot enable PCI device and request regions!\n",
1804                                 dev->minor);
1805                         return ret;
1806                 }
1807                 bar = thisboard->mainbar;
1808                 base = pci_resource_start(pci_dev, bar);
1809                 len = pci_resource_len(pci_dev, bar);
1810                 if (len < thisboard->mainsize) {
1811                         printk(KERN_ERR
1812                                 "comedi%d: error! PCI region size too small!\n",
1813                                 dev->minor);
1814                         return -EINVAL;
1815                 }
1816                 if ((pci_resource_flags(pci_dev, bar) & IORESOURCE_MEM) != 0) {
1817                         devpriv->io.u.membase = ioremap_nocache(base, len);
1818                         if (!devpriv->io.u.membase) {
1819                                 printk(KERN_ERR
1820                                         "comedi%d: error! cannot remap registers!\n",
1821                                         dev->minor);
1822                                 return -ENOMEM;
1823                         }
1824                         devpriv->io.regtype = mmio_regtype;
1825                 } else {
1826                         devpriv->io.u.iobase = (unsigned long)base;
1827                         devpriv->io.regtype = io_regtype;
1828                 }
1829                 irq = pci_dev->irq;
1830         } else
1831 #endif
1832         {
1833                 ret = dio200_request_region(dev->minor, iobase,
1834                         thisboard->mainsize);
1835                 if (ret < 0) {
1836                         return ret;
1837                 }
1838                 devpriv->io.u.iobase = iobase;
1839                 devpriv->io.regtype = io_regtype;
1840         }
1841
1842         switch (thisboard->model) {
1843 #ifdef CONFIG_COMEDI_PCI
1844         case pcie215_model:
1845         case pcie236_model:
1846         case pcie296_model:
1847                 ret = dio200_pcie_board_setup(dev);
1848                 if (ret < 0) {
1849                         return ret;
1850                 }
1851                 break;
1852 #endif
1853         default:
1854                 break;
1855         }
1856
1857         layout = thislayout;
1858         if ((ret = alloc_subdevices(dev, layout->n_subdevs)) < 0) {
1859                 printk(KERN_ERR "comedi%d: error! out of memory!\n",
1860                         dev->minor);
1861                 return ret;
1862         }
1863
1864         for (n = 0; n < dev->n_subdevices; n++) {
1865                 s = &dev->subdevices[n];
1866                 switch (layout->sdtype[n]) {
1867                 case sd_8254:
1868                         /* counter subdevice (8254) */
1869                         ret = dio200_subdev_8254_init(dev, s,
1870                                 layout->sdinfo[n]);
1871                         if (ret < 0) {
1872                                 return ret;
1873                         }
1874                         break;
1875                 case sd_8255:
1876                         /* digital i/o subdevice (8255) */
1877                         ret = dio200_subdev_8255_init(dev, s,
1878                                 layout->sdinfo[n]);
1879                         if (ret < 0) {
1880                                 return ret;
1881                         }
1882                         break;
1883                 case sd_intr:
1884                         /* 'INTERRUPT' subdevice */
1885                         if (irq) {
1886                                 ret = dio200_subdev_intr_init(dev, s,
1887                                         DIO200_INT_SCE, layout->sdinfo[n]);
1888                                 if (ret < 0) {
1889                                         return ret;
1890                                 }
1891                                 devpriv->intr_sd = n;
1892                         } else {
1893                                 s->type = COMEDI_SUBD_UNUSED;
1894                         }
1895                         break;
1896                 case sd_timer:
1897                         /* TODO.  Fall-thru to default for now. */
1898                 default:
1899                         s->type = COMEDI_SUBD_UNUSED;
1900                         break;
1901                 }
1902         }
1903
1904         sdx = devpriv->intr_sd;
1905         if (sdx >= 0 && sdx < dev->n_subdevices) {
1906                 dev->read_subdev = &dev->subdevices[sdx];
1907         }
1908
1909         dev->board_name = thisboard->name;
1910
1911         if (irq) {
1912                 unsigned long flags = share_irq ? IRQF_SHARED : 0;
1913
1914                 if (comedi_request_irq(irq, dio200_interrupt, flags,
1915                                 DIO200_DRIVER_NAME, dev) >= 0) {
1916                         dev->irq = irq;
1917                 } else {
1918                         printk(KERN_WARNING
1919                                 "comedi%d: warning! irq %u unavailable!\n",
1920                                 dev->minor, irq);
1921                 }
1922         }
1923
1924         printk(KERN_INFO "comedi%d: %s ", dev->minor, dev->board_name);
1925         if (thisboard->bustype == isa_bustype) {
1926                 printk("(base %#lx) ", iobase);
1927         } else {
1928 #ifdef CONFIG_COMEDI_PCI
1929                 printk("(pci %s) ", pci_name(pci_dev));
1930 #endif
1931         }
1932         if (irq) {
1933                 printk("(irq %u%s) ", irq, (dev->irq ? "" : " UNAVAILABLE"));
1934         } else {
1935                 printk("(no irq) ");
1936         }
1937
1938         printk("attached\n");
1939
1940         return 1;
1941 }
1942
1943 /*
1944  * _detach is called to deconfigure a device.  It should deallocate
1945  * resources.
1946  * This function is also called when _attach() fails, so it should be
1947  * careful not to release resources that were not necessarily
1948  * allocated by _attach().  dev->private and dev->subdevices are
1949  * deallocated automatically by the core.
1950  */
1951 static int dio200_detach(comedi_device * dev)
1952 {
1953         const dio200_layout *layout;
1954         unsigned n;
1955
1956         printk(KERN_DEBUG "comedi%d: %s: detach\n", dev->minor,
1957                 DIO200_DRIVER_NAME);
1958
1959         if (dev->irq) {
1960                 comedi_free_irq(dev->irq, dev);
1961         }
1962         if (dev->subdevices) {
1963                 layout = thislayout;
1964                 for (n = 0; n < dev->n_subdevices; n++) {
1965                         comedi_subdevice *s = &dev->subdevices[n];
1966                         switch (layout->sdtype[n]) {
1967                         case sd_8254:
1968                                 dio200_subdev_8254_cleanup(dev, s);
1969                                 break;
1970                         case sd_8255:
1971                                 dio200_subdev_8255_cleanup(dev, s);
1972                                 break;
1973                         case sd_intr:
1974                                 dio200_subdev_intr_cleanup(dev, s);
1975                                 break;
1976                         default:
1977                                 break;
1978                         }
1979                 }
1980         }
1981         if (devpriv) {
1982                 if (devpriv->io.regtype == mmio_regtype) {
1983                         iounmap(devpriv->io.u.membase);
1984                 }
1985 #ifdef CONFIG_COMEDI_PCI
1986                 if (devpriv->pci_dev) {
1987                         if (devpriv->io.regtype != no_regtype) {
1988                                 comedi_pci_disable(devpriv->pci_dev);
1989                         }
1990                         pci_dev_put(devpriv->pci_dev);
1991                 } else
1992 #endif
1993                 {
1994                         if (devpriv->io.regtype == io_regtype) {
1995                                 release_region(devpriv->io.u.iobase,
1996                                         thisboard->mainsize);
1997                         }
1998                 }
1999         }
2000         if (dev->board_name) {
2001                 printk(KERN_INFO "comedi%d: %s removed\n",
2002                         dev->minor, dev->board_name);
2003         }
2004
2005         return 0;
2006 }