adl_pci9111.c revision ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3f
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/*
27Driver: adl_pci9111
28Description: Adlink PCI-9111HR
29Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
30Devices: [ADLink] PCI-9111HR (adl_pci9111)
31Status: experimental
32
33Supports:
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
50Configuration 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/*
61CHANGELOG:
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
68TODO:
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
268static int pci9111_attach(struct comedi_device * dev, comedi_devconfig * it);
269static int pci9111_detach(struct comedi_device * dev);
270static 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
273static const struct 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
284static 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
291MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
292
293//
294// Board specification structure
295//
296
297typedef 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 struct comedi_lrange *ai_range_list;	// rangelist for A/D
307	const struct comedi_lrange *ao_range_list;	// rangelist for D/A
308	unsigned int ai_acquisition_period_min_ns;
309} pci9111_board_struct;
310
311static 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
329static struct comedi_driver pci9111_driver = {
330      driver_name:PCI9111_DRIVER_NAME,
331      module:THIS_MODULE,
332      attach:pci9111_attach,
333      detach:pci9111_detach,
334};
335
336COMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
337
338//
339// Private data structure
340//
341
342typedef 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
386static 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
418static 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
438typedef enum {
439	software,
440	timer_pacer,
441	external
442} pci9111_trigger_sources;
443
444static 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
468static 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
480static 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
492typedef enum {
493	irq_on_eoc,
494	irq_on_fifo_half_full
495} pci9111_ISC0_sources;
496
497typedef enum {
498	irq_on_timer_tick,
499	irq_on_external_trigger
500} pci9111_ISC1_sources;
501
502static 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
530static 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
559static int
560pci9111_ai_do_cmd_test(struct comedi_device * dev,
561	struct comedi_subdevice * s, struct 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
761static int pci9111_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * subdevice)
762{
763	struct 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
884static 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
912static 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	struct 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
1074static 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
1133static int
1134pci9111_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
1151static 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
1173static 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
1188static 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
1221static 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
1249static 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
1423static 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}
1447