staging: comedi: adl_pci9111: remove pci9111_ai_channel_[gs]et macros
[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: not applicable, uses PCI auto config
51 */
52
53 /*
54 CHANGELOG:
55
56 2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
57 a multiple of chanlist_len*convert_arg.
58 2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
59 2002/02/18 Added external trigger support for analog input.
60
61 TODO:
62
63         - Really test implemented functionality.
64         - Add support for the PCI-9111DG with a probe routine to identify
65           the card type (perhaps with the help of the channel number readback
66           of the A/D Data register).
67         - Add external multiplexer support.
68
69 */
70
71 #include "../comedidev.h"
72
73 #include <linux/delay.h>
74 #include <linux/interrupt.h>
75
76 #include "8253.h"
77 #include "comedi_fc.h"
78
79 #define PCI9111_DRIVER_NAME     "adl_pci9111"
80 #define PCI9111_HR_DEVICE_ID    0x9111
81
82 #define PCI9111_FIFO_HALF_SIZE  512
83
84 #define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS    10000
85
86 #define PCI9111_RANGE_SETTING_DELAY             10
87 #define PCI9111_AI_INSTANT_READ_UDELAY_US       2
88 #define PCI9111_AI_INSTANT_READ_TIMEOUT         100
89
90 #define PCI9111_8254_CLOCK_PERIOD_NS            500
91
92 /* IO address map */
93
94 #define PCI9111_AI_FIFO_REG                             0x00
95 #define PCI9111_AO_REG                                  0x00
96 #define PCI9111_DIO_REG                                 0x02
97 #define PCI9111_REGISTER_EXTENDED_IO_PORTS              0x04
98 #define PCI9111_AI_CHANNEL_REG                          0x06
99 #define PCI9111_REGISTER_AD_CHANNEL_READBACK            0x06
100 #define PCI9111_AI_RANGE_REG                            0x08
101 #define PCI9111_RANGE_STATUS_REG                        0x08
102 #define PCI9111_REGISTER_TRIGGER_MODE_CONTROL           0x0A
103 #define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK     0x0A
104 #define PCI9111_REGISTER_SOFTWARE_TRIGGER               0x0E
105 #define PCI9111_REGISTER_INTERRUPT_CONTROL              0x0C
106 #define PCI9111_8254_BASE_REG                           0x40
107 #define PCI9111_REGISTER_INTERRUPT_CLEAR                0x48
108
109 #define PCI9111_TRIGGER_MASK                            0x0F
110 #define PCI9111_PTRG_OFF                                (0 << 3)
111 #define PCI9111_PTRG_ON                                 (1 << 3)
112 #define PCI9111_EITS_EXTERNAL                           (1 << 2)
113 #define PCI9111_EITS_INTERNAL                           (0 << 2)
114 #define PCI9111_TPST_SOFTWARE_TRIGGER                   (0 << 1)
115 #define PCI9111_TPST_TIMER_PACER                        (1 << 1)
116 #define PCI9111_ASCAN_ON                                (1 << 0)
117 #define PCI9111_ASCAN_OFF                               (0 << 0)
118
119 #define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
120 #define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL          (1 << 0)
121 #define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK              (0 << 1)
122 #define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG                 (1 << 1)
123 #define PCI9111_FFEN_SET_FIFO_ENABLE                    (0 << 2)
124 #define PCI9111_FFEN_SET_FIFO_DISABLE                   (1 << 2)
125
126 #define PCI9111_RANGE_MASK                              0x07
127 #define PCI9111_FIFO_EMPTY_MASK                         0x10
128 #define PCI9111_FIFO_HALF_FULL_MASK                     0x20
129 #define PCI9111_FIFO_FULL_MASK                          0x40
130 #define PCI9111_AD_BUSY_MASK                            0x80
131
132 /*
133  * Define inlined function
134  */
135
136 #define pci9111_trigger_and_autoscan_get() \
137         (inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
138
139 #define pci9111_trigger_and_autoscan_set(flags) \
140         outb(flags, dev->iobase + PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
141
142 #define pci9111_interrupt_and_fifo_get() \
143         ((inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
144                 >> 4) & 0x03)
145
146 #define pci9111_interrupt_and_fifo_set(flags) \
147         outb(flags, dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL)
148
149 #define pci9111_interrupt_clear() \
150         outb(0, dev->iobase + PCI9111_REGISTER_INTERRUPT_CLEAR)
151
152 #define pci9111_software_trigger() \
153         outb(0, dev->iobase + PCI9111_REGISTER_SOFTWARE_TRIGGER)
154
155 #define pci9111_fifo_reset() do { \
156         outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
157                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
158         outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
159                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
160         outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
161                 dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
162         } while (0)
163
164 #define pci9111_is_fifo_full() \
165         ((inb(dev->iobase + PCI9111_RANGE_STATUS_REG)& \
166                 PCI9111_FIFO_FULL_MASK) == 0)
167
168 #define pci9111_is_fifo_half_full() \
169         ((inb(dev->iobase + PCI9111_RANGE_STATUS_REG)& \
170                 PCI9111_FIFO_HALF_FULL_MASK) == 0)
171
172 #define pci9111_is_fifo_empty() \
173         ((inb(dev->iobase + PCI9111_RANGE_STATUS_REG)& \
174                 PCI9111_FIFO_EMPTY_MASK) == 0)
175
176 static const struct comedi_lrange pci9111_hr_ai_range = {
177         5,
178         {
179          BIP_RANGE(10),
180          BIP_RANGE(5),
181          BIP_RANGE(2.5),
182          BIP_RANGE(1.25),
183          BIP_RANGE(0.625)
184          }
185 };
186
187 /*  Private data structure */
188
189 struct pci9111_private_data {
190         unsigned long lcr_io_base; /* Local configuration register base
191                                     * address */
192
193         int stop_counter;
194         int stop_is_none;
195
196         unsigned int scan_delay;
197         unsigned int chanlist_len;
198         unsigned int chunk_counter;
199         unsigned int chunk_num_samples;
200
201         int ao_readback;        /*  Last written analog output data */
202
203         unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
204                                        * pacer */
205         unsigned int timer_divisor_2;
206
207         int is_valid;           /*  Is device valid */
208
209         short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
210 };
211
212 /*  ------------------------------------------------------------------ */
213 /*  PLX9050 SECTION */
214 /*  ------------------------------------------------------------------ */
215
216 #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
217
218 #define PLX9050_LINTI1_ENABLE           (1 << 0)
219 #define PLX9050_LINTI1_ACTIVE_HIGH      (1 << 1)
220 #define PLX9050_LINTI1_STATUS           (1 << 2)
221 #define PLX9050_LINTI2_ENABLE           (1 << 3)
222 #define PLX9050_LINTI2_ACTIVE_HIGH      (1 << 4)
223 #define PLX9050_LINTI2_STATUS           (1 << 5)
224 #define PLX9050_PCI_INTERRUPT_ENABLE    (1 << 6)
225 #define PLX9050_SOFTWARE_INTERRUPT      (1 << 7)
226
227 static void plx9050_interrupt_control(unsigned long io_base,
228                                       bool LINTi1_enable,
229                                       bool LINTi1_active_high,
230                                       bool LINTi2_enable,
231                                       bool LINTi2_active_high,
232                                       bool interrupt_enable)
233 {
234         int flags = 0;
235
236         if (LINTi1_enable)
237                 flags |= PLX9050_LINTI1_ENABLE;
238         if (LINTi1_active_high)
239                 flags |= PLX9050_LINTI1_ACTIVE_HIGH;
240         if (LINTi2_enable)
241                 flags |= PLX9050_LINTI2_ENABLE;
242         if (LINTi2_active_high)
243                 flags |= PLX9050_LINTI2_ACTIVE_HIGH;
244
245         if (interrupt_enable)
246                 flags |= PLX9050_PCI_INTERRUPT_ENABLE;
247
248         outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
249 }
250
251 /*  ------------------------------------------------------------------ */
252 /*  MISCELLANEOUS SECTION */
253 /*  ------------------------------------------------------------------ */
254
255 /*  8254 timer */
256
257 static void pci9111_timer_set(struct comedi_device *dev)
258 {
259         struct pci9111_private_data *dev_private = dev->private;
260         unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
261
262         i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
263         i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
264         i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
265
266         udelay(1);
267
268         i8254_write(timer_base, 1, 2, dev_private->timer_divisor_2);
269         i8254_write(timer_base, 1, 1, dev_private->timer_divisor_1);
270 }
271
272 enum pci9111_trigger_sources {
273         software,
274         timer_pacer,
275         external
276 };
277
278 static void pci9111_trigger_source_set(struct comedi_device *dev,
279                                        enum pci9111_trigger_sources source)
280 {
281         int flags;
282
283         flags = pci9111_trigger_and_autoscan_get() & 0x09;
284
285         switch (source) {
286         case software:
287                 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
288                 break;
289
290         case timer_pacer:
291                 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
292                 break;
293
294         case external:
295                 flags |= PCI9111_EITS_EXTERNAL;
296                 break;
297         }
298
299         pci9111_trigger_and_autoscan_set(flags);
300 }
301
302 static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
303 {
304         int flags;
305
306         flags = pci9111_trigger_and_autoscan_get() & 0x07;
307
308         if (pretrigger)
309                 flags |= PCI9111_PTRG_ON;
310
311         pci9111_trigger_and_autoscan_set(flags);
312 }
313
314 static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
315 {
316         int flags;
317
318         flags = pci9111_trigger_and_autoscan_get() & 0x0e;
319
320         if (autoscan)
321                 flags |= PCI9111_ASCAN_ON;
322
323         pci9111_trigger_and_autoscan_set(flags);
324 }
325
326 enum pci9111_ISC0_sources {
327         irq_on_eoc,
328         irq_on_fifo_half_full
329 };
330
331 enum pci9111_ISC1_sources {
332         irq_on_timer_tick,
333         irq_on_external_trigger
334 };
335
336 static void pci9111_interrupt_source_set(struct comedi_device *dev,
337                                          enum pci9111_ISC0_sources irq_0_source,
338                                          enum pci9111_ISC1_sources irq_1_source)
339 {
340         int flags;
341
342         flags = pci9111_interrupt_and_fifo_get() & 0x04;
343
344         if (irq_0_source == irq_on_fifo_half_full)
345                 flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
346
347         if (irq_1_source == irq_on_external_trigger)
348                 flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
349
350         pci9111_interrupt_and_fifo_set(flags);
351 }
352
353 /*  ------------------------------------------------------------------ */
354 /*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
355 /*  ------------------------------------------------------------------ */
356
357 /*  Cancel analog input autoscan */
358
359 static int pci9111_ai_cancel(struct comedi_device *dev,
360                              struct comedi_subdevice *s)
361 {
362         struct pci9111_private_data *dev_private = dev->private;
363
364         /*  Disable interrupts */
365
366         plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
367                                   true, false);
368
369         pci9111_trigger_source_set(dev, software);
370
371         pci9111_autoscan_set(dev, false);
372
373         pci9111_fifo_reset();
374
375         return 0;
376 }
377
378 /*  Test analog input command */
379
380 #define pci9111_check_trigger_src(src, flags)   do {                    \
381                 tmp = src;                                              \
382                 src &= flags;                                           \
383                 if (!src || tmp != src)                                 \
384                         error++;                                        \
385         } while (false);
386
387 static int
388 pci9111_ai_do_cmd_test(struct comedi_device *dev,
389                        struct comedi_subdevice *s, struct comedi_cmd *cmd)
390 {
391         struct pci9111_private_data *dev_private = dev->private;
392         int tmp;
393         int error = 0;
394         int range, reference;
395         int i;
396
397         /*  Step 1 : check if trigger are trivialy valid */
398
399         pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
400         pci9111_check_trigger_src(cmd->scan_begin_src,
401                                   TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
402         pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
403         pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
404         pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
405
406         if (error)
407                 return 1;
408
409         /*  step 2 : make sure trigger sources are unique and mutually
410          *  compatible */
411
412         if (cmd->start_src != TRIG_NOW)
413                 error++;
414
415         if ((cmd->scan_begin_src != TRIG_TIMER) &&
416             (cmd->scan_begin_src != TRIG_FOLLOW) &&
417             (cmd->scan_begin_src != TRIG_EXT))
418                 error++;
419
420         if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
421                 error++;
422         if ((cmd->convert_src == TRIG_TIMER) &&
423             !((cmd->scan_begin_src == TRIG_TIMER) ||
424               (cmd->scan_begin_src == TRIG_FOLLOW)))
425                 error++;
426         if ((cmd->convert_src == TRIG_EXT) &&
427             !((cmd->scan_begin_src == TRIG_EXT) ||
428               (cmd->scan_begin_src == TRIG_FOLLOW)))
429                 error++;
430
431
432         if (cmd->scan_end_src != TRIG_COUNT)
433                 error++;
434         if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
435                 error++;
436
437         if (error)
438                 return 2;
439
440         /*  Step 3 : make sure arguments are trivialy compatible */
441
442         if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
443                 cmd->start_arg = 0;
444                 error++;
445         }
446
447         if ((cmd->convert_src == TRIG_TIMER) &&
448             (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
449                 cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
450                 error++;
451         }
452         if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
453                 cmd->convert_arg = 0;
454                 error++;
455         }
456
457         if ((cmd->scan_begin_src == TRIG_TIMER) &&
458             (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
459                 cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
460                 error++;
461         }
462         if ((cmd->scan_begin_src == TRIG_FOLLOW)
463             && (cmd->scan_begin_arg != 0)) {
464                 cmd->scan_begin_arg = 0;
465                 error++;
466         }
467         if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
468                 cmd->scan_begin_arg = 0;
469                 error++;
470         }
471
472         if ((cmd->scan_end_src == TRIG_COUNT) &&
473             (cmd->scan_end_arg != cmd->chanlist_len)) {
474                 cmd->scan_end_arg = cmd->chanlist_len;
475                 error++;
476         }
477
478         if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
479                 cmd->stop_arg = 1;
480                 error++;
481         }
482         if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
483                 cmd->stop_arg = 0;
484                 error++;
485         }
486
487         if (error)
488                 return 3;
489
490         /*  Step 4 : fix up any arguments */
491
492         if (cmd->convert_src == TRIG_TIMER) {
493                 tmp = cmd->convert_arg;
494                 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
495                                                &(dev_private->timer_divisor_1),
496                                                &(dev_private->timer_divisor_2),
497                                                &(cmd->convert_arg),
498                                                cmd->flags & TRIG_ROUND_MASK);
499                 if (tmp != cmd->convert_arg)
500                         error++;
501         }
502         /*  There's only one timer on this card, so the scan_begin timer must */
503         /*  be a multiple of chanlist_len*convert_arg */
504
505         if (cmd->scan_begin_src == TRIG_TIMER) {
506
507                 unsigned int scan_begin_min;
508                 unsigned int scan_begin_arg;
509                 unsigned int scan_factor;
510
511                 scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
512
513                 if (cmd->scan_begin_arg != scan_begin_min) {
514                         if (scan_begin_min < cmd->scan_begin_arg) {
515                                 scan_factor =
516                                     cmd->scan_begin_arg / scan_begin_min;
517                                 scan_begin_arg = scan_factor * scan_begin_min;
518                                 if (cmd->scan_begin_arg != scan_begin_arg) {
519                                         cmd->scan_begin_arg = scan_begin_arg;
520                                         error++;
521                                 }
522                         } else {
523                                 cmd->scan_begin_arg = scan_begin_min;
524                                 error++;
525                         }
526                 }
527         }
528
529         if (error)
530                 return 4;
531
532         /*  Step 5 : check channel list */
533
534         if (cmd->chanlist) {
535
536                 range = CR_RANGE(cmd->chanlist[0]);
537                 reference = CR_AREF(cmd->chanlist[0]);
538
539                 if (cmd->chanlist_len > 1) {
540                         for (i = 0; i < cmd->chanlist_len; i++) {
541                                 if (CR_CHAN(cmd->chanlist[i]) != i) {
542                                         comedi_error(dev,
543                                                      "entries in chanlist must be consecutive "
544                                                      "channels,counting upwards from 0\n");
545                                         error++;
546                                 }
547                                 if (CR_RANGE(cmd->chanlist[i]) != range) {
548                                         comedi_error(dev,
549                                                      "entries in chanlist must all have the same gain\n");
550                                         error++;
551                                 }
552                                 if (CR_AREF(cmd->chanlist[i]) != reference) {
553                                         comedi_error(dev,
554                                                      "entries in chanlist must all have the same reference\n");
555                                         error++;
556                                 }
557                         }
558                 }
559         }
560
561         if (error)
562                 return 5;
563
564         return 0;
565
566 }
567
568 /*  Analog input command */
569
570 static int pci9111_ai_do_cmd(struct comedi_device *dev,
571                              struct comedi_subdevice *s)
572 {
573         struct pci9111_private_data *dev_private = dev->private;
574         struct comedi_cmd *async_cmd = &s->async->cmd;
575
576         if (!dev->irq) {
577                 comedi_error(dev,
578                              "no irq assigned for PCI9111, cannot do hardware conversion");
579                 return -1;
580         }
581         /*  Set channel scan limit */
582         /*  PCI9111 allows only scanning from channel 0 to channel n */
583         /*  TODO: handle the case of an external multiplexer */
584
585         if (async_cmd->chanlist_len > 1) {
586                 outb(async_cmd->chanlist_len - 1,
587                         dev->iobase + PCI9111_AI_CHANNEL_REG);
588                 pci9111_autoscan_set(dev, true);
589         } else {
590                 outb(CR_CHAN(async_cmd->chanlist[0]),
591                         dev->iobase + PCI9111_AI_CHANNEL_REG);
592                 pci9111_autoscan_set(dev, false);
593         }
594
595         /*  Set gain */
596         /*  This is the same gain on every channel */
597
598         outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_RANGE_MASK,
599                 dev->iobase + PCI9111_AI_RANGE_REG);
600
601         /* Set counter */
602
603         switch (async_cmd->stop_src) {
604         case TRIG_COUNT:
605                 dev_private->stop_counter =
606                     async_cmd->stop_arg * async_cmd->chanlist_len;
607                 dev_private->stop_is_none = 0;
608                 break;
609
610         case TRIG_NONE:
611                 dev_private->stop_counter = 0;
612                 dev_private->stop_is_none = 1;
613                 break;
614
615         default:
616                 comedi_error(dev, "Invalid stop trigger");
617                 return -1;
618         }
619
620         /*  Set timer pacer */
621
622         dev_private->scan_delay = 0;
623         switch (async_cmd->convert_src) {
624         case TRIG_TIMER:
625                 i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
626                                                &(dev_private->timer_divisor_1),
627                                                &(dev_private->timer_divisor_2),
628                                                &(async_cmd->convert_arg),
629                                                async_cmd->
630                                                flags & TRIG_ROUND_MASK);
631
632                 pci9111_trigger_source_set(dev, software);
633                 pci9111_timer_set(dev);
634                 pci9111_fifo_reset();
635                 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
636                                              irq_on_timer_tick);
637                 pci9111_trigger_source_set(dev, timer_pacer);
638                 plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
639                                           false, true, true);
640
641                 if (async_cmd->scan_begin_src == TRIG_TIMER) {
642                         dev_private->scan_delay =
643                                 (async_cmd->scan_begin_arg /
644                                  (async_cmd->convert_arg *
645                                   async_cmd->chanlist_len)) - 1;
646                 }
647
648                 break;
649
650         case TRIG_EXT:
651
652                 pci9111_trigger_source_set(dev, external);
653                 pci9111_fifo_reset();
654                 pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
655                                              irq_on_timer_tick);
656                 plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
657                                           false, true, true);
658
659                 break;
660
661         default:
662                 comedi_error(dev, "Invalid convert trigger");
663                 return -1;
664         }
665
666         dev_private->stop_counter *= (1 + dev_private->scan_delay);
667         dev_private->chanlist_len = async_cmd->chanlist_len;
668         dev_private->chunk_counter = 0;
669         dev_private->chunk_num_samples =
670             dev_private->chanlist_len * (1 + dev_private->scan_delay);
671
672         return 0;
673 }
674
675 static void pci9111_ai_munge(struct comedi_device *dev,
676                              struct comedi_subdevice *s, void *data,
677                              unsigned int num_bytes,
678                              unsigned int start_chan_index)
679 {
680         short *array = data;
681         unsigned int maxdata = s->maxdata;
682         unsigned int invert = (maxdata + 1) >> 1;
683         unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
684         unsigned int num_samples = num_bytes / sizeof(short);
685         unsigned int i;
686
687         for (i = 0; i < num_samples; i++)
688                 array[i] = ((array[i] >> shift) & maxdata) ^ invert;
689 }
690
691 /*  ------------------------------------------------------------------ */
692 /*  INTERRUPT SECTION */
693 /*  ------------------------------------------------------------------ */
694
695 static irqreturn_t pci9111_interrupt(int irq, void *p_device)
696 {
697         struct comedi_device *dev = p_device;
698         struct pci9111_private_data *dev_private = dev->private;
699         struct comedi_subdevice *s = dev->read_subdev;
700         struct comedi_async *async;
701         unsigned long irq_flags;
702         unsigned char intcsr;
703
704         if (!dev->attached) {
705                 /*  Ignore interrupt before device fully attached. */
706                 /*  Might not even have allocated subdevices yet! */
707                 return IRQ_NONE;
708         }
709
710         async = s->async;
711
712         spin_lock_irqsave(&dev->spinlock, irq_flags);
713
714         /*  Check if we are source of interrupt */
715         intcsr = inb(dev_private->lcr_io_base +
716                      PLX9050_REGISTER_INTERRUPT_CONTROL);
717         if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
718               && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
719                    == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
720                   || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
721                       == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
722                 /*  Not the source of the interrupt. */
723                 /*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
724                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
725                 return IRQ_NONE;
726         }
727
728         if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
729             (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
730                 /*  Interrupt comes from fifo_half-full signal */
731
732                 if (pci9111_is_fifo_full()) {
733                         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
734                         comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
735                         pci9111_interrupt_clear();
736                         pci9111_ai_cancel(dev, s);
737                         async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
738                         comedi_event(dev, s);
739
740                         return IRQ_HANDLED;
741                 }
742
743                 if (pci9111_is_fifo_half_full()) {
744                         unsigned int num_samples;
745                         unsigned int bytes_written = 0;
746
747                         num_samples =
748                             PCI9111_FIFO_HALF_SIZE >
749                             dev_private->stop_counter
750                             && !dev_private->
751                             stop_is_none ? dev_private->stop_counter :
752                             PCI9111_FIFO_HALF_SIZE;
753                         insw(dev->iobase + PCI9111_AI_FIFO_REG,
754                              dev_private->ai_bounce_buffer, num_samples);
755
756                         if (dev_private->scan_delay < 1) {
757                                 bytes_written =
758                                     cfc_write_array_to_buffer(s,
759                                                               dev_private->
760                                                               ai_bounce_buffer,
761                                                               num_samples *
762                                                               sizeof(short));
763                         } else {
764                                 int position = 0;
765                                 int to_read;
766
767                                 while (position < num_samples) {
768                                         if (dev_private->chunk_counter <
769                                             dev_private->chanlist_len) {
770                                                 to_read =
771                                                     dev_private->chanlist_len -
772                                                     dev_private->chunk_counter;
773
774                                                 if (to_read >
775                                                     num_samples - position)
776                                                         to_read =
777                                                             num_samples -
778                                                             position;
779
780                                                 bytes_written +=
781                                                     cfc_write_array_to_buffer
782                                                     (s,
783                                                      dev_private->ai_bounce_buffer
784                                                      + position,
785                                                      to_read * sizeof(short));
786                                         } else {
787                                                 to_read =
788                                                     dev_private->chunk_num_samples
789                                                     -
790                                                     dev_private->chunk_counter;
791                                                 if (to_read >
792                                                     num_samples - position)
793                                                         to_read =
794                                                             num_samples -
795                                                             position;
796
797                                                 bytes_written +=
798                                                     sizeof(short) * to_read;
799                                         }
800
801                                         position += to_read;
802                                         dev_private->chunk_counter += to_read;
803
804                                         if (dev_private->chunk_counter >=
805                                             dev_private->chunk_num_samples)
806                                                 dev_private->chunk_counter = 0;
807                                 }
808                         }
809
810                         dev_private->stop_counter -=
811                             bytes_written / sizeof(short);
812                 }
813         }
814
815         if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
816                 async->events |= COMEDI_CB_EOA;
817                 pci9111_ai_cancel(dev, s);
818         }
819
820         /* Very important, otherwise another interrupt request will be inserted
821          * and will cause driver hangs on processing interrupt event. */
822
823         pci9111_interrupt_clear();
824
825         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
826
827         comedi_event(dev, s);
828
829         return IRQ_HANDLED;
830 }
831
832 /*  ------------------------------------------------------------------ */
833 /*  INSTANT ANALOG INPUT OUTPUT SECTION */
834 /*  ------------------------------------------------------------------ */
835
836 /*  analog instant input */
837
838 static int pci9111_ai_insn_read(struct comedi_device *dev,
839                                 struct comedi_subdevice *s,
840                                 struct comedi_insn *insn, unsigned int *data)
841 {
842         unsigned int chan = CR_CHAN(insn->chanspec);
843         unsigned int range = CR_RANGE(insn->chanspec);
844         unsigned int maxdata = s->maxdata;
845         unsigned int invert = (maxdata + 1) >> 1;
846         unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
847         unsigned int current_range;
848         int timeout;
849         int i;
850
851         outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
852
853         current_range = inb(dev->iobase + PCI9111_RANGE_STATUS_REG);
854         if ((current_range & PCI9111_RANGE_MASK) != range) {
855                 outb(range & PCI9111_RANGE_MASK,
856                         dev->iobase + PCI9111_AI_RANGE_REG);
857         }
858
859         pci9111_fifo_reset();
860
861         for (i = 0; i < insn->n; i++) {
862                 pci9111_software_trigger();
863
864                 timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
865
866                 while (timeout--) {
867                         if (!pci9111_is_fifo_empty())
868                                 goto conversion_done;
869                 }
870
871                 comedi_error(dev, "A/D read timeout");
872                 data[i] = 0;
873                 pci9111_fifo_reset();
874                 return -ETIME;
875
876 conversion_done:
877
878                 data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG);
879                 data[i] = ((data[i] >> shift) & maxdata) ^ invert;
880         }
881
882         return i;
883 }
884
885 static int pci9111_ao_insn_write(struct comedi_device *dev,
886                                  struct comedi_subdevice *s,
887                                  struct comedi_insn *insn,
888                                  unsigned int *data)
889 {
890         struct pci9111_private_data *dev_private = dev->private;
891         unsigned int val = 0;
892         int i;
893
894         for (i = 0; i < insn->n; i++) {
895                 val = data[i];
896                 outw(val, dev->iobase + PCI9111_AO_REG);
897         }
898         dev_private->ao_readback = val;
899
900         return insn->n;
901 }
902
903 static int pci9111_ao_insn_read(struct comedi_device *dev,
904                                 struct comedi_subdevice *s,
905                                 struct comedi_insn *insn,
906                                 unsigned int *data)
907 {
908         struct pci9111_private_data *dev_private = dev->private;
909         int i;
910
911         for (i = 0; i < insn->n; i++)
912                 data[i] = dev_private->ao_readback;
913
914         return insn->n;
915 }
916
917 static int pci9111_di_insn_bits(struct comedi_device *dev,
918                                 struct comedi_subdevice *s,
919                                 struct comedi_insn *insn,
920                                 unsigned int *data)
921 {
922         data[1] = inw(dev->iobase + PCI9111_DIO_REG);
923
924         return insn->n;
925 }
926
927 static int pci9111_do_insn_bits(struct comedi_device *dev,
928                                 struct comedi_subdevice *s,
929                                 struct comedi_insn *insn,
930                                 unsigned int *data)
931 {
932         unsigned int mask = data[0];
933         unsigned int bits = data[1];
934
935         if (mask) {
936                 s->state &= ~mask;
937                 s->state |= (bits & mask);
938
939                 outw(s->state, dev->iobase + PCI9111_DIO_REG);
940         }
941
942         data[1] = s->state;
943
944         return insn->n;
945 }
946
947 /*  ------------------------------------------------------------------ */
948 /*  INITIALISATION SECTION */
949 /*  ------------------------------------------------------------------ */
950
951 /*  Reset device */
952
953 static int pci9111_reset(struct comedi_device *dev)
954 {
955         struct pci9111_private_data *dev_private = dev->private;
956
957         /*  Set trigger source to software */
958
959         plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
960                                   true, false);
961
962         pci9111_trigger_source_set(dev, software);
963         pci9111_pretrigger_set(dev, false);
964         pci9111_autoscan_set(dev, false);
965
966         /*  Reset 8254 chip */
967
968         dev_private->timer_divisor_1 = 0;
969         dev_private->timer_divisor_2 = 0;
970
971         pci9111_timer_set(dev);
972
973         return 0;
974 }
975
976 static int pci9111_attach_pci(struct comedi_device *dev,
977                               struct pci_dev *pcidev)
978 {
979         struct pci9111_private_data *dev_private;
980         struct comedi_subdevice *s;
981         int ret;
982
983         comedi_set_hw_dev(dev, &pcidev->dev);
984         dev->board_name = dev->driver->driver_name;
985
986         ret = alloc_private(dev, sizeof(*dev_private));
987         if (ret)
988                 return ret;
989         dev_private = dev->private;
990
991         ret = comedi_pci_enable(pcidev, dev->board_name);
992         if (ret)
993                 return ret;
994         dev_private->lcr_io_base = pci_resource_start(pcidev, 1);
995         dev->iobase = pci_resource_start(pcidev, 2);
996
997         pci9111_reset(dev);
998
999         if (pcidev->irq > 0) {
1000                 ret = request_irq(dev->irq, pci9111_interrupt,
1001                                   IRQF_SHARED, dev->board_name, dev);
1002                 if (ret)
1003                         return ret;
1004                 dev->irq = pcidev->irq;
1005         }
1006
1007         ret = comedi_alloc_subdevices(dev, 4);
1008         if (ret)
1009                 return ret;
1010
1011         s = &dev->subdevices[0];
1012         dev->read_subdev = s;
1013         s->type         = COMEDI_SUBD_AI;
1014         s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
1015         s->n_chan       = 16;
1016         s->maxdata      = 0xffff;
1017         s->len_chanlist = 16;
1018         s->range_table  = &pci9111_hr_ai_range;
1019         s->cancel       = pci9111_ai_cancel;
1020         s->insn_read    = pci9111_ai_insn_read;
1021         s->do_cmdtest   = pci9111_ai_do_cmd_test;
1022         s->do_cmd       = pci9111_ai_do_cmd;
1023         s->munge        = pci9111_ai_munge;
1024
1025         s = &dev->subdevices[1];
1026         s->type         = COMEDI_SUBD_AO;
1027         s->subdev_flags = SDF_WRITABLE | SDF_COMMON;
1028         s->n_chan       = 1;
1029         s->maxdata      = 0x0fff;
1030         s->len_chanlist = 1;
1031         s->range_table  = &range_bipolar10;
1032         s->insn_write   = pci9111_ao_insn_write;
1033         s->insn_read    = pci9111_ao_insn_read;
1034
1035         s = &dev->subdevices[2];
1036         s->type         = COMEDI_SUBD_DI;
1037         s->subdev_flags = SDF_READABLE;
1038         s->n_chan       = 16;
1039         s->maxdata      = 1;
1040         s->range_table  = &range_digital;
1041         s->insn_bits    = pci9111_di_insn_bits;
1042
1043         s = &dev->subdevices[3];
1044         s->type         = COMEDI_SUBD_DO;
1045         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1046         s->n_chan       = 16;
1047         s->maxdata      = 1;
1048         s->range_table  = &range_digital;
1049         s->insn_bits    = pci9111_do_insn_bits;
1050
1051         dev_private->is_valid = 1;
1052
1053         dev_info(dev->class_dev, "%s attached\n", dev->board_name);
1054
1055         return 0;
1056 }
1057
1058 static void pci9111_detach(struct comedi_device *dev)
1059 {
1060         struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1061         struct pci9111_private_data *dev_private = dev->private;
1062
1063         if (dev_private) {
1064                 if (dev_private->is_valid)
1065                         pci9111_reset(dev);
1066         }
1067         if (dev->irq != 0)
1068                 free_irq(dev->irq, dev);
1069         if (pcidev) {
1070                 if (dev->iobase)
1071                         comedi_pci_disable(pcidev);
1072                 pci_dev_put(pcidev);
1073         }
1074 }
1075
1076 static struct comedi_driver adl_pci9111_driver = {
1077         .driver_name    = "adl_pci9111",
1078         .module         = THIS_MODULE,
1079         .attach_pci     = pci9111_attach_pci,
1080         .detach         = pci9111_detach,
1081 };
1082
1083 static int __devinit pci9111_pci_probe(struct pci_dev *dev,
1084                                        const struct pci_device_id *ent)
1085 {
1086         return comedi_pci_auto_config(dev, &adl_pci9111_driver);
1087 }
1088
1089 static void __devexit pci9111_pci_remove(struct pci_dev *dev)
1090 {
1091         comedi_pci_auto_unconfig(dev);
1092 }
1093
1094 static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
1095         { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
1096         /* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
1097         { 0 }
1098 };
1099 MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
1100
1101 static struct pci_driver adl_pci9111_pci_driver = {
1102         .name           = "adl_pci9111",
1103         .id_table       = pci9111_pci_table,
1104         .probe          = pci9111_pci_probe,
1105         .remove         = __devexit_p(pci9111_pci_remove),
1106 };
1107 module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
1108
1109 MODULE_AUTHOR("Comedi http://www.comedi.org");
1110 MODULE_DESCRIPTION("Comedi low-level driver");
1111 MODULE_LICENSE("GPL");