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