3 comedi/drivers/adl_pci9111.c
5 Hardware driver for PCI9111 ADLink cards:
9 Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
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.
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.
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.
28 Description: Adlink PCI-9111HR
29 Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
30 Devices: [ADLink] PCI-9111HR (adl_pci9111)
39 - ai_do_cmd mode with the following sources:
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
47 The scanned channels must be consecutive and start from 0. They must
48 all have the same range and aref.
50 Configuration options:
52 [0] - PCI bus number (optional)
53 [1] - PCI slot number (optional)
55 If bus/slot is not specified, the first available PCI
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.
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.
77 #include <linux/comedidev.h>
79 #include <linux/delay.h>
80 #include <linux/pci.h>
83 #include "comedi_fc.h"
85 #define PCI9111_DRIVER_NAME "adl_pci9111"
86 #define PCI9111_HR_DEVICE_ID 0x9111
88 // TODO: Add other pci9111 board id
90 #define PCI9111_IO_RANGE 0x0100
92 #define PCI9111_FIFO_HALF_SIZE 512
94 #define PCI9111_AI_CHANNEL_NBR 16
96 #define PCI9111_AI_RESOLUTION 12
97 #define PCI9111_AI_RESOLUTION_MASK 0x0FFF
98 #define PCI9111_AI_RESOLUTION_2_CMP_BIT 0x0800
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
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
112 #define PCI9111_RANGE_SETTING_DELAY 10
113 #define PCI9111_AI_INSTANT_READ_UDELAY_US 2
114 #define PCI9111_AI_INSTANT_READ_TIMEOUT 100
116 #define PCI9111_8254_CLOCK_PERIOD_NS 500
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
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
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)
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)
171 #define PCI9111_CHANNEL_MASK 0x0F
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
179 #define PCI9111_IO_BASE dev->iobase
182 * Define inlined function
185 #define pci9111_trigger_and_autoscan_get() \
186 (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
188 #define pci9111_trigger_and_autoscan_set(flags) \
189 outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
191 #define pci9111_interrupt_and_fifo_get() \
192 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)
194 #define pci9111_interrupt_and_fifo_set(flags) \
195 outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
197 #define pci9111_interrupt_clear() \
198 outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
200 #define pci9111_software_trigger() \
201 outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
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)
208 #define pci9111_is_fifo_full() \
209 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
210 PCI9111_FIFO_FULL_MASK)==0)
212 #define pci9111_is_fifo_half_full() \
213 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
214 PCI9111_FIFO_HALF_FULL_MASK)==0)
216 #define pci9111_is_fifo_empty() \
217 ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
218 PCI9111_FIFO_EMPTY_MASK)==0)
220 #define pci9111_ai_channel_set(channel) \
221 outb((channel)&PCI9111_CHANNEL_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
223 #define pci9111_ai_channel_get() \
224 inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK
226 #define pci9111_ai_range_set(range) \
227 outb((range)&PCI9111_RANGE_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
229 #define pci9111_ai_range_get() \
230 inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK
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
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
240 #define pci9111_ao_set_data(data) \
241 outw(data&PCI9111_AO_RESOLUTION_MASK,PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
243 #define pci9111_di_get_bits() \
244 inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
246 #define pci9111_do_set_bits(bits) \
247 outw(bits,PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
249 #define pci9111_8254_control_set(flags) \
250 outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
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)
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)
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)
265 // Function prototypes
268 static int pci9111_attach (comedi_device *dev,comedi_devconfig *it);
269 static int pci9111_detach (comedi_device *dev);
270 static void pci9111_ai_munge(comedi_device *dev, comedi_subdevice *s, void *data,
271 unsigned int num_bytes, unsigned int start_chan_index );
273 static comedi_lrange pci9111_hr_ai_range=
285 static struct pci_device_id pci9111_pci_table[] __devinitdata = {
286 { PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
287 //{ PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
290 MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
293 // Board specification structure
297 char *name; // driver name
299 int ai_channel_nbr; // num of A/D chans
300 int ao_channel_nbr; // num of D/A chans
301 int ai_resolution; // resolution of A/D
302 int ai_resolution_mask;
303 int ao_resolution; // resolution of D/A
304 int ao_resolution_mask;
305 comedi_lrange *ai_range_list; // rangelist for A/D
306 comedi_lrange *ao_range_list; // rangelist for D/A
307 unsigned int ai_acquisition_period_min_ns;
308 } pci9111_board_struct;
311 static pci9111_board_struct pci9111_boards[] =
315 device_id: PCI9111_HR_DEVICE_ID,
316 ai_channel_nbr: PCI9111_AI_CHANNEL_NBR,
317 ao_channel_nbr: PCI9111_AO_CHANNEL_NBR,
318 ai_resolution: PCI9111_HR_AI_RESOLUTION,
319 ai_resolution_mask: PCI9111_HR_AI_RESOLUTION_MASK,
320 ao_resolution: PCI9111_AO_RESOLUTION,
321 ao_resolution_mask: PCI9111_AO_RESOLUTION_MASK,
322 ai_range_list: &pci9111_hr_ai_range,
323 ao_range_list: &range_bipolar10,
324 ai_acquisition_period_min_ns: PCI9111_AI_ACQUISITION_PERIOD_MIN_NS
328 #define pci9111_board_nbr \
329 (sizeof(pci9111_boards)/sizeof(pci9111_board_struct))
331 static comedi_driver pci9111_driver=
333 driver_name: PCI9111_DRIVER_NAME,
335 attach: pci9111_attach,
336 detach: pci9111_detach,
337 num_names: pci9111_board_nbr,
338 board_name: (const char**)pci9111_boards,
339 offset: sizeof(pci9111_board_struct),
341 COMEDI_INITCLEANUP(pci9111_driver);
344 // Private data structure
349 struct pci_dev* pci_device;
350 unsigned long io_range; // PCI6503 io range
352 unsigned long lcr_io_base; // Local configuration register base address
353 unsigned long lcr_io_range;
358 unsigned int scan_delay;
359 unsigned int chanlist_len;
360 unsigned int chunk_counter;
361 unsigned int chunk_num_samples;
363 int ao_readback; // Last written analog output data
365 int timer_divisor_1; // Divisor values for the 8254 timer pacer
368 int is_valid; // Is device valid
370 sampl_t ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
372 pci9111_private_data_struct;
375 #define dev_private ((pci9111_private_data_struct *)dev->private)
377 // ------------------------------------------------------------------
381 // ------------------------------------------------------------------
383 #define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
385 #define PLX9050_LINTI1_ENABLE (1 << 0)
386 #define PLX9050_LINTI1_ACTIVE_HIGH (1 << 1)
387 #define PLX9050_LINTI1_STATUS (1 << 2)
388 #define PLX9050_LINTI2_ENABLE (1 << 3)
389 #define PLX9050_LINTI2_ACTIVE_HIGH (1 << 4)
390 #define PLX9050_LINTI2_STATUS (1 << 5)
391 #define PLX9050_PCI_INTERRUPT_ENABLE (1 << 6)
392 #define PLX9050_SOFTWARE_INTERRUPT (1 << 7)
394 static void plx9050_interrupt_control (unsigned long io_base,
396 bool LINTi1_active_high,
398 bool LINTi2_active_high,
399 bool interrupt_enable)
403 if (LINTi1_enable) flags |= PLX9050_LINTI1_ENABLE;
404 if (LINTi1_active_high) flags |= PLX9050_LINTI1_ACTIVE_HIGH;
405 if (LINTi2_enable) flags |= PLX9050_LINTI2_ENABLE;
406 if (LINTi2_active_high) flags |= PLX9050_LINTI2_ACTIVE_HIGH;
408 if (interrupt_enable) flags |= PLX9050_PCI_INTERRUPT_ENABLE;
410 outb (flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
413 // ------------------------------------------------------------------
415 // MISCELLANEOUS SECTION
417 // ------------------------------------------------------------------
423 static void pci9111_timer_set ( comedi_device * dev)
425 pci9111_8254_control_set ( PCI9111_8254_COUNTER_0|
426 PCI9111_8254_READ_LOAD_LSB_MSB|
428 PCI9111_8254_BINARY_COUNTER);
430 pci9111_8254_control_set ( PCI9111_8254_COUNTER_1|
431 PCI9111_8254_READ_LOAD_LSB_MSB|
433 PCI9111_8254_BINARY_COUNTER);
435 pci9111_8254_control_set ( PCI9111_8254_COUNTER_2|
436 PCI9111_8254_READ_LOAD_LSB_MSB|
438 PCI9111_8254_BINARY_COUNTER);
442 pci9111_8254_counter_2_set (dev_private->timer_divisor_2);
443 pci9111_8254_counter_1_set (dev_private->timer_divisor_1);
452 pci9111_trigger_sources;
454 static void pci9111_trigger_source_set (comedi_device *dev,
455 pci9111_trigger_sources source)
459 flags = pci9111_trigger_and_autoscan_get() & 0x09;
464 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
468 flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
472 flags |= PCI9111_EITS_EXTERNAL;
476 pci9111_trigger_and_autoscan_set (flags);
479 static void pci9111_pretrigger_set (comedi_device *dev,
484 flags = pci9111_trigger_and_autoscan_get () & 0x07;
486 if (pretrigger) flags |= PCI9111_PTRG_ON;
488 pci9111_trigger_and_autoscan_set (flags);
491 static void pci9111_autoscan_set (comedi_device *dev,
496 flags = pci9111_trigger_and_autoscan_get() & 0x0e;
498 if (autoscan) flags |= PCI9111_ASCAN_ON;
500 pci9111_trigger_and_autoscan_set (flags);
506 irq_on_fifo_half_full
508 pci9111_ISC0_sources;
513 irq_on_external_trigger
515 pci9111_ISC1_sources;
517 static void pci9111_interrupt_source_set (comedi_device *dev,
518 pci9111_ISC0_sources irq_0_source,
519 pci9111_ISC1_sources irq_1_source)
523 flags = pci9111_interrupt_and_fifo_get() & 0x04;
525 if (irq_0_source == irq_on_fifo_half_full)
526 flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
528 if (irq_1_source == irq_on_external_trigger)
529 flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
531 pci9111_interrupt_and_fifo_set (flags);
534 // ------------------------------------------------------------------
536 // HARDWARE TRIGGERED ANALOG INPUT SECTION
538 // ------------------------------------------------------------------
541 // Cancel analog input autoscan
544 #undef AI_DO_CMD_DEBUG
546 static int pci9111_ai_cancel ( comedi_device *dev,
549 // Disable interrupts
551 plx9050_interrupt_control (dev_private->lcr_io_base, true, true, true, true, false);
553 pci9111_trigger_source_set (dev, software);
555 pci9111_autoscan_set (dev, false);
557 pci9111_fifo_reset();
559 #ifdef AI_DO_CMD_DEBUG
560 printk (PCI9111_DRIVER_NAME ": ai_cancel\n");
567 // Test analog input command
570 #define pci9111_check_trigger_src(src,flags) \
573 if (!src || tmp != src) error++
576 pci9111_ai_do_cmd_test ( comedi_device *dev,
582 int range, reference;
584 pci9111_board_struct* board= (pci9111_board_struct*) dev->board_ptr;
586 // Step 1 : check if trigger are trivialy valid
588 pci9111_check_trigger_src (cmd->start_src, TRIG_NOW);
589 pci9111_check_trigger_src (cmd->scan_begin_src, TRIG_TIMER|TRIG_FOLLOW|TRIG_EXT);
590 pci9111_check_trigger_src (cmd->convert_src, TRIG_TIMER|TRIG_EXT);
591 pci9111_check_trigger_src (cmd->scan_end_src, TRIG_COUNT);
592 pci9111_check_trigger_src (cmd->stop_src, TRIG_COUNT|TRIG_NONE);
596 // step 2 : make sure trigger sources are unique and mutually compatible
598 if (cmd->start_src != TRIG_NOW) error++;
600 if ((cmd->scan_begin_src != TRIG_TIMER) &&
601 (cmd->scan_begin_src != TRIG_FOLLOW) &&
602 (cmd->scan_begin_src != TRIG_EXT)) error++;
604 if ((cmd->convert_src != TRIG_TIMER) &&
605 (cmd->convert_src != TRIG_EXT))
609 if ((cmd->convert_src == TRIG_TIMER) &&
610 !((cmd->scan_begin_src == TRIG_TIMER) ||
611 (cmd->scan_begin_src == TRIG_FOLLOW)))
615 if ((cmd->convert_src == TRIG_EXT) &&
616 !((cmd->scan_begin_src == TRIG_EXT) ||
617 (cmd->scan_begin_src == TRIG_FOLLOW)))
622 if (cmd->scan_end_src != TRIG_COUNT) error++;
623 if ( (cmd->stop_src != TRIG_COUNT) &&
624 (cmd->stop_src != TRIG_NONE)) error++;
628 // Step 3 : make sure arguments are trivialy compatible
630 if (cmd->chanlist_len<1)
636 if (cmd->chanlist_len>board->ai_channel_nbr)
638 cmd->chanlist_len=board->ai_channel_nbr;
642 if ((cmd->start_src == TRIG_NOW) &&
643 (cmd->start_arg!=0)) {
648 if ((cmd->convert_src == TRIG_TIMER) &&
649 (cmd->convert_arg<board->ai_acquisition_period_min_ns))
651 cmd->convert_arg=board->ai_acquisition_period_min_ns;
654 if ((cmd->convert_src == TRIG_EXT) &&
655 (cmd->convert_arg != 0))
657 cmd->convert_arg = 0;
661 if ((cmd->scan_begin_src == TRIG_TIMER) &&
662 (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns))
664 cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
667 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
668 (cmd->scan_begin_arg != 0))
670 cmd->scan_begin_arg = 0;
673 if ((cmd->scan_begin_src == TRIG_EXT) &&
674 (cmd->scan_begin_arg != 0))
676 cmd->scan_begin_arg = 0;
680 if ((cmd->scan_end_src == TRIG_COUNT) &&
681 (cmd->scan_end_arg != cmd->chanlist_len))
683 cmd->scan_end_arg=cmd->chanlist_len;
687 if ((cmd->stop_src == TRIG_COUNT) &&
693 if ((cmd->stop_src == TRIG_NONE) &&
702 // Step 4 : fix up any arguments
704 if (cmd->convert_src == TRIG_TIMER)
706 tmp = cmd->convert_arg;
707 i8253_cascade_ns_to_timer_2div (PCI9111_8254_CLOCK_PERIOD_NS,
708 &(dev_private->timer_divisor_1),
709 &(dev_private->timer_divisor_2),
711 cmd->flags & TRIG_ROUND_MASK);
712 if (tmp != cmd->convert_arg) error++;
715 // There's only one timer on this card, so the scan_begin timer must
716 // be a multiple of chanlist_len*convert_arg
718 if (cmd->scan_begin_src == TRIG_TIMER) {
720 unsigned int scan_begin_min;
721 unsigned int scan_begin_arg;
722 unsigned int scan_factor;
724 scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
726 if (cmd->scan_begin_arg != scan_begin_min) {
727 if (scan_begin_min < cmd->scan_begin_arg) {
728 scan_factor = cmd->scan_begin_arg / scan_begin_min;
729 scan_begin_arg = scan_factor * scan_begin_min;
730 if (cmd->scan_begin_arg != scan_begin_arg) {
731 cmd->scan_begin_arg = scan_begin_arg;
735 cmd->scan_begin_arg = scan_begin_min;
743 // Step 5 : check channel list
747 range=CR_RANGE(cmd->chanlist[0]);
748 reference=CR_AREF(cmd->chanlist[0]);
750 if (cmd->chanlist_len > 1) {
751 for (i=0;i<cmd->chanlist_len;i++)
753 if (CR_CHAN(cmd->chanlist[i]) != i)
756 "entries in chanlist must be consecutive "
757 "channels,counting upwards from 0\n");
760 if (CR_RANGE(cmd->chanlist[i]) != range)
763 "entries in chanlist must all have the same gain\n");
766 if (CR_AREF(cmd->chanlist[i]) != reference)
769 "entries in chanlist must all have the same reference\n");
776 if ((CR_CHAN (cmd->chanlist[0]) > (board->ai_channel_nbr -1)) ||
777 (CR_CHAN (cmd->chanlist[0]) < 0))
780 "channel number is out of limits\n");
794 // Analog input command
797 static int pci9111_ai_do_cmd ( comedi_device *dev,
798 comedi_subdevice *subdevice)
800 comedi_cmd *async_cmd=&subdevice->async->cmd;
804 comedi_error (dev, "no irq assigned for PCI9111, cannot do hardware conversion");
808 // Set channel scan limit
810 // PCI9111 allows only scanning from channel 0 to channel n
812 // TODO: handle the case of an external multiplexer
815 if (async_cmd->chanlist_len > 1)
817 pci9111_ai_channel_set ((async_cmd->chanlist_len)-1);
818 pci9111_autoscan_set (dev, true);
822 pci9111_ai_channel_set (CR_CHAN (async_cmd->chanlist[0]));
823 pci9111_autoscan_set (dev, false);
828 // This is the same gain on every channel
831 pci9111_ai_range_set (CR_RANGE(async_cmd->chanlist[0]));
835 switch (async_cmd->stop_src)
838 dev_private->stop_counter = async_cmd->stop_arg * async_cmd->chanlist_len;
839 dev_private->stop_is_none = 0;
843 dev_private->stop_counter = 0;
844 dev_private->stop_is_none = 1;
848 comedi_error(dev, "Invalid stop trigger");
854 dev_private->scan_delay = 0;
855 switch (async_cmd->convert_src)
858 i8253_cascade_ns_to_timer_2div (PCI9111_8254_CLOCK_PERIOD_NS,
859 &(dev_private->timer_divisor_1),
860 &(dev_private->timer_divisor_2),
861 &(async_cmd->convert_arg),
862 async_cmd->flags & TRIG_ROUND_MASK);
863 #ifdef AI_DO_CMD_DEBUG
864 printk (PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
865 dev_private->timer_divisor_1,dev_private->timer_divisor_2);
869 pci9111_trigger_source_set (dev,software);
870 pci9111_timer_set (dev);
871 pci9111_fifo_reset ();
872 pci9111_interrupt_source_set (dev,irq_on_fifo_half_full,
874 pci9111_trigger_source_set (dev,timer_pacer);
875 plx9050_interrupt_control (dev_private->lcr_io_base, true, true, false, true, true);
877 dev_private->scan_delay =
878 (async_cmd->scan_begin_arg / (async_cmd->convert_arg * async_cmd->chanlist_len)) - 1;
884 pci9111_trigger_source_set (dev, external);
885 pci9111_fifo_reset ();
886 pci9111_interrupt_source_set (dev, irq_on_fifo_half_full,
888 plx9050_interrupt_control (dev_private->lcr_io_base, true, true, false, true, true);
893 comedi_error (dev, "Invalid convert trigger");
897 dev_private->stop_counter *= (1 + dev_private->scan_delay);
898 dev_private->chanlist_len = async_cmd->chanlist_len;
899 dev_private->chunk_counter = 0;
900 dev_private->chunk_num_samples = dev_private->chanlist_len * (1 + dev_private->scan_delay);
902 #ifdef AI_DO_CMD_DEBUG
903 printk (PCI9111_DRIVER_NAME ": start interruptions!\n");
904 printk (PCI9111_DRIVER_NAME ": trigger source = %2x\n",
905 pci9111_trigger_and_autoscan_get());
906 printk (PCI9111_DRIVER_NAME ": irq source = %2x\n",
907 pci9111_interrupt_and_fifo_get());
908 printk (PCI9111_DRIVER_NAME ": ai_do_cmd\n");
909 printk (PCI9111_DRIVER_NAME ": stop counter = %d\n",
910 dev_private->stop_counter);
911 printk (PCI9111_DRIVER_NAME ": scan delay = %d\n",
912 dev_private->scan_delay);
913 printk (PCI9111_DRIVER_NAME ": chanlist_len = %d\n",
914 dev_private->chanlist_len);
915 printk (PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
916 dev_private->chunk_num_samples);
922 static void pci9111_ai_munge(comedi_device *dev, comedi_subdevice *s, void *data,
923 unsigned int num_bytes, unsigned int start_chan_index )
925 unsigned int i, num_samples = num_bytes / sizeof(sampl_t);
926 sampl_t *array = data;
927 int resolution = ((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
929 for(i = 0; i < num_samples; i++)
931 if(resolution == PCI9111_HR_AI_RESOLUTION)
932 array[i] = (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
934 array[i] = ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^ PCI9111_AI_RESOLUTION_2_CMP_BIT;
938 // ------------------------------------------------------------------
942 // ------------------------------------------------------------------
944 #undef INTERRUPT_DEBUG
947 pci9111_interrupt (int irq, void *p_device PT_REGS_ARG)
949 comedi_device *dev=p_device;
950 comedi_subdevice *subdevice = dev->read_subdev;
952 unsigned long irq_flags;
954 async = subdevice->async;
956 comedi_spin_lock_irqsave (&dev->spinlock, irq_flags);
958 if ((inb (dev_private->lcr_io_base + PLX9050_REGISTER_INTERRUPT_CONTROL) &
959 PLX9050_LINTI1_STATUS) != 0)
961 // Interrupt comes from fifo_half-full signal
963 if (pci9111_is_fifo_full())
965 comedi_spin_unlock_irqrestore (&dev->spinlock, irq_flags);
966 comedi_error (dev, PCI9111_DRIVER_NAME " fifo overflow");
967 pci9111_interrupt_clear();
968 pci9111_ai_cancel (dev, subdevice);
969 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
970 comedi_event (dev, subdevice, async->events);
975 if (pci9111_is_fifo_half_full())
977 unsigned int num_samples;
978 unsigned int bytes_written = 0;
980 #ifdef INTERRUPT_DEBUG
981 printk (PCI9111_DRIVER_NAME ": fifo is half full\n");
984 num_samples = PCI9111_FIFO_HALF_SIZE > dev_private->stop_counter &&
985 !dev_private->stop_is_none ?
986 dev_private->stop_counter :
987 PCI9111_FIFO_HALF_SIZE;
988 insw (PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
989 dev_private->ai_bounce_buffer,
992 if (dev_private->scan_delay < 1) {
993 bytes_written = cfc_write_array_to_buffer (subdevice,
994 dev_private->ai_bounce_buffer,
995 num_samples * sizeof(sampl_t));
1000 while (position < num_samples) {
1001 if (dev_private->chunk_counter < dev_private->chanlist_len) {
1002 to_read = dev_private->chanlist_len - dev_private->chunk_counter;
1004 if (to_read > num_samples - position)
1005 to_read = num_samples - position;
1007 bytes_written += cfc_write_array_to_buffer (subdevice,
1008 dev_private->ai_bounce_buffer + position,
1009 to_read * sizeof(sampl_t));
1011 to_read = dev_private->chunk_num_samples - dev_private->chunk_counter;
1012 if (to_read > num_samples - position)
1013 to_read = num_samples - position;
1015 bytes_written += sizeof(sampl_t) * to_read;
1018 position += to_read;
1019 dev_private->chunk_counter += to_read;
1021 if (dev_private->chunk_counter >= dev_private->chunk_num_samples)
1022 dev_private->chunk_counter = 0;
1026 dev_private->stop_counter -= bytes_written / sizeof(sampl_t);
1030 if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none))
1032 async->events |= COMEDI_CB_EOA;
1033 pci9111_ai_cancel (dev, subdevice);
1036 /* Very important, otherwise another interrupt request will be inserted
1037 * and will cause driver hangs on processing interrupt event. */
1039 pci9111_interrupt_clear();
1041 comedi_spin_unlock_irqrestore (&dev->spinlock, irq_flags);
1043 comedi_event (dev, subdevice, async->events);
1048 // ------------------------------------------------------------------
1050 // INSTANT ANALOG INPUT OUTPUT SECTION
1052 // ------------------------------------------------------------------
1055 // analog instant input
1058 #undef AI_INSN_DEBUG
1060 static int pci9111_ai_insn_read ( comedi_device *dev,
1061 comedi_subdevice *subdevice,
1065 int resolution = ((pci9111_board_struct *) dev->board_ptr)->ai_resolution;
1069 #ifdef AI_INSN_DEBUG
1070 printk (PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
1071 CR_CHAN((&insn->chanspec)[0]),
1072 CR_RANGE((&insn->chanspec)[0]),
1076 pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
1078 if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
1080 pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
1083 pci9111_fifo_reset();
1085 for (i=0;i<insn->n;i++)
1087 pci9111_software_trigger();
1089 timeout=PCI9111_AI_INSTANT_READ_TIMEOUT;
1092 if (!pci9111_is_fifo_empty()) goto conversion_done;
1095 comedi_error(dev,"A/D read timeout");
1097 pci9111_fifo_reset();
1102 if (resolution==PCI9111_HR_AI_RESOLUTION)
1104 data[i] = pci9111_hr_ai_get_data();
1108 data[i] = pci9111_ai_get_data();
1112 #ifdef AI_INSN_DEBUG
1113 printk (PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
1114 pci9111_ai_channel_get(),
1115 pci9111_ai_range_get(),
1116 pci9111_trigger_and_autoscan_get());
1123 // Analog instant output
1127 pci9111_ao_insn_write ( comedi_device *dev,
1128 comedi_subdevice *s,
1134 for (i=0; i<insn->n; i++) {
1135 pci9111_ao_set_data(data[i]);
1136 dev_private->ao_readback=data[i];
1143 // Analog output readback
1146 static int pci9111_ao_insn_read ( comedi_device * dev,
1147 comedi_subdevice * s,
1153 for (i=0; i<insn->n; i++) {
1154 data[i]=dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
1160 // ------------------------------------------------------------------
1162 // DIGITAL INPUT OUTPUT SECTION
1164 // ------------------------------------------------------------------
1170 static int pci9111_di_insn_bits ( comedi_device *dev,
1171 comedi_subdevice *subdevice,
1177 bits = pci9111_di_get_bits();
1187 static int pci9111_do_insn_bits ( comedi_device *dev,
1188 comedi_subdevice *subdevice,
1194 // Only set bits that have been masked
1196 // data[1] = bit state
1198 data[0] &= PCI9111_DO_MASK;
1200 bits = subdevice->state;
1202 bits |= data[0] & data[1];
1203 subdevice->state = bits;
1205 pci9111_do_set_bits(bits);
1213 // ------------------------------------------------------------------
1215 // INITIALISATION SECTION
1217 // ------------------------------------------------------------------
1223 static int pci9111_reset (comedi_device *dev)
1225 // Set trigger source to software
1227 plx9050_interrupt_control (dev_private->lcr_io_base, true, true, true, true, false);
1229 pci9111_trigger_source_set (dev, software);
1230 pci9111_pretrigger_set (dev, false);
1231 pci9111_autoscan_set (dev,false);
1235 dev_private->timer_divisor_1=0;
1236 dev_private->timer_divisor_2=0;
1238 pci9111_timer_set (dev);
1246 // - Register PCI device
1247 // - Declare device driver capability
1250 static int pci9111_attach(comedi_device *dev,comedi_devconfig *it)
1252 comedi_subdevice *subdevice;
1253 unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
1254 struct pci_dev* pci_device;
1256 pci9111_board_struct* board;
1258 if(alloc_private(dev, sizeof(pci9111_private_data_struct)) < 0)
1263 // Probe the device to determine what device in the series it is.
1266 printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n",dev->minor);
1268 for(pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL); pci_device != NULL ;
1269 pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device))
1271 if (pci_device->vendor == PCI_VENDOR_ID_ADLINK)
1273 for (i= 0; i< pci9111_board_nbr; i++)
1275 if(pci9111_boards[i].device_id == pci_device->device)
1277 // was a particular bus/slot requested?
1278 if((it->options[0] != 0) || (it->options[1] != 0))
1280 // are we on the wrong bus/slot?
1281 if(pci_device->bus->number != it->options[0] ||
1282 PCI_SLOT(pci_device->devfn) != it->options[1])
1288 dev->board_ptr = pci9111_boards + i;
1289 board = (pci9111_board_struct *) dev->board_ptr;
1290 dev_private->pci_device = pci_device;
1297 printk ("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
1298 dev->minor,it->options[0], it->options[1]);
1303 printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
1305 pci9111_boards[i].name,
1306 pci_device->bus->number,
1307 PCI_SLOT(pci_device->devfn),
1308 PCI_FUNC(pci_device->devfn),
1311 // TODO: Warn about non-tested boards.
1313 switch(board->device_id)
1317 // Read local configuration register base address [PCI_BASE_ADDRESS #1].
1319 lcr_io_base = pci_resource_start (pci_device, 1);
1320 lcr_io_range = pci_resource_len (pci_device, 1);
1322 printk ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
1327 // Enable PCI device
1328 if(pci_enable_device (pci_device) < 0)
1330 printk("comedi%d: Failed to enable PCI device\n", dev->minor);
1334 // Read PCI6308 register base address [PCI_BASE_ADDRESS #2].
1336 io_base = pci_resource_start (pci_device, 2);
1337 io_range = pci_resource_len (pci_device, 2);
1339 printk ("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
1344 // Allocate IO ressources
1345 if(pci_request_regions(pci_device, PCI9111_DRIVER_NAME))
1347 printk("comedi%d: I/O port conflict\n",dev->minor);
1351 dev->iobase=io_base;
1352 dev->board_name = board->name;
1353 dev_private->io_range = io_range;
1354 dev_private->is_valid=0;
1355 dev_private->lcr_io_base=lcr_io_base;
1356 dev_private->lcr_io_range=lcr_io_range;
1363 if (pci_device->irq>0)
1365 if (comedi_request_irq (pci_device->irq,
1368 PCI9111_DRIVER_NAME,
1371 printk ("comedi%d: unable to allocate irq %u\n", dev->minor, pci_device->irq);
1375 dev->irq = pci_device->irq;
1378 // TODO: Add external multiplexer setup (according to option[2]).
1381 if((error=alloc_subdevices(dev, 4))<0)
1384 subdevice = dev->subdevices + 0;
1385 dev->read_subdev = subdevice;
1387 subdevice->type = COMEDI_SUBD_AI;
1388 subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
1391 // TODO: Add external multiplexer data
1393 // if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; }
1394 // else { subdevice->n_chan = this_board->n_aichan; }
1397 subdevice->n_chan = board->ai_channel_nbr;
1398 subdevice->maxdata = board->ai_resolution_mask;
1399 subdevice->len_chanlist = board->ai_channel_nbr;
1400 subdevice->range_table = board->ai_range_list;
1401 subdevice->cancel = pci9111_ai_cancel;
1402 subdevice->insn_read = pci9111_ai_insn_read;
1403 subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
1404 subdevice->do_cmd = pci9111_ai_do_cmd;
1405 subdevice->munge = pci9111_ai_munge;
1407 subdevice = dev->subdevices + 1;
1408 subdevice->type = COMEDI_SUBD_AO;
1409 subdevice->subdev_flags = SDF_WRITABLE|SDF_COMMON;
1410 subdevice->n_chan = board->ao_channel_nbr;
1411 subdevice->maxdata = board->ao_resolution_mask;
1412 subdevice->len_chanlist = board->ao_channel_nbr;
1413 subdevice->range_table = board->ao_range_list;
1414 subdevice->insn_write = pci9111_ao_insn_write;
1415 subdevice->insn_read = pci9111_ao_insn_read;
1417 subdevice = dev->subdevices + 2;
1418 subdevice->type = COMEDI_SUBD_DI;
1419 subdevice->subdev_flags = SDF_READABLE;
1420 subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
1421 subdevice->maxdata = 1;
1422 subdevice->range_table = &range_digital;
1423 subdevice->insn_bits = pci9111_di_insn_bits;
1425 subdevice = dev->subdevices + 3;
1426 subdevice->type = COMEDI_SUBD_DO;
1427 subdevice->subdev_flags = SDF_READABLE|SDF_WRITABLE;
1428 subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
1429 subdevice->maxdata = 1;
1430 subdevice->range_table = &range_digital;
1431 subdevice->insn_bits = pci9111_do_insn_bits;
1433 dev_private->is_valid = 1;
1443 static int pci9111_detach(comedi_device *dev)
1447 if (dev->private!=0)
1449 if (dev_private->is_valid) pci9111_reset(dev);
1453 // Release previously allocated irq
1457 comedi_free_irq(dev->irq,dev);
1460 if (dev_private!=0 && dev_private->pci_device!=0)
1464 pci_release_regions(dev_private->pci_device);
1465 pci_disable_device(dev_private->pci_device);
1467 pci_dev_put(dev_private->pci_device);