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