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