adl_pci9111.c revision f2bed9b4cbc6fa34db4e9b788c5f631fb7358ecc
1/*
2
3comedi/drivers/adl_pci9111.c
4
5Hardware driver for PCI9111 ADLink cards:
6
7PCI-9111HR
8
9Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
10
11This program is free software; you can redistribute it and/or modify
12it under the terms of the GNU General Public License as published by
13the Free Software Foundation; either version 2 of the License, or
14(at your option) any later version.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, 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
47The scanned channels must be consecutive and start from 0. They must
48all have the same range and aref.
49
50Configuration options:
51
52	[0] - PCI bus number (optional)
53	[1] - PCI slot number (optional)
54
55If bus/slot is not specified, the first available PCI
56device will be used.
57
58*/
59
60/*
61CHANGELOG:
62
632005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
64a multiple of chanlist_len*convert_arg.
652002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
662002/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
72	  the card type (perhaps with the help of the channel number readback
73	  of the A/D Data register).
74	- Add external multiplexer support.
75
76*/
77
78#include "../comedidev.h"
79
80#include <linux/delay.h>
81#include <linux/interrupt.h>
82
83#include "8253.h"
84#include "comedi_fc.h"
85
86#define PCI9111_DRIVER_NAME	"adl_pci9111"
87#define PCI9111_HR_DEVICE_ID	0x9111
88
89/*  TODO: Add other pci9111 board id */
90
91#define PCI9111_IO_RANGE	0x0100
92
93#define PCI9111_FIFO_HALF_SIZE	512
94
95#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
96
97#define PCI9111_RANGE_SETTING_DELAY		10
98#define PCI9111_AI_INSTANT_READ_UDELAY_US	2
99#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
100
101#define PCI9111_8254_CLOCK_PERIOD_NS		500
102
103/* IO address map */
104
105#define PCI9111_AI_FIFO_REG				0x00
106#define PCI9111_AO_REG					0x00
107#define PCI9111_DIO_REG					0x02
108#define PCI9111_REGISTER_EXTENDED_IO_PORTS		0x04
109#define PCI9111_REGISTER_AD_CHANNEL_CONTROL		0x06 /* Channel
110								selection */
111#define PCI9111_REGISTER_AD_CHANNEL_READBACK		0x06
112#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE		0x08
113#define PCI9111_REGISTER_RANGE_STATUS_READBACK		0x08
114#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL		0x0A
115#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK	0x0A
116#define PCI9111_REGISTER_SOFTWARE_TRIGGER		0x0E
117#define PCI9111_REGISTER_INTERRUPT_CONTROL		0x0C
118#define PCI9111_8254_BASE_REG				0x40
119#define PCI9111_REGISTER_INTERRUPT_CLEAR		0x48
120
121#define PCI9111_TRIGGER_MASK				0x0F
122#define PCI9111_PTRG_OFF				(0 << 3)
123#define PCI9111_PTRG_ON					(1 << 3)
124#define PCI9111_EITS_EXTERNAL				(1 << 2)
125#define PCI9111_EITS_INTERNAL				(0 << 2)
126#define PCI9111_TPST_SOFTWARE_TRIGGER			(0 << 1)
127#define PCI9111_TPST_TIMER_PACER			(1 << 1)
128#define PCI9111_ASCAN_ON				(1 << 0)
129#define PCI9111_ASCAN_OFF				(0 << 0)
130
131#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
132#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL		(1 << 0)
133#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK		(0 << 1)
134#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG			(1 << 1)
135#define PCI9111_FFEN_SET_FIFO_ENABLE			(0 << 2)
136#define PCI9111_FFEN_SET_FIFO_DISABLE			(1 << 2)
137
138#define PCI9111_CHANNEL_MASK				0x0F
139
140#define PCI9111_RANGE_MASK				0x07
141#define PCI9111_FIFO_EMPTY_MASK				0x10
142#define PCI9111_FIFO_HALF_FULL_MASK			0x20
143#define PCI9111_FIFO_FULL_MASK				0x40
144#define PCI9111_AD_BUSY_MASK				0x80
145
146/*
147 * Define inlined function
148 */
149
150#define pci9111_trigger_and_autoscan_get() \
151	(inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
152
153#define pci9111_trigger_and_autoscan_set(flags) \
154	outb(flags, dev->iobase + PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
155
156#define pci9111_interrupt_and_fifo_get() \
157	((inb(dev->iobase + PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
158		>> 4) & 0x03)
159
160#define pci9111_interrupt_and_fifo_set(flags) \
161	outb(flags, dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL)
162
163#define pci9111_interrupt_clear() \
164	outb(0, dev->iobase + PCI9111_REGISTER_INTERRUPT_CLEAR)
165
166#define pci9111_software_trigger() \
167	outb(0, dev->iobase + PCI9111_REGISTER_SOFTWARE_TRIGGER)
168
169#define pci9111_fifo_reset() do { \
170	outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
171		dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
172	outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
173		dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
174	outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
175		dev->iobase + PCI9111_REGISTER_INTERRUPT_CONTROL); \
176	} while (0)
177
178#define pci9111_is_fifo_full() \
179	((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
180		PCI9111_FIFO_FULL_MASK) == 0)
181
182#define pci9111_is_fifo_half_full() \
183	((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
184		PCI9111_FIFO_HALF_FULL_MASK) == 0)
185
186#define pci9111_is_fifo_empty() \
187	((inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
188		PCI9111_FIFO_EMPTY_MASK) == 0)
189
190#define pci9111_ai_channel_set(channel) \
191	outb((channel)&PCI9111_CHANNEL_MASK, \
192		dev->iobase + PCI9111_REGISTER_AD_CHANNEL_CONTROL)
193
194#define pci9111_ai_channel_get() \
195	(inb(dev->iobase + PCI9111_REGISTER_AD_CHANNEL_READBACK) \
196		&PCI9111_CHANNEL_MASK)
197
198#define pci9111_ai_range_set(range) \
199	outb((range)&PCI9111_RANGE_MASK, \
200		dev->iobase + PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
201
202#define pci9111_ai_range_get() \
203	(inb(dev->iobase + PCI9111_REGISTER_RANGE_STATUS_READBACK) \
204		&PCI9111_RANGE_MASK)
205
206static const struct comedi_lrange pci9111_hr_ai_range = {
207	5,
208	{
209	 BIP_RANGE(10),
210	 BIP_RANGE(5),
211	 BIP_RANGE(2.5),
212	 BIP_RANGE(1.25),
213	 BIP_RANGE(0.625)
214	 }
215};
216
217/*  */
218/*  Board specification structure */
219/*  */
220
221struct pci9111_board {
222	const char *name;	/*  driver name */
223	int device_id;
224};
225
226static const struct pci9111_board pci9111_boards[] = {
227	{
228	 .name = "pci9111_hr",
229	 .device_id = PCI9111_HR_DEVICE_ID,
230	},
231};
232
233/*  Private data structure */
234
235struct pci9111_private_data {
236	unsigned long lcr_io_base; /* Local configuration register base
237				    * address */
238
239	int stop_counter;
240	int stop_is_none;
241
242	unsigned int scan_delay;
243	unsigned int chanlist_len;
244	unsigned int chunk_counter;
245	unsigned int chunk_num_samples;
246
247	int ao_readback;	/*  Last written analog output data */
248
249	unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
250				       * pacer */
251	unsigned int timer_divisor_2;
252
253	int is_valid;		/*  Is device valid */
254
255	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
256};
257
258/*  ------------------------------------------------------------------ */
259/*  PLX9050 SECTION */
260/*  ------------------------------------------------------------------ */
261
262#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
263
264#define PLX9050_LINTI1_ENABLE		(1 << 0)
265#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
266#define PLX9050_LINTI1_STATUS		(1 << 2)
267#define PLX9050_LINTI2_ENABLE		(1 << 3)
268#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
269#define PLX9050_LINTI2_STATUS		(1 << 5)
270#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
271#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
272
273static void plx9050_interrupt_control(unsigned long io_base,
274				      bool LINTi1_enable,
275				      bool LINTi1_active_high,
276				      bool LINTi2_enable,
277				      bool LINTi2_active_high,
278				      bool interrupt_enable)
279{
280	int flags = 0;
281
282	if (LINTi1_enable)
283		flags |= PLX9050_LINTI1_ENABLE;
284	if (LINTi1_active_high)
285		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
286	if (LINTi2_enable)
287		flags |= PLX9050_LINTI2_ENABLE;
288	if (LINTi2_active_high)
289		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
290
291	if (interrupt_enable)
292		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
293
294	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
295}
296
297/*  ------------------------------------------------------------------ */
298/*  MISCELLANEOUS SECTION */
299/*  ------------------------------------------------------------------ */
300
301/*  8254 timer */
302
303static void pci9111_timer_set(struct comedi_device *dev)
304{
305	struct pci9111_private_data *dev_private = dev->private;
306	unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
307
308	i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
309	i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
310	i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
311
312	udelay(1);
313
314	i8254_write(timer_base, 1, 2, dev_private->timer_divisor_2);
315	i8254_write(timer_base, 1, 1, dev_private->timer_divisor_1);
316}
317
318enum pci9111_trigger_sources {
319	software,
320	timer_pacer,
321	external
322};
323
324static void pci9111_trigger_source_set(struct comedi_device *dev,
325				       enum pci9111_trigger_sources source)
326{
327	int flags;
328
329	flags = pci9111_trigger_and_autoscan_get() & 0x09;
330
331	switch (source) {
332	case software:
333		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
334		break;
335
336	case timer_pacer:
337		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
338		break;
339
340	case external:
341		flags |= PCI9111_EITS_EXTERNAL;
342		break;
343	}
344
345	pci9111_trigger_and_autoscan_set(flags);
346}
347
348static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
349{
350	int flags;
351
352	flags = pci9111_trigger_and_autoscan_get() & 0x07;
353
354	if (pretrigger)
355		flags |= PCI9111_PTRG_ON;
356
357	pci9111_trigger_and_autoscan_set(flags);
358}
359
360static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
361{
362	int flags;
363
364	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
365
366	if (autoscan)
367		flags |= PCI9111_ASCAN_ON;
368
369	pci9111_trigger_and_autoscan_set(flags);
370}
371
372enum pci9111_ISC0_sources {
373	irq_on_eoc,
374	irq_on_fifo_half_full
375};
376
377enum pci9111_ISC1_sources {
378	irq_on_timer_tick,
379	irq_on_external_trigger
380};
381
382static void pci9111_interrupt_source_set(struct comedi_device *dev,
383					 enum pci9111_ISC0_sources irq_0_source,
384					 enum pci9111_ISC1_sources irq_1_source)
385{
386	int flags;
387
388	flags = pci9111_interrupt_and_fifo_get() & 0x04;
389
390	if (irq_0_source == irq_on_fifo_half_full)
391		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
392
393	if (irq_1_source == irq_on_external_trigger)
394		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
395
396	pci9111_interrupt_and_fifo_set(flags);
397}
398
399/*  ------------------------------------------------------------------ */
400/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
401/*  ------------------------------------------------------------------ */
402
403/*  Cancel analog input autoscan */
404
405#undef AI_DO_CMD_DEBUG
406
407static int pci9111_ai_cancel(struct comedi_device *dev,
408			     struct comedi_subdevice *s)
409{
410	struct pci9111_private_data *dev_private = dev->private;
411
412	/*  Disable interrupts */
413
414	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
415				  true, false);
416
417	pci9111_trigger_source_set(dev, software);
418
419	pci9111_autoscan_set(dev, false);
420
421	pci9111_fifo_reset();
422
423#ifdef AI_DO_CMD_DEBUG
424	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
425#endif
426
427	return 0;
428}
429
430/*  Test analog input command */
431
432#define pci9111_check_trigger_src(src, flags)	do {			\
433		tmp = src;						\
434		src &= flags;						\
435		if (!src || tmp != src)					\
436			error++;					\
437	} while (false);
438
439static int
440pci9111_ai_do_cmd_test(struct comedi_device *dev,
441		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
442{
443	struct pci9111_private_data *dev_private = dev->private;
444	int tmp;
445	int error = 0;
446	int range, reference;
447	int i;
448
449	/*  Step 1 : check if trigger are trivialy valid */
450
451	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
452	pci9111_check_trigger_src(cmd->scan_begin_src,
453				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
454	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
455	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
456	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
457
458	if (error)
459		return 1;
460
461	/*  step 2 : make sure trigger sources are unique and mutually
462	 *  compatible */
463
464	if (cmd->start_src != TRIG_NOW)
465		error++;
466
467	if ((cmd->scan_begin_src != TRIG_TIMER) &&
468	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
469	    (cmd->scan_begin_src != TRIG_EXT))
470		error++;
471
472	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
473		error++;
474	if ((cmd->convert_src == TRIG_TIMER) &&
475	    !((cmd->scan_begin_src == TRIG_TIMER) ||
476	      (cmd->scan_begin_src == TRIG_FOLLOW)))
477		error++;
478	if ((cmd->convert_src == TRIG_EXT) &&
479	    !((cmd->scan_begin_src == TRIG_EXT) ||
480	      (cmd->scan_begin_src == TRIG_FOLLOW)))
481		error++;
482
483
484	if (cmd->scan_end_src != TRIG_COUNT)
485		error++;
486	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
487		error++;
488
489	if (error)
490		return 2;
491
492	/*  Step 3 : make sure arguments are trivialy compatible */
493
494	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
495		cmd->start_arg = 0;
496		error++;
497	}
498
499	if ((cmd->convert_src == TRIG_TIMER) &&
500	    (cmd->convert_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
501		cmd->convert_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
502		error++;
503	}
504	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
505		cmd->convert_arg = 0;
506		error++;
507	}
508
509	if ((cmd->scan_begin_src == TRIG_TIMER) &&
510	    (cmd->scan_begin_arg < PCI9111_AI_ACQUISITION_PERIOD_MIN_NS)) {
511		cmd->scan_begin_arg = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS;
512		error++;
513	}
514	if ((cmd->scan_begin_src == TRIG_FOLLOW)
515	    && (cmd->scan_begin_arg != 0)) {
516		cmd->scan_begin_arg = 0;
517		error++;
518	}
519	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
520		cmd->scan_begin_arg = 0;
521		error++;
522	}
523
524	if ((cmd->scan_end_src == TRIG_COUNT) &&
525	    (cmd->scan_end_arg != cmd->chanlist_len)) {
526		cmd->scan_end_arg = cmd->chanlist_len;
527		error++;
528	}
529
530	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
531		cmd->stop_arg = 1;
532		error++;
533	}
534	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
535		cmd->stop_arg = 0;
536		error++;
537	}
538
539	if (error)
540		return 3;
541
542	/*  Step 4 : fix up any arguments */
543
544	if (cmd->convert_src == TRIG_TIMER) {
545		tmp = cmd->convert_arg;
546		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
547					       &(dev_private->timer_divisor_1),
548					       &(dev_private->timer_divisor_2),
549					       &(cmd->convert_arg),
550					       cmd->flags & TRIG_ROUND_MASK);
551		if (tmp != cmd->convert_arg)
552			error++;
553	}
554	/*  There's only one timer on this card, so the scan_begin timer must */
555	/*  be a multiple of chanlist_len*convert_arg */
556
557	if (cmd->scan_begin_src == TRIG_TIMER) {
558
559		unsigned int scan_begin_min;
560		unsigned int scan_begin_arg;
561		unsigned int scan_factor;
562
563		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
564
565		if (cmd->scan_begin_arg != scan_begin_min) {
566			if (scan_begin_min < cmd->scan_begin_arg) {
567				scan_factor =
568				    cmd->scan_begin_arg / scan_begin_min;
569				scan_begin_arg = scan_factor * scan_begin_min;
570				if (cmd->scan_begin_arg != scan_begin_arg) {
571					cmd->scan_begin_arg = scan_begin_arg;
572					error++;
573				}
574			} else {
575				cmd->scan_begin_arg = scan_begin_min;
576				error++;
577			}
578		}
579	}
580
581	if (error)
582		return 4;
583
584	/*  Step 5 : check channel list */
585
586	if (cmd->chanlist) {
587
588		range = CR_RANGE(cmd->chanlist[0]);
589		reference = CR_AREF(cmd->chanlist[0]);
590
591		if (cmd->chanlist_len > 1) {
592			for (i = 0; i < cmd->chanlist_len; i++) {
593				if (CR_CHAN(cmd->chanlist[i]) != i) {
594					comedi_error(dev,
595						     "entries in chanlist must be consecutive "
596						     "channels,counting upwards from 0\n");
597					error++;
598				}
599				if (CR_RANGE(cmd->chanlist[i]) != range) {
600					comedi_error(dev,
601						     "entries in chanlist must all have the same gain\n");
602					error++;
603				}
604				if (CR_AREF(cmd->chanlist[i]) != reference) {
605					comedi_error(dev,
606						     "entries in chanlist must all have the same reference\n");
607					error++;
608				}
609			}
610		}
611	}
612
613	if (error)
614		return 5;
615
616	return 0;
617
618}
619
620/*  Analog input command */
621
622static int pci9111_ai_do_cmd(struct comedi_device *dev,
623			     struct comedi_subdevice *s)
624{
625	struct pci9111_private_data *dev_private = dev->private;
626	struct comedi_cmd *async_cmd = &s->async->cmd;
627
628	if (!dev->irq) {
629		comedi_error(dev,
630			     "no irq assigned for PCI9111, cannot do hardware conversion");
631		return -1;
632	}
633	/*  Set channel scan limit */
634	/*  PCI9111 allows only scanning from channel 0 to channel n */
635	/*  TODO: handle the case of an external multiplexer */
636
637	if (async_cmd->chanlist_len > 1) {
638		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
639		pci9111_autoscan_set(dev, true);
640	} else {
641		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
642		pci9111_autoscan_set(dev, false);
643	}
644
645	/*  Set gain */
646	/*  This is the same gain on every channel */
647
648	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
649
650	/* Set counter */
651
652	switch (async_cmd->stop_src) {
653	case TRIG_COUNT:
654		dev_private->stop_counter =
655		    async_cmd->stop_arg * async_cmd->chanlist_len;
656		dev_private->stop_is_none = 0;
657		break;
658
659	case TRIG_NONE:
660		dev_private->stop_counter = 0;
661		dev_private->stop_is_none = 1;
662		break;
663
664	default:
665		comedi_error(dev, "Invalid stop trigger");
666		return -1;
667	}
668
669	/*  Set timer pacer */
670
671	dev_private->scan_delay = 0;
672	switch (async_cmd->convert_src) {
673	case TRIG_TIMER:
674		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
675					       &(dev_private->timer_divisor_1),
676					       &(dev_private->timer_divisor_2),
677					       &(async_cmd->convert_arg),
678					       async_cmd->
679					       flags & TRIG_ROUND_MASK);
680#ifdef AI_DO_CMD_DEBUG
681		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
682		       dev_private->timer_divisor_1,
683		       dev_private->timer_divisor_2);
684#endif
685
686		pci9111_trigger_source_set(dev, software);
687		pci9111_timer_set(dev);
688		pci9111_fifo_reset();
689		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
690					     irq_on_timer_tick);
691		pci9111_trigger_source_set(dev, timer_pacer);
692		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
693					  false, true, true);
694
695		if (async_cmd->scan_begin_src == TRIG_TIMER) {
696			dev_private->scan_delay =
697				(async_cmd->scan_begin_arg /
698				 (async_cmd->convert_arg *
699				  async_cmd->chanlist_len)) - 1;
700		}
701
702		break;
703
704	case TRIG_EXT:
705
706		pci9111_trigger_source_set(dev, external);
707		pci9111_fifo_reset();
708		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
709					     irq_on_timer_tick);
710		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
711					  false, true, true);
712
713		break;
714
715	default:
716		comedi_error(dev, "Invalid convert trigger");
717		return -1;
718	}
719
720	dev_private->stop_counter *= (1 + dev_private->scan_delay);
721	dev_private->chanlist_len = async_cmd->chanlist_len;
722	dev_private->chunk_counter = 0;
723	dev_private->chunk_num_samples =
724	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
725
726#ifdef AI_DO_CMD_DEBUG
727	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
728	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
729	       pci9111_trigger_and_autoscan_get());
730	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
731	       pci9111_interrupt_and_fifo_get());
732	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
733	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
734	       dev_private->stop_counter);
735	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
736	       dev_private->scan_delay);
737	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
738	       dev_private->chanlist_len);
739	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
740	       dev_private->chunk_num_samples);
741#endif
742
743	return 0;
744}
745
746static void pci9111_ai_munge(struct comedi_device *dev,
747			     struct comedi_subdevice *s, void *data,
748			     unsigned int num_bytes,
749			     unsigned int start_chan_index)
750{
751	short *array = data;
752	unsigned int maxdata = s->maxdata;
753	unsigned int invert = (maxdata + 1) >> 1;
754	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
755	unsigned int num_samples = num_bytes / sizeof(short);
756	unsigned int i;
757
758	for (i = 0; i < num_samples; i++)
759		array[i] = ((array[i] >> shift) & maxdata) ^ invert;
760}
761
762/*  ------------------------------------------------------------------ */
763/*  INTERRUPT SECTION */
764/*  ------------------------------------------------------------------ */
765
766#undef INTERRUPT_DEBUG
767
768static irqreturn_t pci9111_interrupt(int irq, void *p_device)
769{
770	struct comedi_device *dev = p_device;
771	struct pci9111_private_data *dev_private = dev->private;
772	struct comedi_subdevice *s = dev->read_subdev;
773	struct comedi_async *async;
774	unsigned long irq_flags;
775	unsigned char intcsr;
776
777	if (!dev->attached) {
778		/*  Ignore interrupt before device fully attached. */
779		/*  Might not even have allocated subdevices yet! */
780		return IRQ_NONE;
781	}
782
783	async = s->async;
784
785	spin_lock_irqsave(&dev->spinlock, irq_flags);
786
787	/*  Check if we are source of interrupt */
788	intcsr = inb(dev_private->lcr_io_base +
789		     PLX9050_REGISTER_INTERRUPT_CONTROL);
790	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
791	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
792		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
793		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
794		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
795		/*  Not the source of the interrupt. */
796		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
797		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
798		return IRQ_NONE;
799	}
800
801	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
802	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
803		/*  Interrupt comes from fifo_half-full signal */
804
805		if (pci9111_is_fifo_full()) {
806			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
807			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
808			pci9111_interrupt_clear();
809			pci9111_ai_cancel(dev, s);
810			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
811			comedi_event(dev, s);
812
813			return IRQ_HANDLED;
814		}
815
816		if (pci9111_is_fifo_half_full()) {
817			unsigned int num_samples;
818			unsigned int bytes_written = 0;
819
820#ifdef INTERRUPT_DEBUG
821			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
822#endif
823
824			num_samples =
825			    PCI9111_FIFO_HALF_SIZE >
826			    dev_private->stop_counter
827			    && !dev_private->
828			    stop_is_none ? dev_private->stop_counter :
829			    PCI9111_FIFO_HALF_SIZE;
830			insw(dev->iobase + PCI9111_AI_FIFO_REG,
831			     dev_private->ai_bounce_buffer, num_samples);
832
833			if (dev_private->scan_delay < 1) {
834				bytes_written =
835				    cfc_write_array_to_buffer(s,
836							      dev_private->
837							      ai_bounce_buffer,
838							      num_samples *
839							      sizeof(short));
840			} else {
841				int position = 0;
842				int to_read;
843
844				while (position < num_samples) {
845					if (dev_private->chunk_counter <
846					    dev_private->chanlist_len) {
847						to_read =
848						    dev_private->chanlist_len -
849						    dev_private->chunk_counter;
850
851						if (to_read >
852						    num_samples - position)
853							to_read =
854							    num_samples -
855							    position;
856
857						bytes_written +=
858						    cfc_write_array_to_buffer
859						    (s,
860						     dev_private->ai_bounce_buffer
861						     + position,
862						     to_read * sizeof(short));
863					} else {
864						to_read =
865						    dev_private->chunk_num_samples
866						    -
867						    dev_private->chunk_counter;
868						if (to_read >
869						    num_samples - position)
870							to_read =
871							    num_samples -
872							    position;
873
874						bytes_written +=
875						    sizeof(short) * to_read;
876					}
877
878					position += to_read;
879					dev_private->chunk_counter += to_read;
880
881					if (dev_private->chunk_counter >=
882					    dev_private->chunk_num_samples)
883						dev_private->chunk_counter = 0;
884				}
885			}
886
887			dev_private->stop_counter -=
888			    bytes_written / sizeof(short);
889		}
890	}
891
892	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
893		async->events |= COMEDI_CB_EOA;
894		pci9111_ai_cancel(dev, s);
895	}
896
897	/* Very important, otherwise another interrupt request will be inserted
898	 * and will cause driver hangs on processing interrupt event. */
899
900	pci9111_interrupt_clear();
901
902	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
903
904	comedi_event(dev, s);
905
906	return IRQ_HANDLED;
907}
908
909/*  ------------------------------------------------------------------ */
910/*  INSTANT ANALOG INPUT OUTPUT SECTION */
911/*  ------------------------------------------------------------------ */
912
913/*  analog instant input */
914
915static int pci9111_ai_insn_read(struct comedi_device *dev,
916				struct comedi_subdevice *s,
917				struct comedi_insn *insn, unsigned int *data)
918{
919	unsigned int maxdata = s->maxdata;
920	unsigned int invert = (maxdata + 1) >> 1;
921	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
922	int timeout;
923	int i;
924
925	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
926
927	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
928		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
929
930	pci9111_fifo_reset();
931
932	for (i = 0; i < insn->n; i++) {
933		pci9111_software_trigger();
934
935		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
936
937		while (timeout--) {
938			if (!pci9111_is_fifo_empty())
939				goto conversion_done;
940		}
941
942		comedi_error(dev, "A/D read timeout");
943		data[i] = 0;
944		pci9111_fifo_reset();
945		return -ETIME;
946
947conversion_done:
948
949		data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG);
950		data[i] = ((data[i] >> shift) & maxdata) ^ invert;
951	}
952
953	return i;
954}
955
956static int pci9111_ao_insn_write(struct comedi_device *dev,
957				 struct comedi_subdevice *s,
958				 struct comedi_insn *insn,
959				 unsigned int *data)
960{
961	struct pci9111_private_data *dev_private = dev->private;
962	unsigned int val = 0;
963	int i;
964
965	for (i = 0; i < insn->n; i++) {
966		val = data[i];
967		outw(val, dev->iobase + PCI9111_AO_REG);
968	}
969	dev_private->ao_readback = val;
970
971	return insn->n;
972}
973
974static int pci9111_ao_insn_read(struct comedi_device *dev,
975				struct comedi_subdevice *s,
976				struct comedi_insn *insn,
977				unsigned int *data)
978{
979	struct pci9111_private_data *dev_private = dev->private;
980	int i;
981
982	for (i = 0; i < insn->n; i++)
983		data[i] = dev_private->ao_readback;
984
985	return insn->n;
986}
987
988static int pci9111_di_insn_bits(struct comedi_device *dev,
989				struct comedi_subdevice *s,
990				struct comedi_insn *insn,
991				unsigned int *data)
992{
993	data[1] = inw(dev->iobase + PCI9111_DIO_REG);
994
995	return insn->n;
996}
997
998static int pci9111_do_insn_bits(struct comedi_device *dev,
999				struct comedi_subdevice *s,
1000				struct comedi_insn *insn,
1001				unsigned int *data)
1002{
1003	unsigned int mask = data[0];
1004	unsigned int bits = data[1];
1005
1006	if (mask) {
1007		s->state &= ~mask;
1008		s->state |= (bits & mask);
1009
1010		outw(s->state, dev->iobase + PCI9111_DIO_REG);
1011	}
1012
1013	data[1] = s->state;
1014
1015	return insn->n;
1016}
1017
1018/*  ------------------------------------------------------------------ */
1019/*  INITIALISATION SECTION */
1020/*  ------------------------------------------------------------------ */
1021
1022/*  Reset device */
1023
1024static int pci9111_reset(struct comedi_device *dev)
1025{
1026	struct pci9111_private_data *dev_private = dev->private;
1027
1028	/*  Set trigger source to software */
1029
1030	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
1031				  true, false);
1032
1033	pci9111_trigger_source_set(dev, software);
1034	pci9111_pretrigger_set(dev, false);
1035	pci9111_autoscan_set(dev, false);
1036
1037	/*  Reset 8254 chip */
1038
1039	dev_private->timer_divisor_1 = 0;
1040	dev_private->timer_divisor_2 = 0;
1041
1042	pci9111_timer_set(dev);
1043
1044	return 0;
1045}
1046
1047static struct pci_dev *pci9111_find_pci(struct comedi_device *dev,
1048					struct comedi_devconfig *it)
1049{
1050	struct pci_dev *pcidev = NULL;
1051	int bus = it->options[0];
1052	int slot = it->options[1];
1053	int i;
1054
1055	for_each_pci_dev(pcidev) {
1056		if (pcidev->vendor != PCI_VENDOR_ID_ADLINK)
1057			continue;
1058		for (i = 0; i < ARRAY_SIZE(pci9111_boards); i++) {
1059			if (pcidev->device != pci9111_boards[i].device_id)
1060				continue;
1061			if (bus || slot) {
1062				/* requested particular bus/slot */
1063				if (pcidev->bus->number != bus ||
1064				    PCI_SLOT(pcidev->devfn) != slot)
1065					continue;
1066			}
1067			dev->board_ptr = pci9111_boards + i;
1068			printk(KERN_ERR
1069				"comedi%d: found %s (b:s:f=%d:%d:%d), irq=%d\n",
1070				dev->minor, pci9111_boards[i].name,
1071				pcidev->bus->number, PCI_SLOT(pcidev->devfn),
1072				PCI_FUNC(pcidev->devfn), pcidev->irq);
1073			return pcidev;
1074		}
1075	}
1076	printk(KERN_ERR
1077		"comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
1078		dev->minor, bus, slot);
1079	return NULL;
1080}
1081
1082static int pci9111_attach(struct comedi_device *dev,
1083			  struct comedi_devconfig *it)
1084{
1085	struct pci9111_private_data *dev_private;
1086	struct pci_dev *pcidev;
1087	struct comedi_subdevice *s;
1088	unsigned long io_base, lcr_io_base;
1089	int ret;
1090	const struct pci9111_board *board;
1091
1092	ret = alloc_private(dev, sizeof(*dev_private));
1093	if (ret)
1094		return ret;
1095	dev_private = dev->private;
1096
1097	/*  Probe the device to determine what device in the series it is. */
1098	pcidev = pci9111_find_pci(dev, it);
1099	if (!pcidev)
1100		return -EIO;
1101	comedi_set_hw_dev(dev, &pcidev->dev);
1102	board = (struct pci9111_board *)dev->board_ptr;
1103
1104	/*  TODO: Warn about non-tested boards. */
1105
1106	/*  Read local configuration register base address
1107	 *  [PCI_BASE_ADDRESS #1]. */
1108
1109	lcr_io_base = pci_resource_start(pcidev, 1);
1110
1111	/*  Enable PCI device and request regions */
1112	if (comedi_pci_enable(pcidev, PCI9111_DRIVER_NAME) < 0) {
1113		printk
1114		    ("comedi%d: Failed to enable PCI device and request regions\n",
1115		     dev->minor);
1116		return -EIO;
1117	}
1118	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
1119
1120	io_base = pci_resource_start(pcidev, 2);
1121
1122	dev->iobase = io_base;
1123	dev->board_name = board->name;
1124	dev_private->is_valid = 0;
1125	dev_private->lcr_io_base = lcr_io_base;
1126
1127	pci9111_reset(dev);
1128
1129	/*  Irq setup */
1130
1131	dev->irq = 0;
1132	if (pcidev->irq > 0) {
1133		dev->irq = pcidev->irq;
1134
1135		if (request_irq(dev->irq, pci9111_interrupt,
1136				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
1137			printk(KERN_ERR
1138				"comedi%d: unable to allocate irq  %u\n",
1139					dev->minor, dev->irq);
1140			return -EINVAL;
1141		}
1142	}
1143
1144	/*  TODO: Add external multiplexer setup (according to option[2]). */
1145
1146	ret = comedi_alloc_subdevices(dev, 4);
1147	if (ret)
1148		return ret;
1149
1150	s = &dev->subdevices[0];
1151	dev->read_subdev = s;
1152	s->type		= COMEDI_SUBD_AI;
1153	s->subdev_flags	= SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
1154	s->n_chan	= 16;
1155	s->maxdata	= 0xffff;
1156	s->len_chanlist	= 16;
1157	s->range_table	= &pci9111_hr_ai_range;
1158	s->cancel	= pci9111_ai_cancel;
1159	s->insn_read	= pci9111_ai_insn_read;
1160	s->do_cmdtest	= pci9111_ai_do_cmd_test;
1161	s->do_cmd	= pci9111_ai_do_cmd;
1162	s->munge	= pci9111_ai_munge;
1163
1164	s = &dev->subdevices[1];
1165	s->type		= COMEDI_SUBD_AO;
1166	s->subdev_flags	= SDF_WRITABLE | SDF_COMMON;
1167	s->n_chan	= 1;
1168	s->maxdata	= 0x0fff;
1169	s->len_chanlist	= 1;
1170	s->range_table	= &range_bipolar10;
1171	s->insn_write	= pci9111_ao_insn_write;
1172	s->insn_read	= pci9111_ao_insn_read;
1173
1174	s = &dev->subdevices[2];
1175	s->type		= COMEDI_SUBD_DI;
1176	s->subdev_flags	= SDF_READABLE;
1177	s->n_chan	= 16;
1178	s->maxdata	= 1;
1179	s->range_table	= &range_digital;
1180	s->insn_bits	= pci9111_di_insn_bits;
1181
1182	s = &dev->subdevices[3];
1183	s->type		= COMEDI_SUBD_DO;
1184	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
1185	s->n_chan	= 16;
1186	s->maxdata	= 1;
1187	s->range_table	= &range_digital;
1188	s->insn_bits	= pci9111_do_insn_bits;
1189
1190	dev_private->is_valid = 1;
1191
1192	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
1193
1194	return 0;
1195}
1196
1197static void pci9111_detach(struct comedi_device *dev)
1198{
1199	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1200	struct pci9111_private_data *dev_private = dev->private;
1201
1202	if (dev_private) {
1203		if (dev_private->is_valid)
1204			pci9111_reset(dev);
1205	}
1206	if (dev->irq != 0)
1207		free_irq(dev->irq, dev);
1208	if (pcidev) {
1209		if (dev->iobase)
1210			comedi_pci_disable(pcidev);
1211		pci_dev_put(pcidev);
1212	}
1213}
1214
1215static struct comedi_driver adl_pci9111_driver = {
1216	.driver_name	= "adl_pci9111",
1217	.module		= THIS_MODULE,
1218	.attach		= pci9111_attach,
1219	.detach		= pci9111_detach,
1220};
1221
1222static int __devinit pci9111_pci_probe(struct pci_dev *dev,
1223				       const struct pci_device_id *ent)
1224{
1225	return comedi_pci_auto_config(dev, &adl_pci9111_driver);
1226}
1227
1228static void __devexit pci9111_pci_remove(struct pci_dev *dev)
1229{
1230	comedi_pci_auto_unconfig(dev);
1231}
1232
1233static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
1234	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
1235	/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
1236	{ 0 }
1237};
1238MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
1239
1240static struct pci_driver adl_pci9111_pci_driver = {
1241	.name		= "adl_pci9111",
1242	.id_table	= pci9111_pci_table,
1243	.probe		= pci9111_pci_probe,
1244	.remove		= __devexit_p(pci9111_pci_remove),
1245};
1246module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
1247
1248MODULE_AUTHOR("Comedi http://www.comedi.org");
1249MODULE_DESCRIPTION("Comedi low-level driver");
1250MODULE_LICENSE("GPL");
1251