staging: comedi: adl_pci9111: cleanup pci9111_ao_insn_write()
[pandora-kernel.git] / drivers / staging / comedi / drivers / adl_pci9111.c
1 /*
2
3 comedi/drivers/adl_pci9111.c
4
5 Hardware driver for PCI9111 ADLink cards:
6
7 PCI-9111HR
8
9 Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
10
11 This program is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26 /*
27 Driver: adl_pci9111
28 Description: Adlink PCI-9111HR
29 Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
30 Devices: [ADLink] PCI-9111HR (adl_pci9111)
31 Status: experimental
32
33 Supports:
34
35         - ai_insn read
36         - ao_insn read/write
37         - di_insn read
38         - do_insn read/write
39         - ai_do_cmd mode with the following sources:
40
41         - start_src             TRIG_NOW
42         - scan_begin_src        TRIG_FOLLOW     TRIG_TIMER      TRIG_EXT
43         - convert_src                           TRIG_TIMER      TRIG_EXT
44         - scan_end_src          TRIG_COUNT
45         - stop_src              TRIG_COUNT      TRIG_NONE
46
47 The scanned channels must be consecutive and start from 0. They must
48 all have the same range and aref.
49
50 Configuration options:
51
52         [0] - PCI bus number (optional)
53         [1] - PCI slot number (optional)
54
55 If bus/slot is not specified, the first available PCI
56 device will be used.
57
58 */
59
60 /*
61 CHANGELOG:
62
63 2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
64 a multiple of chanlist_len*convert_arg.
65 2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
66 2002/02/18 Added external trigger support for analog input.
67
68 TODO:
69
70         - Really test implemented functionality.
71         - Add support for the PCI-9111DG with a probe routine to identify
72           the card type (perhaps with the help of the channel number readback
73           of the A/D Data register).
74         - Add external multiplexer support.
75
76 */
77
78 #include "../comedidev.h"
79
80 #include <linux/delay.h>
81 #include <linux/interrupt.h>
82
83 #include "8253.h"
84 #include "comedi_fc.h"
85
86 #define PCI9111_DRIVER_NAME     "adl_pci9111"
87 #define PCI9111_HR_DEVICE_ID    0x9111
88
89 /*  TODO: Add other pci9111 board id */
90
91 #define PCI9111_IO_RANGE        0x0100
92
93 #define PCI9111_FIFO_HALF_SIZE  512
94
95 #define PCI9111_AI_CHANNEL_NBR                  16
96
97 #define PCI9111_AI_RESOLUTION                   12
98 #define PCI9111_AI_RESOLUTION_MASK              0x0FFF
99 #define PCI9111_AI_RESOLUTION_2_CMP_BIT         0x0800
100
101 #define PCI9111_HR_AI_RESOLUTION                16
102 #define PCI9111_HR_AI_RESOLUTION_MASK           0xFFFF
103 #define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT      0x8000
104
105 #define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS    10000
106 #define PCI9111_AO_CHANNEL_NBR                  1
107 #define PCI9111_DI_CHANNEL_NBR                  16
108 #define PCI9111_DO_CHANNEL_NBR                  16
109
110 #define PCI9111_RANGE_SETTING_DELAY             10
111 #define PCI9111_AI_INSTANT_READ_UDELAY_US       2
112 #define PCI9111_AI_INSTANT_READ_TIMEOUT         100
113
114 #define PCI9111_8254_CLOCK_PERIOD_NS            500
115
116 /* IO address map */
117
118 #define PCI9111_REGISTER_AD_FIFO_VALUE                  0x00 /* AD Data stored
119                                                                 in FIFO */
120 #define PCI9111_AO_REG                                  0x00
121 #define PCI9111_DIO_REG                                 0x02
122 #define PCI9111_REGISTER_EXTENDED_IO_PORTS              0x04
123 #define PCI9111_REGISTER_AD_CHANNEL_CONTROL             0x06 /* Channel
124                                                                 selection */
125 #define PCI9111_REGISTER_AD_CHANNEL_READBACK            0x06
126 #define PCI9111_REGISTER_INPUT_SIGNAL_RANGE             0x08
127 #define PCI9111_REGISTER_RANGE_STATUS_READBACK          0x08
128 #define PCI9111_REGISTER_TRIGGER_MODE_CONTROL           0x0A
129 #define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK     0x0A
130 #define PCI9111_REGISTER_SOFTWARE_TRIGGER               0x0E
131 #define PCI9111_REGISTER_INTERRUPT_CONTROL              0x0C
132 #define PCI9111_8254_BASE_REG                           0x40
133 #define PCI9111_REGISTER_INTERRUPT_CLEAR                0x48
134
135 #define PCI9111_TRIGGER_MASK                            0x0F
136 #define PCI9111_PTRG_OFF                                (0 << 3)
137 #define PCI9111_PTRG_ON                                 (1 << 3)
138 #define PCI9111_EITS_EXTERNAL                           (1 << 2)
139 #define PCI9111_EITS_INTERNAL                           (0 << 2)
140 #define PCI9111_TPST_SOFTWARE_TRIGGER                   (0 << 1)
141 #define PCI9111_TPST_TIMER_PACER                        (1 << 1)
142 #define PCI9111_ASCAN_ON                                (1 << 0)
143 #define PCI9111_ASCAN_OFF                               (0 << 0)
144
145 #define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
146 #define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL          (1 << 0)
147 #define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK              (0 << 1)
148 #define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG                 (1 << 1)
149 #define PCI9111_FFEN_SET_FIFO_ENABLE                    (0 << 2)
150 #define PCI9111_FFEN_SET_FIFO_DISABLE                   (1 << 2)
151
152 #define PCI9111_CHANNEL_MASK                            0x0F
153
154 #define PCI9111_RANGE_MASK                              0x07
155 #define PCI9111_FIFO_EMPTY_MASK                         0x10
156 #define PCI9111_FIFO_HALF_FULL_MASK                     0x20
157 #define PCI9111_FIFO_FULL_MASK                          0x40
158 #define PCI9111_AD_BUSY_MASK                            0x80
159
160 /*
161  * Define inlined function
162  */
163
164 #define pci9111_trigger_and_autoscan_get() \
165         (inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
166
167 #define pci9111_trigger_and_autoscan_set(flags) \
168         outb(flags, dev->iobase + PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
169
170 #define pci9111_interrupt_and_fifo_get() \
171         ((inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
172                 >> 4) & 0x03)
173
174 #define pci9111_interrupt_and_fifo_set(flags) \
175         outb(flags, dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL)
176
177 #define pci9111_interrupt_clear() \
178         outb(0, dev->iobase + PCI9111_REGISTER_INTERRUPT_CLEAR)
179
180 #define pci9111_software_trigger() \
181         outb(0, dev->iobase + PCI9111_REGISTER_SOFTWARE_TRIGGER)
182
183 #define pci9111_fifo_reset() do { \
184         outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
185                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
186         outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
187                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
188         outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
189                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
190         } while (0)
191
192 #define pci9111_is_fifo_full() \
193         ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
194                 PCI9111_FIFO_FULL_MASK) == 0)
195
196 #define pci9111_is_fifo_half_full() \
197         ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
198                 PCI9111_FIFO_HALF_FULL_MASK) == 0)
199
200 #define pci9111_is_fifo_empty() \
201         ((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
202                 PCI9111_FIFO_EMPTY_MASK) == 0)
203
204 #define pci9111_ai_channel_set(channel) \
205         outb((channel)&PCI9111_CHANNEL_MASK, \
206                 dev->iobase + PCI9111_REGISTER_AD_CHANNEL_CONTROL)
207
208 #define pci9111_ai_channel_get() \
209         (inb(dev->iobase + PCI9111_REGISTER_AD_CHANNEL_READBACK) \
210                 &PCI9111_CHANNEL_MASK)
211
212 #define pci9111_ai_range_set(range) \
213         outb((range)&PCI9111_RANGE_MASK, \
214                 dev->iobase + PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
215
216 #define pci9111_ai_range_get() \
217         (inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK) \
218                 &PCI9111_RANGE_MASK)
219
220 #define pci9111_ai_get_data() \
221         (((inw(dev->iobase + PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
222                 &PCI9111_AI_RESOLUTION_MASK) \
223                         ^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
224
225 #define pci9111_hr_ai_get_data() \
226         ((inw(dev->iobase + PCI9111_REGISTER_AD_FIFO_VALUE) \
227                 &PCI9111_HR_AI_RESOLUTION_MASK) \
228                         ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
229
230 static const struct comedi_lrange pci9111_hr_ai_range = {
231         5,
232         {
233          BIP_RANGE(10),
234          BIP_RANGE(5),
235          BIP_RANGE(2.5),
236          BIP_RANGE(1.25),
237          BIP_RANGE(0.625)
238          }
239 };
240
241 /*  */
242 /*  Board specification structure */
243 /*  */
244
245 struct pci9111_board {
246         const char *name;       /*  driver name */
247         int device_id;
248         int ai_channel_nbr;     /*  num of A/D chans */
249         int ao_channel_nbr;     /*  num of D/A chans */
250         int ai_resolution;      /*  resolution of A/D */
251         int ai_resolution_mask;
252         int ao_maxdata;
253         const struct comedi_lrange *ai_range_list;      /*  rangelist for A/D */
254         const struct comedi_lrange *ao_range_list;      /*  rangelist for D/A */
255         unsigned int ai_acquisition_period_min_ns;
256 };
257
258 static const struct pci9111_board pci9111_boards[] = {
259         {
260          .name = "pci9111_hr",
261          .device_id = PCI9111_HR_DEVICE_ID,
262          .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
263          .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
264          .ai_resolution = PCI9111_HR_AI_RESOLUTION,
265          .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
266          .ao_maxdata = 0x0fff,
267          .ai_range_list = &pci9111_hr_ai_range,
268          .ao_range_list = &range_bipolar10,
269          .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
270 };
271
272 /*  Private data structure */
273
274 struct pci9111_private_data {
275         unsigned long io_range; /*  PCI6503 io range */
276
277         unsigned long lcr_io_base; /* Local configuration register base
278                                     * address */
279         unsigned long lcr_io_range;
280
281         int stop_counter;
282         int stop_is_none;
283
284         unsigned int scan_delay;
285         unsigned int chanlist_len;
286         unsigned int chunk_counter;
287         unsigned int chunk_num_samples;
288
289         int ao_readback;        /*  Last written analog output data */
290
291         unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
292                                        * pacer */
293         unsigned int timer_divisor_2;
294
295         int is_valid;           /*  Is device valid */
296
297         short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
298 };
299
300 /*  ------------------------------------------------------------------ */
301 /*  PLX9050 SECTION */
302 /*  ------------------------------------------------------------------ */
303
304 #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
305
306 #define PLX9050_LINTI1_ENABLE           (1 << 0)
307 #define PLX9050_LINTI1_ACTIVE_HIGH      (1 << 1)
308 #define PLX9050_LINTI1_STATUS           (1 << 2)
309 #define PLX9050_LINTI2_ENABLE           (1 << 3)
310 #define PLX9050_LINTI2_ACTIVE_HIGH      (1 << 4)
311 #define PLX9050_LINTI2_STATUS           (1 << 5)
312 #define PLX9050_PCI_INTERRUPT_ENABLE    (1 << 6)
313 #define PLX9050_SOFTWARE_INTERRUPT      (1 << 7)
314
315 static void plx9050_interrupt_control(unsigned long io_base,
316                                       bool LINTi1_enable,
317                                       bool LINTi1_active_high,
318                                       bool LINTi2_enable,
319                                       bool LINTi2_active_high,
320                                       bool interrupt_enable)
321 {
322         int flags = 0;
323
324         if (LINTi1_enable)
325                 flags |= PLX9050_LINTI1_ENABLE;
326         if (LINTi1_active_high)
327                 flags |= PLX9050_LINTI1_ACTIVE_HIGH;
328         if (LINTi2_enable)
329                 flags |= PLX9050_LINTI2_ENABLE;
330         if (LINTi2_active_high)
331                 flags |= PLX9050_LINTI2_ACTIVE_HIGH;
332
333         if (interrupt_enable)
334                 flags |= PLX9050_PCI_INTERRUPT_ENABLE;
335
336         outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
337 }
338
339 /*  ------------------------------------------------------------------ */
340 /*  MISCELLANEOUS SECTION */
341 /*  ------------------------------------------------------------------ */
342
343 /*  8254 timer */
344
345 static void pci9111_timer_set(struct comedi_device *dev)
346 {
347         struct pci9111_private_data *dev_private = dev->private;
348         unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
349
350         i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
351         i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
352         i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
353
354         udelay(1);
355
356         i8254_write(timer_base, 1, 2, dev_private->timer_divisor_2);
357         i8254_write(timer_base, 1, 1, dev_private->timer_divisor_1);
358 }
359
360 enum pci9111_trigger_sources {
361         software,
362         timer_pacer,
363         external
364 };
365
366 static void pci9111_trigger_source_set(struct comedi_device *dev,
367                                        enum pci9111_trigger_sources source)
368 {
369         int flags;
370
371         flags = pci9111_trigger_and_autoscan_get() & 0x09;
372
373         switch (source) {
374         case software:
375                 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
376                 break;
377
378         case timer_pacer:
379                 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
380                 break;
381
382         case external:
383                 flags |= PCI9111_EITS_EXTERNAL;
384                 break;
385         }
386
387         pci9111_trigger_and_autoscan_set(flags);
388 }
389
390 static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
391 {
392         int flags;
393
394         flags = pci9111_trigger_and_autoscan_get() & 0x07;
395
396         if (pretrigger)
397                 flags |= PCI9111_PTRG_ON;
398
399         pci9111_trigger_and_autoscan_set(flags);
400 }
401
402 static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
403 {
404         int flags;
405
406         flags = pci9111_trigger_and_autoscan_get() & 0x0e;
407
408         if (autoscan)
409                 flags |= PCI9111_ASCAN_ON;
410
411         pci9111_trigger_and_autoscan_set(flags);
412 }
413
414 enum pci9111_ISC0_sources {
415         irq_on_eoc,
416         irq_on_fifo_half_full
417 };
418
419 enum pci9111_ISC1_sources {
420         irq_on_timer_tick,
421         irq_on_external_trigger
422 };
423
424 static void pci9111_interrupt_source_set(struct comedi_device *dev,
425                                          enum pci9111_ISC0_sources irq_0_source,
426                                          enum pci9111_ISC1_sources irq_1_source)
427 {
428         int flags;
429
430         flags = pci9111_interrupt_and_fifo_get() & 0x04;
431
432         if (irq_0_source == irq_on_fifo_half_full)
433                 flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
434
435         if (irq_1_source == irq_on_external_trigger)
436                 flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
437
438         pci9111_interrupt_and_fifo_set(flags);
439 }
440
441 /*  ------------------------------------------------------------------ */
442 /*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
443 /*  ------------------------------------------------------------------ */
444
445 /*  Cancel analog input autoscan */
446
447 #undef AI_DO_CMD_DEBUG
448
449 static int pci9111_ai_cancel(struct comedi_device *dev,
450                              struct comedi_subdevice *s)
451 {
452         struct pci9111_private_data *dev_private = dev->private;
453
454         /*  Disable interrupts */
455
456         plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
457                                   true, false);
458
459         pci9111_trigger_source_set(dev, software);
460
461         pci9111_autoscan_set(dev, false);
462
463         pci9111_fifo_reset();
464
465 #ifdef AI_DO_CMD_DEBUG
466         printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
467 #endif
468
469         return 0;
470 }
471
472 /*  Test analog input command */
473
474 #define pci9111_check_trigger_src(src, flags)   do {                    \
475                 tmp = src;                                              \
476                 src &= flags;                                           \
477                 if (!src || tmp != src)                                 \
478                         error++;                                        \
479         } while (false);
480
481 static int
482 pci9111_ai_do_cmd_test(struct comedi_device *dev,
483                        struct comedi_subdevice *s, struct comedi_cmd *cmd)
484 {
485         struct pci9111_private_data *dev_private = dev->private;
486         int tmp;
487         int error = 0;
488         int range, reference;
489         int i;
490         struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
491
492         /*  Step 1 : check if trigger are trivialy valid */
493
494         pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
495         pci9111_check_trigger_src(cmd->scan_begin_src,
496                                   TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
497         pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
498         pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
499         pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
500
501         if (error)
502                 return 1;
503
504         /*  step 2 : make sure trigger sources are unique and mutually
505          *  compatible */
506
507         if (cmd->start_src != TRIG_NOW)
508                 error++;
509
510         if ((cmd->scan_begin_src != TRIG_TIMER) &&
511             (cmd->scan_begin_src != TRIG_FOLLOW) &&
512             (cmd->scan_begin_src != TRIG_EXT))
513                 error++;
514
515         if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
516                 error++;
517         if ((cmd->convert_src == TRIG_TIMER) &&
518             !((cmd->scan_begin_src == TRIG_TIMER) ||
519               (cmd->scan_begin_src == TRIG_FOLLOW)))
520                 error++;
521         if ((cmd->convert_src == TRIG_EXT) &&
522             !((cmd->scan_begin_src == TRIG_EXT) ||
523               (cmd->scan_begin_src == TRIG_FOLLOW)))
524                 error++;
525
526
527         if (cmd->scan_end_src != TRIG_COUNT)
528                 error++;
529         if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
530                 error++;
531
532         if (error)
533                 return 2;
534
535         /*  Step 3 : make sure arguments are trivialy compatible */
536
537         if (cmd->chanlist_len < 1) {
538                 cmd->chanlist_len = 1;
539                 error++;
540         }
541
542         if (cmd->chanlist_len > board->ai_channel_nbr) {
543                 cmd->chanlist_len = board->ai_channel_nbr;
544                 error++;
545         }
546
547         if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
548                 cmd->start_arg = 0;
549                 error++;
550         }
551
552         if ((cmd->convert_src == TRIG_TIMER) &&
553             (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
554                 cmd->convert_arg = board->ai_acquisition_period_min_ns;
555                 error++;
556         }
557         if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
558                 cmd->convert_arg = 0;
559                 error++;
560         }
561
562         if ((cmd->scan_begin_src == TRIG_TIMER) &&
563             (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
564                 cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
565                 error++;
566         }
567         if ((cmd->scan_begin_src == TRIG_FOLLOW)
568             && (cmd->scan_begin_arg != 0)) {
569                 cmd->scan_begin_arg = 0;
570                 error++;
571         }
572         if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
573                 cmd->scan_begin_arg = 0;
574                 error++;
575         }
576
577         if ((cmd->scan_end_src == TRIG_COUNT) &&
578             (cmd->scan_end_arg != cmd->chanlist_len)) {
579                 cmd->scan_end_arg = cmd->chanlist_len;
580                 error++;
581         }
582
583         if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
584                 cmd->stop_arg = 1;
585                 error++;
586         }
587         if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
588                 cmd->stop_arg = 0;
589                 error++;
590         }
591
592         if (error)
593                 return 3;
594
595         /*  Step 4 : fix up any arguments */
596
597         if (cmd->convert_src == TRIG_TIMER) {
598                 tmp = cmd->convert_arg;
599                 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
600                                                &(dev_private->timer_divisor_1),
601                                                &(dev_private->timer_divisor_2),
602                                                &(cmd->convert_arg),
603                                                cmd->flags & TRIG_ROUND_MASK);
604                 if (tmp != cmd->convert_arg)
605                         error++;
606         }
607         /*  There's only one timer on this card, so the scan_begin timer must */
608         /*  be a multiple of chanlist_len*convert_arg */
609
610         if (cmd->scan_begin_src == TRIG_TIMER) {
611
612                 unsigned int scan_begin_min;
613                 unsigned int scan_begin_arg;
614                 unsigned int scan_factor;
615
616                 scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
617
618                 if (cmd->scan_begin_arg != scan_begin_min) {
619                         if (scan_begin_min < cmd->scan_begin_arg) {
620                                 scan_factor =
621                                     cmd->scan_begin_arg / scan_begin_min;
622                                 scan_begin_arg = scan_factor * scan_begin_min;
623                                 if (cmd->scan_begin_arg != scan_begin_arg) {
624                                         cmd->scan_begin_arg = scan_begin_arg;
625                                         error++;
626                                 }
627                         } else {
628                                 cmd->scan_begin_arg = scan_begin_min;
629                                 error++;
630                         }
631                 }
632         }
633
634         if (error)
635                 return 4;
636
637         /*  Step 5 : check channel list */
638
639         if (cmd->chanlist) {
640
641                 range = CR_RANGE(cmd->chanlist[0]);
642                 reference = CR_AREF(cmd->chanlist[0]);
643
644                 if (cmd->chanlist_len > 1) {
645                         for (i = 0; i < cmd->chanlist_len; i++) {
646                                 if (CR_CHAN(cmd->chanlist[i]) != i) {
647                                         comedi_error(dev,
648                                                      "entries in chanlist must be consecutive "
649                                                      "channels,counting upwards from 0\n");
650                                         error++;
651                                 }
652                                 if (CR_RANGE(cmd->chanlist[i]) != range) {
653                                         comedi_error(dev,
654                                                      "entries in chanlist must all have the same gain\n");
655                                         error++;
656                                 }
657                                 if (CR_AREF(cmd->chanlist[i]) != reference) {
658                                         comedi_error(dev,
659                                                      "entries in chanlist must all have the same reference\n");
660                                         error++;
661                                 }
662                         }
663                 } else {
664                         if ((CR_CHAN(cmd->chanlist[0]) >
665                              (board->ai_channel_nbr - 1))
666                             || (CR_CHAN(cmd->chanlist[0]) < 0)) {
667                                 comedi_error(dev,
668                                              "channel number is out of limits\n");
669                                 error++;
670                         }
671                 }
672         }
673
674         if (error)
675                 return 5;
676
677         return 0;
678
679 }
680
681 /*  Analog input command */
682
683 static int pci9111_ai_do_cmd(struct comedi_device *dev,
684                              struct comedi_subdevice *s)
685 {
686         struct pci9111_private_data *dev_private = dev->private;
687         struct comedi_cmd *async_cmd = &s->async->cmd;
688
689         if (!dev->irq) {
690                 comedi_error(dev,
691                              "no irq assigned for PCI9111, cannot do hardware conversion");
692                 return -1;
693         }
694         /*  Set channel scan limit */
695         /*  PCI9111 allows only scanning from channel 0 to channel n */
696         /*  TODO: handle the case of an external multiplexer */
697
698         if (async_cmd->chanlist_len > 1) {
699                 pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
700                 pci9111_autoscan_set(dev, true);
701         } else {
702                 pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
703                 pci9111_autoscan_set(dev, false);
704         }
705
706         /*  Set gain */
707         /*  This is the same gain on every channel */
708
709         pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
710
711         /* Set counter */
712
713         switch (async_cmd->stop_src) {
714         case TRIG_COUNT:
715                 dev_private->stop_counter =
716                     async_cmd->stop_arg * async_cmd->chanlist_len;
717                 dev_private->stop_is_none = 0;
718                 break;
719
720         case TRIG_NONE:
721                 dev_private->stop_counter = 0;
722                 dev_private->stop_is_none = 1;
723                 break;
724
725         default:
726                 comedi_error(dev, "Invalid stop trigger");
727                 return -1;
728         }
729
730         /*  Set timer pacer */
731
732         dev_private->scan_delay = 0;
733         switch (async_cmd->convert_src) {
734         case TRIG_TIMER:
735                 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
736                                                &(dev_private->timer_divisor_1),
737                                                &(dev_private->timer_divisor_2),
738                                                &(async_cmd->convert_arg),
739                                                async_cmd->
740                                                flags & TRIG_ROUND_MASK);
741 #ifdef AI_DO_CMD_DEBUG
742                 printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
743                        dev_private->timer_divisor_1,
744                        dev_private->timer_divisor_2);
745 #endif
746
747                 pci9111_trigger_source_set(dev, software);
748                 pci9111_timer_set(dev);
749                 pci9111_fifo_reset();
750                 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
751                                              irq_on_timer_tick);
752                 pci9111_trigger_source_set(dev, timer_pacer);
753                 plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
754                                           false, true, true);
755
756                 if (async_cmd->scan_begin_src == TRIG_TIMER) {
757                         dev_private->scan_delay =
758                                 (async_cmd->scan_begin_arg /
759                                  (async_cmd->convert_arg *
760                                   async_cmd->chanlist_len)) - 1;
761                 }
762
763                 break;
764
765         case TRIG_EXT:
766
767                 pci9111_trigger_source_set(dev, external);
768                 pci9111_fifo_reset();
769                 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
770                                              irq_on_timer_tick);
771                 plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
772                                           false, true, true);
773
774                 break;
775
776         default:
777                 comedi_error(dev, "Invalid convert trigger");
778                 return -1;
779         }
780
781         dev_private->stop_counter *= (1 + dev_private->scan_delay);
782         dev_private->chanlist_len = async_cmd->chanlist_len;
783         dev_private->chunk_counter = 0;
784         dev_private->chunk_num_samples =
785             dev_private->chanlist_len * (1 + dev_private->scan_delay);
786
787 #ifdef AI_DO_CMD_DEBUG
788         printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
789         printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
790                pci9111_trigger_and_autoscan_get());
791         printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
792                pci9111_interrupt_and_fifo_get());
793         printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
794         printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
795                dev_private->stop_counter);
796         printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
797                dev_private->scan_delay);
798         printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
799                dev_private->chanlist_len);
800         printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
801                dev_private->chunk_num_samples);
802 #endif
803
804         return 0;
805 }
806
807 static void pci9111_ai_munge(struct comedi_device *dev,
808                              struct comedi_subdevice *s, void *data,
809                              unsigned int num_bytes,
810                              unsigned int start_chan_index)
811 {
812         unsigned int i, num_samples = num_bytes / sizeof(short);
813         short *array = data;
814         int resolution =
815             ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
816
817         for (i = 0; i < num_samples; i++) {
818                 if (resolution == PCI9111_HR_AI_RESOLUTION)
819                         array[i] =
820                             (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
821                             PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
822                 else
823                         array[i] =
824                             ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
825                             PCI9111_AI_RESOLUTION_2_CMP_BIT;
826         }
827 }
828
829 /*  ------------------------------------------------------------------ */
830 /*  INTERRUPT SECTION */
831 /*  ------------------------------------------------------------------ */
832
833 #undef INTERRUPT_DEBUG
834
835 static irqreturn_t pci9111_interrupt(int irq, void *p_device)
836 {
837         struct comedi_device *dev = p_device;
838         struct pci9111_private_data *dev_private = dev->private;
839         struct comedi_subdevice *s = dev->read_subdev;
840         struct comedi_async *async;
841         unsigned long irq_flags;
842         unsigned char intcsr;
843
844         if (!dev->attached) {
845                 /*  Ignore interrupt before device fully attached. */
846                 /*  Might not even have allocated subdevices yet! */
847                 return IRQ_NONE;
848         }
849
850         async = s->async;
851
852         spin_lock_irqsave(&dev->spinlock, irq_flags);
853
854         /*  Check if we are source of interrupt */
855         intcsr = inb(dev_private->lcr_io_base +
856                      PLX9050_REGISTER_INTERRUPT_CONTROL);
857         if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
858               && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
859                    == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
860                   || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
861                       == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
862                 /*  Not the source of the interrupt. */
863                 /*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
864                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
865                 return IRQ_NONE;
866         }
867
868         if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
869             (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
870                 /*  Interrupt comes from fifo_half-full signal */
871
872                 if (pci9111_is_fifo_full()) {
873                         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
874                         comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
875                         pci9111_interrupt_clear();
876                         pci9111_ai_cancel(dev, s);
877                         async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
878                         comedi_event(dev, s);
879
880                         return IRQ_HANDLED;
881                 }
882
883                 if (pci9111_is_fifo_half_full()) {
884                         unsigned int num_samples;
885                         unsigned int bytes_written = 0;
886
887 #ifdef INTERRUPT_DEBUG
888                         printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
889 #endif
890
891                         num_samples =
892                             PCI9111_FIFO_HALF_SIZE >
893                             dev_private->stop_counter
894                             && !dev_private->
895                             stop_is_none ? dev_private->stop_counter :
896                             PCI9111_FIFO_HALF_SIZE;
897                         insw(dev->iobase + PCI9111_REGISTER_AD_FIFO_VALUE,
898                              dev_private->ai_bounce_buffer, num_samples);
899
900                         if (dev_private->scan_delay < 1) {
901                                 bytes_written =
902                                     cfc_write_array_to_buffer(s,
903                                                               dev_private->
904                                                               ai_bounce_buffer,
905                                                               num_samples *
906                                                               sizeof(short));
907                         } else {
908                                 int position = 0;
909                                 int to_read;
910
911                                 while (position < num_samples) {
912                                         if (dev_private->chunk_counter <
913                                             dev_private->chanlist_len) {
914                                                 to_read =
915                                                     dev_private->chanlist_len -
916                                                     dev_private->chunk_counter;
917
918                                                 if (to_read >
919                                                     num_samples - position)
920                                                         to_read =
921                                                             num_samples -
922                                                             position;
923
924                                                 bytes_written +=
925                                                     cfc_write_array_to_buffer
926                                                     (s,
927                                                      dev_private->ai_bounce_buffer
928                                                      + position,
929                                                      to_read * sizeof(short));
930                                         } else {
931                                                 to_read =
932                                                     dev_private->chunk_num_samples
933                                                     -
934                                                     dev_private->chunk_counter;
935                                                 if (to_read >
936                                                     num_samples - position)
937                                                         to_read =
938                                                             num_samples -
939                                                             position;
940
941                                                 bytes_written +=
942                                                     sizeof(short) * to_read;
943                                         }
944
945                                         position += to_read;
946                                         dev_private->chunk_counter += to_read;
947
948                                         if (dev_private->chunk_counter >=
949                                             dev_private->chunk_num_samples)
950                                                 dev_private->chunk_counter = 0;
951                                 }
952                         }
953
954                         dev_private->stop_counter -=
955                             bytes_written / sizeof(short);
956                 }
957         }
958
959         if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
960                 async->events |= COMEDI_CB_EOA;
961                 pci9111_ai_cancel(dev, s);
962         }
963
964         /* Very important, otherwise another interrupt request will be inserted
965          * and will cause driver hangs on processing interrupt event. */
966
967         pci9111_interrupt_clear();
968
969         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
970
971         comedi_event(dev, s);
972
973         return IRQ_HANDLED;
974 }
975
976 /*  ------------------------------------------------------------------ */
977 /*  INSTANT ANALOG INPUT OUTPUT SECTION */
978 /*  ------------------------------------------------------------------ */
979
980 /*  analog instant input */
981
982 #undef AI_INSN_DEBUG
983
984 static int pci9111_ai_insn_read(struct comedi_device *dev,
985                                 struct comedi_subdevice *s,
986                                 struct comedi_insn *insn, unsigned int *data)
987 {
988         int resolution =
989             ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
990
991         int timeout, i;
992
993 #ifdef AI_INSN_DEBUG
994         printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
995                CR_CHAN((&insn->chanspec)[0]),
996                CR_RANGE((&insn->chanspec)[0]), insn->n);
997 #endif
998
999         pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
1000
1001         if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
1002                 pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
1003
1004         pci9111_fifo_reset();
1005
1006         for (i = 0; i < insn->n; i++) {
1007                 pci9111_software_trigger();
1008
1009                 timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
1010
1011                 while (timeout--) {
1012                         if (!pci9111_is_fifo_empty())
1013                                 goto conversion_done;
1014                 }
1015
1016                 comedi_error(dev, "A/D read timeout");
1017                 data[i] = 0;
1018                 pci9111_fifo_reset();
1019                 return -ETIME;
1020
1021 conversion_done:
1022
1023                 if (resolution == PCI9111_HR_AI_RESOLUTION)
1024                         data[i] = pci9111_hr_ai_get_data();
1025                 else
1026                         data[i] = pci9111_ai_get_data();
1027         }
1028
1029 #ifdef AI_INSN_DEBUG
1030         printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
1031                pci9111_ai_channel_get(),
1032                pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
1033 #endif
1034
1035         return i;
1036 }
1037
1038 static int pci9111_ao_insn_write(struct comedi_device *dev,
1039                                  struct comedi_subdevice *s,
1040                                  struct comedi_insn *insn,
1041                                  unsigned int *data)
1042 {
1043         struct pci9111_private_data *dev_private = dev->private;
1044         unsigned int val = 0;
1045         int i;
1046
1047         for (i = 0; i < insn->n; i++) {
1048                 val = data[i];
1049                 outw(val, dev->iobase + PCI9111_AO_REG);
1050         }
1051         dev_private->ao_readback = val;
1052
1053         return insn->n;
1054 }
1055
1056 static int pci9111_ao_insn_read(struct comedi_device *dev,
1057                                 struct comedi_subdevice *s,
1058                                 struct comedi_insn *insn,
1059                                 unsigned int *data)
1060 {
1061         struct pci9111_private_data *dev_private = dev->private;
1062         int i;
1063
1064         for (i = 0; i < insn->n; i++)
1065                 data[i] = dev_private->ao_readback;
1066
1067         return insn->n;
1068 }
1069
1070 static int pci9111_di_insn_bits(struct comedi_device *dev,
1071                                 struct comedi_subdevice *s,
1072                                 struct comedi_insn *insn,
1073                                 unsigned int *data)
1074 {
1075         data[1] = inw(dev->iobase + PCI9111_DIO_REG);
1076
1077         return insn->n;
1078 }
1079
1080 static int pci9111_do_insn_bits(struct comedi_device *dev,
1081                                 struct comedi_subdevice *s,
1082                                 struct comedi_insn *insn,
1083                                 unsigned int *data)
1084 {
1085         unsigned int mask = data[0];
1086         unsigned int bits = data[1];
1087
1088         if (mask) {
1089                 s->state &= ~mask;
1090                 s->state |= (bits & mask);
1091
1092                 outw(s->state, dev->iobase + PCI9111_DIO_REG);
1093         }
1094
1095         data[1] = s->state;
1096
1097         return insn->n;
1098 }
1099
1100 /*  ------------------------------------------------------------------ */
1101 /*  INITIALISATION SECTION */
1102 /*  ------------------------------------------------------------------ */
1103
1104 /*  Reset device */
1105
1106 static int pci9111_reset(struct comedi_device *dev)
1107 {
1108         struct pci9111_private_data *dev_private = dev->private;
1109
1110         /*  Set trigger source to software */
1111
1112         plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
1113                                   true, false);
1114
1115         pci9111_trigger_source_set(dev, software);
1116         pci9111_pretrigger_set(dev, false);
1117         pci9111_autoscan_set(dev, false);
1118
1119         /*  Reset 8254 chip */
1120
1121         dev_private->timer_divisor_1 = 0;
1122         dev_private->timer_divisor_2 = 0;
1123
1124         pci9111_timer_set(dev);
1125
1126         return 0;
1127 }
1128
1129 static struct pci_dev *pci9111_find_pci(struct comedi_device *dev,
1130                                         struct comedi_devconfig *it)
1131 {
1132         struct pci_dev *pcidev = NULL;
1133         int bus = it->options[0];
1134         int slot = it->options[1];
1135         int i;
1136
1137         for_each_pci_dev(pcidev) {
1138                 if (pcidev->vendor != PCI_VENDOR_ID_ADLINK)
1139                         continue;
1140                 for (i = 0; i < ARRAY_SIZE(pci9111_boards); i++) {
1141                         if (pcidev->device != pci9111_boards[i].device_id)
1142                                 continue;
1143                         if (bus || slot) {
1144                                 /* requested particular bus/slot */
1145                                 if (pcidev->bus->number != bus ||
1146                                     PCI_SLOT(pcidev->devfn) != slot)
1147                                         continue;
1148                         }
1149                         dev->board_ptr = pci9111_boards + i;
1150                         printk(KERN_ERR
1151                                 "comedi%d: found %s (b:s:f=%d:%d:%d), irq=%d\n",
1152                                 dev->minor, pci9111_boards[i].name,
1153                                 pcidev->bus->number, PCI_SLOT(pcidev->devfn),
1154                                 PCI_FUNC(pcidev->devfn), pcidev->irq);
1155                         return pcidev;
1156                 }
1157         }
1158         printk(KERN_ERR
1159                 "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
1160                 dev->minor, bus, slot);
1161         return NULL;
1162 }
1163
1164 static int pci9111_attach(struct comedi_device *dev,
1165                           struct comedi_devconfig *it)
1166 {
1167         struct pci9111_private_data *dev_private;
1168         struct pci_dev *pcidev;
1169         struct comedi_subdevice *s;
1170         unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
1171         int ret;
1172         const struct pci9111_board *board;
1173
1174         ret = alloc_private(dev, sizeof(*dev_private));
1175         if (ret)
1176                 return ret;
1177         dev_private = dev->private;
1178
1179         /*  Probe the device to determine what device in the series it is. */
1180
1181         printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n",
1182                                                                 dev->minor);
1183
1184         pcidev = pci9111_find_pci(dev, it);
1185         if (!pcidev)
1186                 return -EIO;
1187         comedi_set_hw_dev(dev, &pcidev->dev);
1188         board = (struct pci9111_board *)dev->board_ptr;
1189
1190         /*  TODO: Warn about non-tested boards. */
1191
1192         /*  Read local configuration register base address
1193          *  [PCI_BASE_ADDRESS #1]. */
1194
1195         lcr_io_base = pci_resource_start(pcidev, 1);
1196         lcr_io_range = pci_resource_len(pcidev, 1);
1197
1198         printk
1199             ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
1200              dev->minor, lcr_io_base, lcr_io_range);
1201
1202         /*  Enable PCI device and request regions */
1203         if (comedi_pci_enable(pcidev, PCI9111_DRIVER_NAME) < 0) {
1204                 printk
1205                     ("comedi%d: Failed to enable PCI device and request regions\n",
1206                      dev->minor);
1207                 return -EIO;
1208         }
1209         /*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
1210
1211         io_base = pci_resource_start(pcidev, 2);
1212         io_range = pci_resource_len(pcidev, 2);
1213
1214         printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
1215                dev->minor, io_base, io_range);
1216
1217         dev->iobase = io_base;
1218         dev->board_name = board->name;
1219         dev_private->io_range = io_range;
1220         dev_private->is_valid = 0;
1221         dev_private->lcr_io_base = lcr_io_base;
1222         dev_private->lcr_io_range = lcr_io_range;
1223
1224         pci9111_reset(dev);
1225
1226         /*  Irq setup */
1227
1228         dev->irq = 0;
1229         if (pcidev->irq > 0) {
1230                 dev->irq = pcidev->irq;
1231
1232                 if (request_irq(dev->irq, pci9111_interrupt,
1233                                 IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
1234                         printk(KERN_ERR
1235                                 "comedi%d: unable to allocate irq  %u\n",
1236                                         dev->minor, dev->irq);
1237                         return -EINVAL;
1238                 }
1239         }
1240
1241         /*  TODO: Add external multiplexer setup (according to option[2]). */
1242
1243         ret = comedi_alloc_subdevices(dev, 4);
1244         if (ret)
1245                 return ret;
1246
1247         s = &dev->subdevices[0];
1248         dev->read_subdev = s;
1249
1250         s->type = COMEDI_SUBD_AI;
1251         s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
1252
1253         /*  TODO: Add external multiplexer data */
1254         /*     if (devpriv->usemux) { s->n_chan = devpriv->usemux; } */
1255         /*     else { s->n_chan = this_board->n_aichan; } */
1256
1257         s->n_chan = board->ai_channel_nbr;
1258         s->maxdata = board->ai_resolution_mask;
1259         s->len_chanlist = board->ai_channel_nbr;
1260         s->range_table = board->ai_range_list;
1261         s->cancel = pci9111_ai_cancel;
1262         s->insn_read = pci9111_ai_insn_read;
1263         s->do_cmdtest = pci9111_ai_do_cmd_test;
1264         s->do_cmd = pci9111_ai_do_cmd;
1265         s->munge = pci9111_ai_munge;
1266
1267         s = &dev->subdevices[1];
1268         s->type = COMEDI_SUBD_AO;
1269         s->subdev_flags = SDF_WRITABLE | SDF_COMMON;
1270         s->n_chan = board->ao_channel_nbr;
1271         s->maxdata = board->ao_maxdata;
1272         s->len_chanlist = board->ao_channel_nbr;
1273         s->range_table = board->ao_range_list;
1274         s->insn_write = pci9111_ao_insn_write;
1275         s->insn_read = pci9111_ao_insn_read;
1276
1277         s = &dev->subdevices[2];
1278         s->type = COMEDI_SUBD_DI;
1279         s->subdev_flags = SDF_READABLE;
1280         s->n_chan = PCI9111_DI_CHANNEL_NBR;
1281         s->maxdata = 1;
1282         s->range_table = &range_digital;
1283         s->insn_bits = pci9111_di_insn_bits;
1284
1285         s = &dev->subdevices[3];
1286         s->type = COMEDI_SUBD_DO;
1287         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1288         s->n_chan = PCI9111_DO_CHANNEL_NBR;
1289         s->maxdata = 1;
1290         s->range_table = &range_digital;
1291         s->insn_bits = pci9111_do_insn_bits;
1292
1293         dev_private->is_valid = 1;
1294
1295         return 0;
1296 }
1297
1298 static void pci9111_detach(struct comedi_device *dev)
1299 {
1300         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1301         struct pci9111_private_data *dev_private = dev->private;
1302
1303         if (dev_private) {
1304                 if (dev_private->is_valid)
1305                         pci9111_reset(dev);
1306         }
1307         if (dev->irq != 0)
1308                 free_irq(dev->irq, dev);
1309         if (pcidev) {
1310                 if (dev->iobase)
1311                         comedi_pci_disable(pcidev);
1312                 pci_dev_put(pcidev);
1313         }
1314 }
1315
1316 static struct comedi_driver adl_pci9111_driver = {
1317         .driver_name    = "adl_pci9111",
1318         .module         = THIS_MODULE,
1319         .attach         = pci9111_attach,
1320         .detach         = pci9111_detach,
1321 };
1322
1323 static int __devinit pci9111_pci_probe(struct pci_dev *dev,
1324                                        const struct pci_device_id *ent)
1325 {
1326         return comedi_pci_auto_config(dev, &adl_pci9111_driver);
1327 }
1328
1329 static void __devexit pci9111_pci_remove(struct pci_dev *dev)
1330 {
1331         comedi_pci_auto_unconfig(dev);
1332 }
1333
1334 static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
1335         { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
1336         /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
1337         { 0 }
1338 };
1339 MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
1340
1341 static struct pci_driver adl_pci9111_pci_driver = {
1342         .name           = "adl_pci9111",
1343         .id_table       = pci9111_pci_table,
1344         .probe          = pci9111_pci_probe,
1345         .remove         = __devexit_p(pci9111_pci_remove),
1346 };
1347 module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
1348
1349 MODULE_AUTHOR("Comedi http://www.comedi.org");
1350 MODULE_DESCRIPTION("Comedi low-level driver");
1351 MODULE_LICENSE("GPL");