staging: comedi: propogate error code from comedi_alloc_subdevices
[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
669c930c
BA
51 PC218E PC212E PC215E/PCI215
52 ------------- ------------- -------------
e948cb52
IA
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
669c930c
BA
62 PC214E PC272E/PCI272
63 ------------- -------------
e948cb52
IA
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
669c930c
BA
99 connector. (N.B. for other values, the counter channel's CLKn
100 pin on the SK1 connector is an output!)
e948cb52
IA
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
669c930c
BA
108 the SK1 connector. This pin is shared by all three counter
109 channels on the chip.
e948cb52
IA
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
669c930c
BA
123 connector. (N.B. for other values, the counter channel's GATn
124 pin on the SK1 connector is an output!)
e948cb52 125 3. /OUT n-2, the inverted output of counter channel n-2 (see note
669c930c 126 2 below).
e948cb52
IA
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
669c930c
BA
156 PC218E PC212E PC215E/PCI215
157 ------------- ------------- -------------
e948cb52
IA
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
669c930c
BA
166 PC214E PC272E/PCI272
167 ------------- -------------
e948cb52
IA
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 208#include <linux/interrupt.h>
5a0e3ad6 209#include <linux/slab.h>
70265d24 210
e948cb52
IA
211#include "../comedidev.h"
212
e948cb52
IA
213#include "8255.h"
214#include "8253.h"
215
216#define DIO200_DRIVER_NAME "amplc_dio200"
217
218/* PCI IDs */
6608224c 219#define PCI_VENDOR_ID_AMPLICON 0x14dc
e948cb52
IA
220#define PCI_DEVICE_ID_AMPLICON_PCI272 0x000a
221#define PCI_DEVICE_ID_AMPLICON_PCI215 0x000b
222#define PCI_DEVICE_ID_INVALID 0xffff
223
224/* 200 series registers */
225#define DIO200_IO_SIZE 0x20
226#define DIO200_XCLK_SCE 0x18 /* Group X clock selection register */
227#define DIO200_YCLK_SCE 0x19 /* Group Y clock selection register */
228#define DIO200_ZCLK_SCE 0x1a /* Group Z clock selection register */
229#define DIO200_XGAT_SCE 0x1b /* Group X gate selection register */
230#define DIO200_YGAT_SCE 0x1c /* Group Y gate selection register */
231#define DIO200_ZGAT_SCE 0x1d /* Group Z gate selection register */
232#define DIO200_INT_SCE 0x1e /* Interrupt enable/status register */
233
234/*
235 * Macros for constructing value for DIO_200_?CLK_SCE and
236 * DIO_200_?GAT_SCE registers:
237 *
238 * 'which' is: 0 for CTR-X1, CTR-Y1, CTR-Z1; 1 for CTR-X2, CTR-Y2 or CTR-Z2.
239 * 'chan' is the channel: 0, 1 or 2.
240 * 'source' is the signal source: 0 to 7.
241 */
242#define CLK_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
243#define GAT_SCE(which, chan, source) (((which) << 5) | ((chan) << 3) | (source))
244
245/*
246 * Periods of the internal clock sources in nanoseconds.
247 */
248static const unsigned clock_period[8] = {
249 0, /* dedicated clock input/output pin */
250 100, /* 10 MHz */
251 1000, /* 1 MHz */
252 10000, /* 100 kHz */
253 100000, /* 10 kHz */
254 1000000, /* 1 kHz */
255 0, /* OUT N-1 */
256 0 /* group clock input pin */
257};
258
259/*
260 * Board descriptions.
261 */
262
263enum dio200_bustype { isa_bustype, pci_bustype };
264
265enum dio200_model {
266 pc212e_model,
267 pc214e_model,
268 pc215e_model, pci215_model,
269 pc218e_model,
270 pc272e_model, pci272_model,
271 anypci_model
272};
273
274enum dio200_layout {
a6e11e3b 275#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
e948cb52
IA
276 pc212_layout,
277 pc214_layout,
8c287d20 278#endif
e948cb52 279 pc215_layout,
a6e11e3b 280#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
e948cb52 281 pc218_layout,
8c287d20 282#endif
e948cb52
IA
283 pc272_layout
284};
285
3d7a42ef 286struct dio200_board {
e948cb52
IA
287 const char *name;
288 unsigned short devid;
289 enum dio200_bustype bustype;
290 enum dio200_model model;
291 enum dio200_layout layout;
3d7a42ef 292};
e948cb52 293
3d7a42ef 294static const struct dio200_board dio200_boards[] = {
a6e11e3b 295#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
e948cb52 296 {
0a85b6f0
MT
297 .name = "pc212e",
298 .bustype = isa_bustype,
299 .model = pc212e_model,
300 .layout = pc212_layout,
301 },
e948cb52 302 {
0a85b6f0
MT
303 .name = "pc214e",
304 .bustype = isa_bustype,
305 .model = pc214e_model,
306 .layout = pc214_layout,
307 },
e948cb52 308 {
0a85b6f0
MT
309 .name = "pc215e",
310 .bustype = isa_bustype,
311 .model = pc215e_model,
312 .layout = pc215_layout,
313 },
e948cb52 314 {
0a85b6f0
MT
315 .name = "pc218e",
316 .bustype = isa_bustype,
317 .model = pc218e_model,
318 .layout = pc218_layout,
319 },
e948cb52 320 {
0a85b6f0
MT
321 .name = "pc272e",
322 .bustype = isa_bustype,
323 .model = pc272e_model,
324 .layout = pc272_layout,
325 },
8c287d20 326#endif
a6e11e3b 327#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
8c287d20
IA
328 {
329 .name = "pci215",
330 .devid = PCI_DEVICE_ID_AMPLICON_PCI215,
331 .bustype = pci_bustype,
332 .model = pci215_model,
333 .layout = pc215_layout,
334 },
e948cb52 335 {
0a85b6f0
MT
336 .name = "pci272",
337 .devid = PCI_DEVICE_ID_AMPLICON_PCI272,
338 .bustype = pci_bustype,
339 .model = pci272_model,
340 .layout = pc272_layout,
341 },
e948cb52 342 {
0a85b6f0
MT
343 .name = DIO200_DRIVER_NAME,
344 .devid = PCI_DEVICE_ID_INVALID,
345 .bustype = pci_bustype,
346 .model = anypci_model, /* wildcard */
347 },
e948cb52
IA
348#endif
349};
350
351/*
352 * Layout descriptions - some ISA and PCI board descriptions share the same
353 * layout.
354 */
355
356enum dio200_sdtype { sd_none, sd_intr, sd_8255, sd_8254 };
357
358#define DIO200_MAX_SUBDEVS 7
359#define DIO200_MAX_ISNS 6
360
af105ad3 361struct dio200_layout_struct {
e948cb52
IA
362 unsigned short n_subdevs; /* number of subdevices */
363 unsigned char sdtype[DIO200_MAX_SUBDEVS]; /* enum dio200_sdtype */
364 unsigned char sdinfo[DIO200_MAX_SUBDEVS]; /* depends on sdtype */
365 char has_int_sce; /* has interrupt enable/status register */
366 char has_clk_gat_sce; /* has clock/gate selection registers */
af105ad3 367};
e948cb52 368
af105ad3 369static const struct dio200_layout_struct dio200_layouts[] = {
a6e11e3b 370#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
e948cb52 371 [pc212_layout] = {
0a85b6f0
MT
372 .n_subdevs = 6,
373 .sdtype = {sd_8255, sd_8254, sd_8254, sd_8254,
374 sd_8254,
375 sd_intr},
376 .sdinfo = {0x00, 0x08, 0x0C, 0x10, 0x14,
377 0x3F},
378 .has_int_sce = 1,
379 .has_clk_gat_sce = 1,
380 },
e948cb52 381 [pc214_layout] = {
0a85b6f0
MT
382 .n_subdevs = 4,
383 .sdtype = {sd_8255, sd_8255, sd_8254,
384 sd_intr},
385 .sdinfo = {0x00, 0x08, 0x10, 0x01},
386 .has_int_sce = 0,
387 .has_clk_gat_sce = 0,
388 },
8c287d20 389#endif
e948cb52 390 [pc215_layout] = {
0a85b6f0
MT
391 .n_subdevs = 5,
392 .sdtype = {sd_8255, sd_8255, sd_8254,
393 sd_8254,
394 sd_intr},
395 .sdinfo = {0x00, 0x08, 0x10, 0x14, 0x3F},
396 .has_int_sce = 1,
397 .has_clk_gat_sce = 1,
398 },
a6e11e3b 399#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA)
e948cb52 400 [pc218_layout] = {
0a85b6f0
MT
401 .n_subdevs = 7,
402 .sdtype = {sd_8254, sd_8254, sd_8255, sd_8254,
403 sd_8254,
404 sd_intr},
405 .sdinfo = {0x00, 0x04, 0x08, 0x0C, 0x10,
406 0x14,
407 0x3F},
408 .has_int_sce = 1,
409 .has_clk_gat_sce = 1,
410 },
8c287d20 411#endif
e948cb52 412 [pc272_layout] = {
0a85b6f0
MT
413 .n_subdevs = 4,
414 .sdtype = {sd_8255, sd_8255, sd_8255,
415 sd_intr},
416 .sdinfo = {0x00, 0x08, 0x10, 0x3F},
417 .has_int_sce = 1,
418 .has_clk_gat_sce = 0,
419 },
e948cb52
IA
420};
421
e948cb52
IA
422/* this structure is for data unique to this hardware driver. If
423 several hardware drivers keep similar information in this structure,
669c930c
BA
424 feel free to suggest moving the variable to the struct comedi_device struct.
425 */
692560db 426struct dio200_private {
e948cb52 427 struct pci_dev *pci_dev; /* PCI device */
e948cb52 428 int intr_sd;
692560db 429};
e948cb52 430
93ba42e9 431struct dio200_subdev_8254 {
e948cb52
IA
432 unsigned long iobase; /* Counter base address */
433 unsigned long clk_sce_iobase; /* CLK_SCE base address */
434 unsigned long gat_sce_iobase; /* GAT_SCE base address */
435 int which; /* Bit 5 of CLK_SCE or GAT_SCE */
436 int has_clk_gat_sce;
437 unsigned clock_src[3]; /* Current clock sources */
438 unsigned gate_src[3]; /* Current gate sources */
ee4063fa 439 spinlock_t spinlock;
93ba42e9 440};
e948cb52 441
d9752ee0 442struct dio200_subdev_intr {
e948cb52
IA
443 unsigned long iobase;
444 spinlock_t spinlock;
445 int active;
446 int has_int_sce;
447 unsigned int valid_isns;
448 unsigned int enabled_isns;
449 unsigned int stopcount;
450 int continuous;
d9752ee0 451};
e948cb52 452
c894ec8d
IA
453/*
454 * This function looks for a board matching the supplied PCI device.
455 */
456static const struct dio200_board *
457dio200_find_pci_board(struct pci_dev *pci_dev)
458{
459 unsigned int i;
460
461 for (i = 0; i < ARRAY_SIZE(dio200_boards); i++)
462 if (dio200_boards[i].bustype == pci_bustype &&
463 pci_dev->device == dio200_boards[i].devid)
464 return &dio200_boards[i];
465 return NULL;
466}
467
e948cb52
IA
468/*
469 * This function looks for a PCI device matching the requested board name,
470 * bus and slot.
471 */
181ad5ed
IA
472static struct pci_dev *
473dio200_find_pci(struct comedi_device *dev, int bus, int slot)
e948cb52 474{
adb4601a 475 const struct dio200_board *thisboard = comedi_board(dev);
e948cb52
IA
476 struct pci_dev *pci_dev = NULL;
477
e948cb52
IA
478 /* Look for matching PCI device. */
479 for (pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON, PCI_ANY_ID, NULL);
0a85b6f0
MT
480 pci_dev != NULL;
481 pci_dev = pci_get_device(PCI_VENDOR_ID_AMPLICON,
482 PCI_ANY_ID, pci_dev)) {
e948cb52
IA
483 /* If bus/slot specified, check them. */
484 if (bus || slot) {
485 if (bus != pci_dev->bus->number
0a85b6f0 486 || slot != PCI_SLOT(pci_dev->devfn))
e948cb52
IA
487 continue;
488 }
489 if (thisboard->model == anypci_model) {
c894ec8d
IA
490 /* Wildcard board matches any supported PCI board. */
491 const struct dio200_board *foundboard;
492
493 foundboard = dio200_find_pci_board(pci_dev);
494 if (foundboard == NULL)
e948cb52 495 continue;
c894ec8d
IA
496 /* Replace wildcard board_ptr. */
497 dev->board_ptr = foundboard;
498 thisboard = comedi_board(dev);
e948cb52
IA
499 } else {
500 /* Match specific model name. */
501 if (pci_dev->device != thisboard->devid)
502 continue;
503 }
504
505 /* Found a match. */
181ad5ed 506 return pci_dev;
e948cb52
IA
507 }
508 /* No match found. */
509 if (bus || slot) {
485455d0
IA
510 dev_err(dev->class_dev,
511 "error! no %s found at pci %02x:%02x!\n",
512 thisboard->name, bus, slot);
e948cb52 513 } else {
485455d0
IA
514 dev_err(dev->class_dev, "error! no %s found!\n",
515 thisboard->name);
e948cb52 516 }
181ad5ed 517 return NULL;
e948cb52 518}
e948cb52
IA
519
520/*
521 * This function checks and requests an I/O region, reporting an error
522 * if there is a conflict.
523 */
524static int
485455d0
IA
525dio200_request_region(struct comedi_device *dev,
526 unsigned long from, unsigned long extent)
e948cb52
IA
527{
528 if (!from || !request_region(from, extent, DIO200_DRIVER_NAME)) {
485455d0
IA
529 dev_err(dev->class_dev, "I/O port conflict (%#lx,%lu)!\n",
530 from, extent);
e948cb52
IA
531 return -EIO;
532 }
533 return 0;
534}
535
536/*
537 * 'insn_bits' function for an 'INTERRUPT' subdevice.
538 */
539static int
0a85b6f0
MT
540dio200_subdev_intr_insn_bits(struct comedi_device *dev,
541 struct comedi_subdevice *s,
542 struct comedi_insn *insn, unsigned int *data)
e948cb52 543{
d9752ee0 544 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
545
546 if (subpriv->has_int_sce) {
547 /* Just read the interrupt status register. */
548 data[1] = inb(subpriv->iobase) & subpriv->valid_isns;
549 } else {
550 /* No interrupt status register. */
551 data[0] = 0;
552 }
553
554 return 2;
555}
556
557/*
558 * Called to stop acquisition for an 'INTERRUPT' subdevice.
559 */
0a85b6f0
MT
560static void dio200_stop_intr(struct comedi_device *dev,
561 struct comedi_subdevice *s)
e948cb52 562{
d9752ee0 563 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
564
565 subpriv->active = 0;
566 subpriv->enabled_isns = 0;
669c930c 567 if (subpriv->has_int_sce)
e948cb52 568 outb(0, subpriv->iobase);
e948cb52
IA
569}
570
571/*
572 * Called to start acquisition for an 'INTERRUPT' subdevice.
573 */
0a85b6f0
MT
574static int dio200_start_intr(struct comedi_device *dev,
575 struct comedi_subdevice *s)
e948cb52
IA
576{
577 unsigned int n;
578 unsigned isn_bits;
d9752ee0 579 struct dio200_subdev_intr *subpriv = s->private;
ea6d0d4c 580 struct comedi_cmd *cmd = &s->async->cmd;
e948cb52
IA
581 int retval = 0;
582
583 if (!subpriv->continuous && subpriv->stopcount == 0) {
584 /* An empty acquisition! */
585 s->async->events |= COMEDI_CB_EOA;
586 subpriv->active = 0;
587 retval = 1;
588 } else {
589 /* Determine interrupt sources to enable. */
590 isn_bits = 0;
591 if (cmd->chanlist) {
669c930c 592 for (n = 0; n < cmd->chanlist_len; n++)
e948cb52 593 isn_bits |= (1U << CR_CHAN(cmd->chanlist[n]));
e948cb52
IA
594 }
595 isn_bits &= subpriv->valid_isns;
596 /* Enable interrupt sources. */
597 subpriv->enabled_isns = isn_bits;
669c930c 598 if (subpriv->has_int_sce)
e948cb52 599 outb(isn_bits, subpriv->iobase);
e948cb52
IA
600 }
601
602 return retval;
603}
604
605/*
606 * Internal trigger function to start acquisition for an 'INTERRUPT' subdevice.
607 */
608static int
da91b269 609dio200_inttrig_start_intr(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 610 unsigned int trignum)
e948cb52 611{
d9752ee0 612 struct dio200_subdev_intr *subpriv;
e948cb52
IA
613 unsigned long flags;
614 int event = 0;
615
616 if (trignum != 0)
617 return -EINVAL;
618
619 subpriv = s->private;
620
5f74ea14 621 spin_lock_irqsave(&subpriv->spinlock, flags);
a7f22a84 622 s->async->inttrig = NULL;
669c930c 623 if (subpriv->active)
e948cb52 624 event = dio200_start_intr(dev, s);
669c930c 625
5f74ea14 626 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 627
669c930c 628 if (event)
e948cb52 629 comedi_event(dev, s);
e948cb52
IA
630
631 return 1;
632}
633
634/*
635 * This is called from the interrupt service routine to handle a read
636 * scan on an 'INTERRUPT' subdevice.
637 */
0a85b6f0
MT
638static int dio200_handle_read_intr(struct comedi_device *dev,
639 struct comedi_subdevice *s)
e948cb52 640{
d9752ee0 641 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
642 unsigned triggered;
643 unsigned intstat;
644 unsigned cur_enabled;
645 unsigned int oldevents;
646 unsigned long flags;
647
648 triggered = 0;
649
5f74ea14 650 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
651 oldevents = s->async->events;
652 if (subpriv->has_int_sce) {
653 /*
654 * Collect interrupt sources that have triggered and disable
655 * them temporarily. Loop around until no extra interrupt
656 * sources have triggered, at which point, the valid part of
657 * the interrupt status register will read zero, clearing the
658 * cause of the interrupt.
659 *
660 * Mask off interrupt sources already seen to avoid infinite
661 * loop in case of misconfiguration.
662 */
663 cur_enabled = subpriv->enabled_isns;
664 while ((intstat = (inb(subpriv->iobase) & subpriv->valid_isns
0a85b6f0 665 & ~triggered)) != 0) {
e948cb52
IA
666 triggered |= intstat;
667 cur_enabled &= ~triggered;
668 outb(cur_enabled, subpriv->iobase);
669 }
670 } else {
671 /*
672 * No interrupt status register. Assume the single interrupt
673 * source has triggered.
674 */
675 triggered = subpriv->enabled_isns;
676 }
677
678 if (triggered) {
679 /*
680 * Some interrupt sources have triggered and have been
681 * temporarily disabled to clear the cause of the interrupt.
682 *
683 * Reenable them NOW to minimize the time they are disabled.
684 */
685 cur_enabled = subpriv->enabled_isns;
669c930c 686 if (subpriv->has_int_sce)
e948cb52 687 outb(cur_enabled, subpriv->iobase);
e948cb52
IA
688
689 if (subpriv->active) {
690 /*
691 * The command is still active.
692 *
693 * Ignore interrupt sources that the command isn't
694 * interested in (just in case there's a race
695 * condition).
696 */
697 if (triggered & subpriv->enabled_isns) {
698 /* Collect scan data. */
790c5541 699 short val;
e948cb52
IA
700 unsigned int n, ch, len;
701
702 val = 0;
703 len = s->async->cmd.chanlist_len;
704 for (n = 0; n < len; n++) {
705 ch = CR_CHAN(s->async->cmd.chanlist[n]);
669c930c 706 if (triggered & (1U << ch))
e948cb52 707 val |= (1U << n);
e948cb52
IA
708 }
709 /* Write the scan to the buffer. */
710 if (comedi_buf_put(s->async, val)) {
711 s->async->events |= (COMEDI_CB_BLOCK |
0a85b6f0 712 COMEDI_CB_EOS);
e948cb52
IA
713 } else {
714 /* Error! Stop acquisition. */
715 dio200_stop_intr(dev, s);
716 s->async->events |= COMEDI_CB_ERROR
0a85b6f0 717 | COMEDI_CB_OVERFLOW;
e948cb52
IA
718 comedi_error(dev, "buffer overflow");
719 }
720
721 /* Check for end of acquisition. */
722 if (!subpriv->continuous) {
723 /* stop_src == TRIG_COUNT */
724 if (subpriv->stopcount > 0) {
725 subpriv->stopcount--;
726 if (subpriv->stopcount == 0) {
727 s->async->events |=
0a85b6f0 728 COMEDI_CB_EOA;
e948cb52 729 dio200_stop_intr(dev,
0a85b6f0 730 s);
e948cb52
IA
731 }
732 }
733 }
734 }
735 }
736 }
5f74ea14 737 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 738
669c930c 739 if (oldevents != s->async->events)
e948cb52 740 comedi_event(dev, s);
e948cb52
IA
741
742 return (triggered != 0);
743}
744
745/*
746 * 'cancel' function for an 'INTERRUPT' subdevice.
747 */
0a85b6f0
MT
748static int dio200_subdev_intr_cancel(struct comedi_device *dev,
749 struct comedi_subdevice *s)
e948cb52 750{
d9752ee0 751 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
752 unsigned long flags;
753
5f74ea14 754 spin_lock_irqsave(&subpriv->spinlock, flags);
669c930c 755 if (subpriv->active)
e948cb52 756 dio200_stop_intr(dev, s);
669c930c 757
5f74ea14 758 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
759
760 return 0;
761}
762
763/*
764 * 'do_cmdtest' function for an 'INTERRUPT' subdevice.
765 */
766static int
0a85b6f0
MT
767dio200_subdev_intr_cmdtest(struct comedi_device *dev,
768 struct comedi_subdevice *s, struct comedi_cmd *cmd)
e948cb52
IA
769{
770 int err = 0;
771 unsigned int tmp;
772
773 /* step 1: make sure trigger sources are trivially valid */
774
775 tmp = cmd->start_src;
776 cmd->start_src &= (TRIG_NOW | TRIG_INT);
777 if (!cmd->start_src || tmp != cmd->start_src)
778 err++;
779
780 tmp = cmd->scan_begin_src;
781 cmd->scan_begin_src &= TRIG_EXT;
782 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
783 err++;
784
785 tmp = cmd->convert_src;
786 cmd->convert_src &= TRIG_NOW;
787 if (!cmd->convert_src || tmp != cmd->convert_src)
788 err++;
789
790 tmp = cmd->scan_end_src;
791 cmd->scan_end_src &= TRIG_COUNT;
792 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
793 err++;
794
795 tmp = cmd->stop_src;
796 cmd->stop_src &= (TRIG_COUNT | TRIG_NONE);
797 if (!cmd->stop_src || tmp != cmd->stop_src)
798 err++;
799
800 if (err)
801 return 1;
802
669c930c
BA
803 /* step 2: make sure trigger sources are unique and mutually
804 compatible */
e948cb52
IA
805
806 /* these tests are true if more than one _src bit is set */
807 if ((cmd->start_src & (cmd->start_src - 1)) != 0)
808 err++;
809 if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
810 err++;
811 if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
812 err++;
813 if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
814 err++;
815 if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
816 err++;
817
818 if (err)
819 return 2;
820
821 /* step 3: make sure arguments are trivially compatible */
822
823 /* cmd->start_src == TRIG_NOW || cmd->start_src == TRIG_INT */
824 if (cmd->start_arg != 0) {
825 cmd->start_arg = 0;
826 err++;
827 }
828
829 /* cmd->scan_begin_src == TRIG_EXT */
830 if (cmd->scan_begin_arg != 0) {
831 cmd->scan_begin_arg = 0;
832 err++;
833 }
834
835 /* cmd->convert_src == TRIG_NOW */
836 if (cmd->convert_arg != 0) {
837 cmd->convert_arg = 0;
838 err++;
839 }
840
841 /* cmd->scan_end_src == TRIG_COUNT */
842 if (cmd->scan_end_arg != cmd->chanlist_len) {
843 cmd->scan_end_arg = cmd->chanlist_len;
844 err++;
845 }
846
847 switch (cmd->stop_src) {
848 case TRIG_COUNT:
849 /* any count allowed */
850 break;
851 case TRIG_NONE:
852 if (cmd->stop_arg != 0) {
853 cmd->stop_arg = 0;
854 err++;
855 }
856 break;
857 default:
858 break;
859 }
860
861 if (err)
862 return 3;
863
864 /* step 4: fix up any arguments */
865
866 /* if (err) return 4; */
867
868 return 0;
869}
870
871/*
872 * 'do_cmd' function for an 'INTERRUPT' subdevice.
873 */
0a85b6f0
MT
874static int dio200_subdev_intr_cmd(struct comedi_device *dev,
875 struct comedi_subdevice *s)
e948cb52 876{
ea6d0d4c 877 struct comedi_cmd *cmd = &s->async->cmd;
d9752ee0 878 struct dio200_subdev_intr *subpriv = s->private;
e948cb52
IA
879 unsigned long flags;
880 int event = 0;
881
5f74ea14 882 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
883 subpriv->active = 1;
884
885 /* Set up end of acquisition. */
886 switch (cmd->stop_src) {
887 case TRIG_COUNT:
888 subpriv->continuous = 0;
889 subpriv->stopcount = cmd->stop_arg;
890 break;
891 default:
892 /* TRIG_NONE */
893 subpriv->continuous = 1;
894 subpriv->stopcount = 0;
895 break;
896 }
897
898 /* Set up start of acquisition. */
899 switch (cmd->start_src) {
900 case TRIG_INT:
901 s->async->inttrig = dio200_inttrig_start_intr;
902 break;
903 default:
904 /* TRIG_NOW */
905 event = dio200_start_intr(dev, s);
906 break;
907 }
5f74ea14 908 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52 909
669c930c 910 if (event)
e948cb52 911 comedi_event(dev, s);
e948cb52
IA
912
913 return 0;
914}
915
916/*
917 * This function initializes an 'INTERRUPT' subdevice.
918 */
919static int
da91b269 920dio200_subdev_intr_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
921 unsigned long iobase, unsigned valid_isns,
922 int has_int_sce)
e948cb52 923{
d9752ee0 924 struct dio200_subdev_intr *subpriv;
e948cb52
IA
925
926 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
927 if (!subpriv) {
485455d0 928 dev_err(dev->class_dev, "error! out of memory!\n");
e948cb52
IA
929 return -ENOMEM;
930 }
931 subpriv->iobase = iobase;
932 subpriv->has_int_sce = has_int_sce;
933 subpriv->valid_isns = valid_isns;
934 spin_lock_init(&subpriv->spinlock);
935
669c930c 936 if (has_int_sce)
e948cb52 937 outb(0, subpriv->iobase); /* Disable interrupt sources. */
e948cb52
IA
938
939 s->private = subpriv;
940 s->type = COMEDI_SUBD_DI;
941 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
942 if (has_int_sce) {
943 s->n_chan = DIO200_MAX_ISNS;
944 s->len_chanlist = DIO200_MAX_ISNS;
945 } else {
946 /* No interrupt source register. Support single channel. */
947 s->n_chan = 1;
948 s->len_chanlist = 1;
949 }
950 s->range_table = &range_digital;
951 s->maxdata = 1;
952 s->insn_bits = dio200_subdev_intr_insn_bits;
953 s->do_cmdtest = dio200_subdev_intr_cmdtest;
954 s->do_cmd = dio200_subdev_intr_cmd;
955 s->cancel = dio200_subdev_intr_cancel;
956
957 return 0;
958}
959
960/*
961 * This function cleans up an 'INTERRUPT' subdevice.
962 */
963static void
0a85b6f0
MT
964dio200_subdev_intr_cleanup(struct comedi_device *dev,
965 struct comedi_subdevice *s)
e948cb52 966{
d9752ee0 967 struct dio200_subdev_intr *subpriv = s->private;
669c930c 968 kfree(subpriv);
e948cb52
IA
969}
970
971/*
972 * Interrupt service routine.
973 */
70265d24 974static irqreturn_t dio200_interrupt(int irq, void *d)
e948cb52 975{
71b5f4f1 976 struct comedi_device *dev = d;
adb4601a 977 struct dio200_private *devpriv = dev->private;
e948cb52
IA
978 int handled;
979
669c930c 980 if (!dev->attached)
e948cb52 981 return IRQ_NONE;
e948cb52
IA
982
983 if (devpriv->intr_sd >= 0) {
984 handled = dio200_handle_read_intr(dev,
0a85b6f0
MT
985 dev->subdevices +
986 devpriv->intr_sd);
e948cb52
IA
987 } else {
988 handled = 0;
989 }
990
991 return IRQ_RETVAL(handled);
992}
993
994/*
995 * Handle 'insn_read' for an '8254' counter subdevice.
996 */
997static int
da91b269 998dio200_subdev_8254_read(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 999 struct comedi_insn *insn, unsigned int *data)
e948cb52 1000{
93ba42e9 1001 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1002 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1003 unsigned long flags;
e948cb52 1004
ee4063fa 1005 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1006 data[0] = i8254_read(subpriv->iobase, 0, chan);
ee4063fa 1007 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1008
1009 return 1;
1010}
1011
1012/*
1013 * Handle 'insn_write' for an '8254' counter subdevice.
1014 */
1015static int
da91b269 1016dio200_subdev_8254_write(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1017 struct comedi_insn *insn, unsigned int *data)
e948cb52 1018{
93ba42e9 1019 struct dio200_subdev_8254 *subpriv = s->private;
e948cb52 1020 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1021 unsigned long flags;
e948cb52 1022
ee4063fa 1023 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52 1024 i8254_write(subpriv->iobase, 0, chan, data[0]);
ee4063fa 1025 spin_unlock_irqrestore(&subpriv->spinlock, flags);
e948cb52
IA
1026
1027 return 1;
1028}
1029
1030/*
1031 * Set gate source for an '8254' counter subdevice channel.
1032 */
1033static int
0a85b6f0
MT
1034dio200_set_gate_src(struct dio200_subdev_8254 *subpriv,
1035 unsigned int counter_number, unsigned int gate_src)
e948cb52
IA
1036{
1037 unsigned char byte;
1038
1039 if (!subpriv->has_clk_gat_sce)
1040 return -1;
1041 if (counter_number > 2)
1042 return -1;
1043 if (gate_src > 7)
1044 return -1;
1045
1046 subpriv->gate_src[counter_number] = gate_src;
1047 byte = GAT_SCE(subpriv->which, counter_number, gate_src);
1048 outb(byte, subpriv->gat_sce_iobase);
1049
1050 return 0;
1051}
1052
1053/*
1054 * Get gate source for an '8254' counter subdevice channel.
1055 */
1056static int
0a85b6f0
MT
1057dio200_get_gate_src(struct dio200_subdev_8254 *subpriv,
1058 unsigned int counter_number)
e948cb52
IA
1059{
1060 if (!subpriv->has_clk_gat_sce)
1061 return -1;
1062 if (counter_number > 2)
1063 return -1;
1064
1065 return subpriv->gate_src[counter_number];
1066}
1067
1068/*
1069 * Set clock source for an '8254' counter subdevice channel.
1070 */
1071static int
0a85b6f0
MT
1072dio200_set_clock_src(struct dio200_subdev_8254 *subpriv,
1073 unsigned int counter_number, unsigned int clock_src)
e948cb52
IA
1074{
1075 unsigned char byte;
1076
1077 if (!subpriv->has_clk_gat_sce)
1078 return -1;
1079 if (counter_number > 2)
1080 return -1;
1081 if (clock_src > 7)
1082 return -1;
1083
1084 subpriv->clock_src[counter_number] = clock_src;
1085 byte = CLK_SCE(subpriv->which, counter_number, clock_src);
1086 outb(byte, subpriv->clk_sce_iobase);
1087
1088 return 0;
1089}
1090
1091/*
1092 * Get clock source for an '8254' counter subdevice channel.
1093 */
1094static int
0a85b6f0
MT
1095dio200_get_clock_src(struct dio200_subdev_8254 *subpriv,
1096 unsigned int counter_number, unsigned int *period_ns)
e948cb52
IA
1097{
1098 unsigned clock_src;
1099
1100 if (!subpriv->has_clk_gat_sce)
1101 return -1;
1102 if (counter_number > 2)
1103 return -1;
1104
1105 clock_src = subpriv->clock_src[counter_number];
1106 *period_ns = clock_period[clock_src];
1107 return clock_src;
1108}
1109
1110/*
1111 * Handle 'insn_config' for an '8254' counter subdevice.
1112 */
1113static int
da91b269 1114dio200_subdev_8254_config(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 1115 struct comedi_insn *insn, unsigned int *data)
e948cb52 1116{
93ba42e9 1117 struct dio200_subdev_8254 *subpriv = s->private;
ee4063fa 1118 int ret = 0;
e948cb52 1119 int chan = CR_CHAN(insn->chanspec);
ee4063fa 1120 unsigned long flags;
e948cb52 1121
ee4063fa 1122 spin_lock_irqsave(&subpriv->spinlock, flags);
e948cb52
IA
1123 switch (data[0]) {
1124 case INSN_CONFIG_SET_COUNTER_MODE:
1125 ret = i8254_set_mode(subpriv->iobase, 0, chan, data[1]);
1126 if (ret < 0)
ee4063fa 1127 ret = -EINVAL;
e948cb52
IA
1128 break;
1129 case INSN_CONFIG_8254_READ_STATUS:
1130 data[1] = i8254_status(subpriv->iobase, 0, chan);
1131 break;
1132 case INSN_CONFIG_SET_GATE_SRC:
1133 ret = dio200_set_gate_src(subpriv, chan, data[2]);
1134 if (ret < 0)
ee4063fa 1135 ret = -EINVAL;
e948cb52
IA
1136 break;
1137 case INSN_CONFIG_GET_GATE_SRC:
1138 ret = dio200_get_gate_src(subpriv, chan);
ee4063fa
IA
1139 if (ret < 0) {
1140 ret = -EINVAL;
1141 break;
1142 }
e948cb52
IA
1143 data[2] = ret;
1144 break;
1145 case INSN_CONFIG_SET_CLOCK_SRC:
1146 ret = dio200_set_clock_src(subpriv, chan, data[1]);
1147 if (ret < 0)
ee4063fa 1148 ret = -EINVAL;
e948cb52
IA
1149 break;
1150 case INSN_CONFIG_GET_CLOCK_SRC:
1151 ret = dio200_get_clock_src(subpriv, chan, &data[2]);
ee4063fa
IA
1152 if (ret < 0) {
1153 ret = -EINVAL;
1154 break;
1155 }
e948cb52
IA
1156 data[1] = ret;
1157 break;
1158 default:
ee4063fa 1159 ret = -EINVAL;
e948cb52
IA
1160 break;
1161 }
ee4063fa
IA
1162 spin_unlock_irqrestore(&subpriv->spinlock, flags);
1163 return ret < 0 ? ret : insn->n;
e948cb52
IA
1164}
1165
1166/*
1167 * This function initializes an '8254' counter subdevice.
1168 *
1169 * Note: iobase is the base address of the board, not the subdevice;
1170 * offset is the offset to the 8254 chip.
1171 */
1172static int
da91b269 1173dio200_subdev_8254_init(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0
MT
1174 unsigned long iobase, unsigned offset,
1175 int has_clk_gat_sce)
e948cb52 1176{
93ba42e9 1177 struct dio200_subdev_8254 *subpriv;
e948cb52
IA
1178 unsigned int chan;
1179
1180 subpriv = kzalloc(sizeof(*subpriv), GFP_KERNEL);
1181 if (!subpriv) {
485455d0 1182 dev_err(dev->class_dev, "error! out of memory!\n");
e948cb52
IA
1183 return -ENOMEM;
1184 }
1185
1186 s->private = subpriv;
1187 s->type = COMEDI_SUBD_COUNTER;
1188 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1189 s->n_chan = 3;
1190 s->maxdata = 0xFFFF;
1191 s->insn_read = dio200_subdev_8254_read;
1192 s->insn_write = dio200_subdev_8254_write;
1193 s->insn_config = dio200_subdev_8254_config;
1194
ee4063fa 1195 spin_lock_init(&subpriv->spinlock);
e948cb52
IA
1196 subpriv->iobase = offset + iobase;
1197 subpriv->has_clk_gat_sce = has_clk_gat_sce;
1198 if (has_clk_gat_sce) {
1199 /* Derive CLK_SCE and GAT_SCE register offsets from
1200 * 8254 offset. */
1201 subpriv->clk_sce_iobase =
0a85b6f0 1202 DIO200_XCLK_SCE + (offset >> 3) + iobase;
e948cb52 1203 subpriv->gat_sce_iobase =
0a85b6f0 1204 DIO200_XGAT_SCE + (offset >> 3) + iobase;
e948cb52
IA
1205 subpriv->which = (offset >> 2) & 1;
1206 }
1207
1208 /* Initialize channels. */
1209 for (chan = 0; chan < 3; chan++) {
1210 i8254_set_mode(subpriv->iobase, 0, chan,
0a85b6f0 1211 I8254_MODE0 | I8254_BINARY);
e948cb52
IA
1212 if (subpriv->has_clk_gat_sce) {
1213 /* Gate source 0 is VCC (logic 1). */
1214 dio200_set_gate_src(subpriv, chan, 0);
1215 /* Clock source 0 is the dedicated clock input. */
1216 dio200_set_clock_src(subpriv, chan, 0);
1217 }
1218 }
1219
1220 return 0;
1221}
1222
1223/*
1224 * This function cleans up an '8254' counter subdevice.
1225 */
1226static void
0a85b6f0
MT
1227dio200_subdev_8254_cleanup(struct comedi_device *dev,
1228 struct comedi_subdevice *s)
e948cb52 1229{
d9752ee0 1230 struct dio200_subdev_intr *subpriv = s->private;
669c930c 1231 kfree(subpriv);
e948cb52
IA
1232}
1233
485455d0
IA
1234static void dio200_report_attach(struct comedi_device *dev, unsigned int irq)
1235{
adb4601a
IA
1236 const struct dio200_board *thisboard = comedi_board(dev);
1237 struct dio200_private *devpriv = dev->private;
485455d0
IA
1238 char tmpbuf[60];
1239 int tmplen;
1240
1241 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
1242 thisboard->bustype == isa_bustype)
1243 tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
1244 "(base %#lx) ", dev->iobase);
1245 else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
1246 thisboard->bustype == pci_bustype)
1247 tmplen = scnprintf(tmpbuf, sizeof(tmpbuf),
1248 "(pci %s) ", pci_name(devpriv->pci_dev));
1249 else
1250 tmplen = 0;
1251 if (irq)
1252 tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
1253 "(irq %u%s) ", irq,
1254 (dev->irq ? "" : " UNAVAILABLE"));
1255 else
1256 tmplen += scnprintf(&tmpbuf[tmplen], sizeof(tmpbuf) - tmplen,
1257 "(no irq) ");
1258 dev_info(dev->class_dev, "%s %sattached\n", dev->board_name, tmpbuf);
1259}
1260
c894ec8d
IA
1261static int dio200_common_attach(struct comedi_device *dev, unsigned long iobase,
1262 unsigned int irq, unsigned long req_irq_flags)
e948cb52 1263{
adb4601a 1264 const struct dio200_board *thisboard = comedi_board(dev);
c894ec8d
IA
1265 struct dio200_private *devpriv = dev->private;
1266 const struct dio200_layout_struct *layout =
1267 &dio200_layouts[thisboard->layout];
34c43922 1268 struct comedi_subdevice *s;
e948cb52 1269 int sdx;
c894ec8d 1270 unsigned int n;
e948cb52
IA
1271 int ret;
1272
a6e11e3b 1273 devpriv->intr_sd = -1;
e948cb52 1274 dev->iobase = iobase;
c894ec8d 1275 dev->board_name = thisboard->name;
8b6c5694 1276
2f0b9d08 1277 ret = comedi_alloc_subdevices(dev, layout->n_subdevs);
8b6c5694 1278 if (ret)
e948cb52 1279 return ret;
8b6c5694 1280
e948cb52
IA
1281 for (n = 0; n < dev->n_subdevices; n++) {
1282 s = &dev->subdevices[n];
1283 switch (layout->sdtype[n]) {
1284 case sd_8254:
1285 /* counter subdevice (8254) */
1286 ret = dio200_subdev_8254_init(dev, s, iobase,
0a85b6f0
MT
1287 layout->sdinfo[n],
1288 layout->has_clk_gat_sce);
669c930c 1289 if (ret < 0)
e948cb52 1290 return ret;
e948cb52
IA
1291 break;
1292 case sd_8255:
1293 /* digital i/o subdevice (8255) */
a7f22a84 1294 ret = subdev_8255_init(dev, s, NULL,
0a85b6f0 1295 iobase + layout->sdinfo[n]);
669c930c 1296 if (ret < 0)
e948cb52 1297 return ret;
e948cb52
IA
1298 break;
1299 case sd_intr:
1300 /* 'INTERRUPT' subdevice */
1301 if (irq) {
1302 ret = dio200_subdev_intr_init(dev, s,
0a85b6f0
MT
1303 iobase +
1304 DIO200_INT_SCE,
1305 layout->sdinfo[n],
1306 layout->
1307 has_int_sce);
669c930c 1308 if (ret < 0)
e948cb52 1309 return ret;
e948cb52
IA
1310 devpriv->intr_sd = n;
1311 } else {
1312 s->type = COMEDI_SUBD_UNUSED;
1313 }
1314 break;
1315 default:
1316 s->type = COMEDI_SUBD_UNUSED;
1317 break;
1318 }
1319 }
e948cb52 1320 sdx = devpriv->intr_sd;
669c930c 1321 if (sdx >= 0 && sdx < dev->n_subdevices)
e948cb52 1322 dev->read_subdev = &dev->subdevices[sdx];
e948cb52 1323 if (irq) {
c894ec8d 1324 if (request_irq(irq, dio200_interrupt, req_irq_flags,
e948cb52
IA
1325 DIO200_DRIVER_NAME, dev) >= 0) {
1326 dev->irq = irq;
1327 } else {
485455d0
IA
1328 dev_warn(dev->class_dev,
1329 "warning! irq %u unavailable!\n", irq);
e948cb52
IA
1330 }
1331 }
485455d0 1332 dio200_report_attach(dev, irq);
e948cb52
IA
1333 return 1;
1334}
1335
c894ec8d
IA
1336static int dio200_pci_common_attach(struct comedi_device *dev,
1337 struct pci_dev *pci_dev)
1338{
1339 struct dio200_private *devpriv = dev->private;
1340 unsigned long iobase;
1341 int ret;
1342
1343 devpriv->pci_dev = pci_dev;
1344 ret = comedi_pci_enable(pci_dev, DIO200_DRIVER_NAME);
1345 if (ret < 0) {
1346 dev_err(dev->class_dev,
1347 "error! cannot enable PCI device and request regions!\n");
1348 return ret;
1349 }
1350 iobase = pci_resource_start(pci_dev, 2);
1351 return dio200_common_attach(dev, iobase, pci_dev->irq, IRQF_SHARED);
1352}
1353
1354/*
1355 * Attach is called by the Comedi core to configure the driver
1356 * for a particular board. If you specified a board_name array
1357 * in the driver structure, dev->board_ptr contains that
1358 * address.
1359 */
1360static int dio200_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1361{
1362 const struct dio200_board *thisboard = comedi_board(dev);
1363 int ret;
1364
1365 dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach\n");
1366
1367 ret = alloc_private(dev, sizeof(struct dio200_private));
1368 if (ret < 0) {
1369 dev_err(dev->class_dev, "error! out of memory!\n");
1370 return ret;
1371 }
1372
1373 /* Process options and reserve resources according to bus type. */
1374 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
1375 thisboard->bustype == isa_bustype) {
1376 unsigned long iobase;
1377 unsigned int irq;
1378
1379 iobase = it->options[0];
1380 irq = it->options[1];
1381 ret = dio200_request_region(dev, iobase, DIO200_IO_SIZE);
1382 if (ret < 0)
1383 return ret;
1384 return dio200_common_attach(dev, iobase, irq, 0);
1385 } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
1386 thisboard->bustype == pci_bustype) {
1387 struct pci_dev *pci_dev;
1388 int bus, slot;
1389
1390 bus = it->options[0];
1391 slot = it->options[1];
1392 pci_dev = dio200_find_pci(dev, bus, slot);
1393 if (pci_dev == NULL)
1394 return -EIO;
1395 return dio200_pci_common_attach(dev, pci_dev);
1396 } else {
1397 dev_err(dev->class_dev, DIO200_DRIVER_NAME
1398 ": BUG! cannot determine board type!\n");
1399 return -EINVAL;
1400 }
1401}
1402
1403/*
1404 * The attach_pci hook (if non-NULL) is called at PCI probe time in preference
1405 * to the "manual" attach hook. dev->board_ptr is NULL on entry. There should
1406 * be a board entry matching the supplied PCI device.
1407 */
1408static int __devinit dio200_attach_pci(struct comedi_device *dev,
1409 struct pci_dev *pci_dev)
1410{
1411 int ret;
1412
1413 if (!IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI))
1414 return -EINVAL;
1415
1416 dev_info(dev->class_dev, DIO200_DRIVER_NAME ": attach pci %s\n",
1417 pci_name(pci_dev));
1418 ret = alloc_private(dev, sizeof(struct dio200_private));
1419 if (ret < 0) {
1420 dev_err(dev->class_dev, "error! out of memory!\n");
1421 return ret;
1422 }
1423 dev->board_ptr = dio200_find_pci_board(pci_dev);
1424 if (dev->board_ptr == NULL) {
1425 dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
1426 return -EINVAL;
1427 }
1428 return dio200_pci_common_attach(dev, pci_dev);
1429}
1430
484ecc95 1431static void dio200_detach(struct comedi_device *dev)
e948cb52 1432{
adb4601a
IA
1433 const struct dio200_board *thisboard = comedi_board(dev);
1434 struct dio200_private *devpriv = dev->private;
af105ad3 1435 const struct dio200_layout_struct *layout;
e948cb52
IA
1436 unsigned n;
1437
669c930c 1438 if (dev->irq)
5f74ea14 1439 free_irq(dev->irq, dev);
e948cb52 1440 if (dev->subdevices) {
adb4601a 1441 layout = &dio200_layouts[thisboard->layout];
e948cb52 1442 for (n = 0; n < dev->n_subdevices; n++) {
34c43922 1443 struct comedi_subdevice *s = &dev->subdevices[n];
e948cb52
IA
1444 switch (layout->sdtype[n]) {
1445 case sd_8254:
1446 dio200_subdev_8254_cleanup(dev, s);
1447 break;
1448 case sd_8255:
1449 subdev_8255_cleanup(dev, s);
1450 break;
1451 case sd_intr:
1452 dio200_subdev_intr_cleanup(dev, s);
1453 break;
1454 default:
1455 break;
1456 }
1457 }
1458 }
1459 if (devpriv) {
a6e11e3b
IA
1460 if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI) &&
1461 thisboard->bustype == pci_bustype) {
1462 if (devpriv->pci_dev) {
1463 if (dev->iobase)
1464 comedi_pci_disable(devpriv->pci_dev);
1465 pci_dev_put(devpriv->pci_dev);
1466 }
1467 } else if (IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_ISA) &&
1468 thisboard->bustype == isa_bustype) {
669c930c 1469 if (dev->iobase)
e948cb52 1470 release_region(dev->iobase, DIO200_IO_SIZE);
e948cb52
IA
1471 }
1472 }
e948cb52 1473}
90f703d3 1474
fd97962b
IA
1475/*
1476 * The struct comedi_driver structure tells the Comedi core module
1477 * which functions to call to configure/deconfigure (attach/detach)
1478 * the board, and also about the kernel module that contains
1479 * the device code.
1480 */
1481static struct comedi_driver amplc_dio200_driver = {
1482 .driver_name = DIO200_DRIVER_NAME,
1483 .module = THIS_MODULE,
1484 .attach = dio200_attach,
c894ec8d 1485 .attach_pci = dio200_attach_pci,
fd97962b
IA
1486 .detach = dio200_detach,
1487 .board_name = &dio200_boards[0].name,
1488 .offset = sizeof(struct dio200_board),
1489 .num_names = ARRAY_SIZE(dio200_boards),
1490};
1491
1492#if IS_ENABLED(CONFIG_COMEDI_AMPLC_DIO200_PCI)
1493static DEFINE_PCI_DEVICE_TABLE(dio200_pci_table) = {
1494 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI215) },
1495 { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI272) },
1496 {0}
1497};
1498
1499MODULE_DEVICE_TABLE(pci, dio200_pci_table);
1500
1501static int __devinit amplc_dio200_pci_probe(struct pci_dev *dev,
1502 const struct pci_device_id
1503 *ent)
1504{
1505 return comedi_pci_auto_config(dev, &amplc_dio200_driver);
1506}
1507
1508static void __devexit amplc_dio200_pci_remove(struct pci_dev *dev)
1509{
1510 comedi_pci_auto_unconfig(dev);
1511}
1512
1513static struct pci_driver amplc_dio200_pci_driver = {
1514 .name = DIO200_DRIVER_NAME,
1515 .id_table = dio200_pci_table,
1516 .probe = &amplc_dio200_pci_probe,
1517 .remove = __devexit_p(&amplc_dio200_pci_remove)
1518};
1519module_comedi_pci_driver(amplc_dio200_driver, amplc_dio200_pci_driver);
1520#else
1521module_comedi_driver(amplc_dio200_driver);
1522#endif
1523
90f703d3
AT
1524MODULE_AUTHOR("Comedi http://www.comedi.org");
1525MODULE_DESCRIPTION("Comedi low-level driver");
1526MODULE_LICENSE("GPL");
This page took 0.422413 seconds and 5 git commands to generate.