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