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