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