adl_pci9111.c revision ce157f8032bbd46d9427034c335b0afd751da25d
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*/
21
22/*
23Driver: adl_pci9111
24Description: Adlink PCI-9111HR
25Author: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
26Devices: [ADLink] PCI-9111HR (adl_pci9111)
27Status: experimental
28
29Supports:
30
31	- ai_insn read
32	- ao_insn read/write
33	- di_insn read
34	- do_insn read/write
35	- ai_do_cmd mode with the following sources:
36
37	- start_src		TRIG_NOW
38	- scan_begin_src	TRIG_FOLLOW	TRIG_TIMER	TRIG_EXT
39	- convert_src				TRIG_TIMER	TRIG_EXT
40	- scan_end_src		TRIG_COUNT
41	- stop_src		TRIG_COUNT	TRIG_NONE
42
43The scanned channels must be consecutive and start from 0. They must
44all have the same range and aref.
45
46Configuration options: not applicable, uses PCI auto config
47*/
48
49/*
50CHANGELOG:
51
522005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
53a multiple of chanlist_len*convert_arg.
542002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
552002/02/18 Added external trigger support for analog input.
56
57TODO:
58
59	- Really test implemented functionality.
60	- Add support for the PCI-9111DG with a probe routine to identify
61	  the card type (perhaps with the help of the channel number readback
62	  of the A/D Data register).
63	- Add external multiplexer support.
64
65*/
66
67#include <linux/module.h>
68#include <linux/pci.h>
69#include <linux/delay.h>
70#include <linux/interrupt.h>
71
72#include "../comedidev.h"
73
74#include "8253.h"
75#include "plx9052.h"
76#include "comedi_fc.h"
77
78#define PCI9111_DRIVER_NAME	"adl_pci9111"
79#define PCI9111_HR_DEVICE_ID	0x9111
80
81#define PCI9111_FIFO_HALF_SIZE	512
82
83#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
84
85#define PCI9111_RANGE_SETTING_DELAY		10
86#define PCI9111_AI_INSTANT_READ_UDELAY_US	2
87#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
88
89#define PCI9111_8254_CLOCK_PERIOD_NS		500
90
91/*
92 * IO address map and bit defines
93 */
94#define PCI9111_AI_FIFO_REG		0x00
95#define PCI9111_AO_REG			0x00
96#define PCI9111_DIO_REG			0x02
97#define PCI9111_EDIO_REG		0x04
98#define PCI9111_AI_CHANNEL_REG		0x06
99#define PCI9111_AI_RANGE_STAT_REG	0x08
100#define PCI9111_AI_STAT_AD_BUSY		(1 << 7)
101#define PCI9111_AI_STAT_FF_FF		(1 << 6)
102#define PCI9111_AI_STAT_FF_HF		(1 << 5)
103#define PCI9111_AI_STAT_FF_EF		(1 << 4)
104#define PCI9111_AI_RANGE_MASK		(7 << 0)
105#define PCI9111_AI_TRIG_CTRL_REG	0x0a
106#define PCI9111_AI_TRIG_CTRL_TRGEVENT	(1 << 5)
107#define PCI9111_AI_TRIG_CTRL_POTRG	(1 << 4)
108#define PCI9111_AI_TRIG_CTRL_PTRG	(1 << 3)
109#define PCI9111_AI_TRIG_CTRL_ETIS	(1 << 2)
110#define PCI9111_AI_TRIG_CTRL_TPST	(1 << 1)
111#define PCI9111_AI_TRIG_CTRL_ASCAN	(1 << 0)
112#define PCI9111_INT_CTRL_REG		0x0c
113#define PCI9111_INT_CTRL_ISC2		(1 << 3)
114#define PCI9111_INT_CTRL_FFEN		(1 << 2)
115#define PCI9111_INT_CTRL_ISC1		(1 << 1)
116#define PCI9111_INT_CTRL_ISC0		(1 << 0)
117#define PCI9111_SOFT_TRIG_REG		0x0e
118#define PCI9111_8254_BASE_REG		0x40
119#define PCI9111_INT_CLR_REG		0x48
120
121/* PLX 9052 Local Interrupt 1 enabled and active */
122#define PCI9111_LI1_ACTIVE	(PLX9052_INTCSR_LI1ENAB |	\
123				 PLX9052_INTCSR_LI1STAT)
124
125/* PLX 9052 Local Interrupt 2 enabled and active */
126#define PCI9111_LI2_ACTIVE	(PLX9052_INTCSR_LI2ENAB |	\
127				 PLX9052_INTCSR_LI2STAT)
128
129static const struct comedi_lrange pci9111_ai_range = {
130	5,
131	{
132		BIP_RANGE(10),
133		BIP_RANGE(5),
134		BIP_RANGE(2.5),
135		BIP_RANGE(1.25),
136		BIP_RANGE(0.625)
137	}
138};
139
140struct pci9111_private_data {
141	unsigned long lcr_io_base;
142
143	int stop_counter;
144	int stop_is_none;
145
146	unsigned int scan_delay;
147	unsigned int chanlist_len;
148	unsigned int chunk_counter;
149	unsigned int chunk_num_samples;
150
151	int ao_readback;
152
153	unsigned int div1;
154	unsigned int div2;
155
156	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
157};
158
159static void plx9050_interrupt_control(unsigned long io_base,
160				      bool LINTi1_enable,
161				      bool LINTi1_active_high,
162				      bool LINTi2_enable,
163				      bool LINTi2_active_high,
164				      bool interrupt_enable)
165{
166	int flags = 0;
167
168	if (LINTi1_enable)
169		flags |= PLX9052_INTCSR_LI1ENAB;
170	if (LINTi1_active_high)
171		flags |= PLX9052_INTCSR_LI1POL;
172	if (LINTi2_enable)
173		flags |= PLX9052_INTCSR_LI2ENAB;
174	if (LINTi2_active_high)
175		flags |= PLX9052_INTCSR_LI2POL;
176
177	if (interrupt_enable)
178		flags |= PLX9052_INTCSR_PCIENAB;
179
180	outb(flags, io_base + PLX9052_INTCSR);
181}
182
183static void pci9111_timer_set(struct comedi_device *dev)
184{
185	struct pci9111_private_data *dev_private = dev->private;
186	unsigned long timer_base = dev->iobase + PCI9111_8254_BASE_REG;
187
188	i8254_set_mode(timer_base, 1, 0, I8254_MODE0 | I8254_BINARY);
189	i8254_set_mode(timer_base, 1, 1, I8254_MODE2 | I8254_BINARY);
190	i8254_set_mode(timer_base, 1, 2, I8254_MODE2 | I8254_BINARY);
191
192	udelay(1);
193
194	i8254_write(timer_base, 1, 2, dev_private->div2);
195	i8254_write(timer_base, 1, 1, dev_private->div1);
196}
197
198enum pci9111_trigger_sources {
199	software,
200	timer_pacer,
201	external
202};
203
204static void pci9111_trigger_source_set(struct comedi_device *dev,
205				       enum pci9111_trigger_sources source)
206{
207	int flags;
208
209	/* Read the current trigger mode control bits */
210	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
211	/* Mask off the EITS and TPST bits */
212	flags &= 0x9;
213
214	switch (source) {
215	case software:
216		break;
217
218	case timer_pacer:
219		flags |= PCI9111_AI_TRIG_CTRL_TPST;
220		break;
221
222	case external:
223		flags |= PCI9111_AI_TRIG_CTRL_ETIS;
224		break;
225	}
226
227	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
228}
229
230static void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
231{
232	int flags;
233
234	/* Read the current trigger mode control bits */
235	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
236	/* Mask off the PTRG bit */
237	flags &= 0x7;
238
239	if (pretrigger)
240		flags |= PCI9111_AI_TRIG_CTRL_PTRG;
241
242	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
243}
244
245static void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
246{
247	int flags;
248
249	/* Read the current trigger mode control bits */
250	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
251	/* Mask off the ASCAN bit */
252	flags &= 0xe;
253
254	if (autoscan)
255		flags |= PCI9111_AI_TRIG_CTRL_ASCAN;
256
257	outb(flags, dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
258}
259
260enum pci9111_ISC0_sources {
261	irq_on_eoc,
262	irq_on_fifo_half_full
263};
264
265enum pci9111_ISC1_sources {
266	irq_on_timer_tick,
267	irq_on_external_trigger
268};
269
270static void pci9111_interrupt_source_set(struct comedi_device *dev,
271					 enum pci9111_ISC0_sources irq_0_source,
272					 enum pci9111_ISC1_sources irq_1_source)
273{
274	int flags;
275
276	/* Read the current interrupt control bits */
277	flags = inb(dev->iobase + PCI9111_AI_TRIG_CTRL_REG);
278	/* Shift the bits so they are compatible with the write register */
279	flags >>= 4;
280	/* Mask off the ISCx bits */
281	flags &= 0xc0;
282
283	/* Now set the new ISCx bits */
284	if (irq_0_source == irq_on_fifo_half_full)
285		flags |= PCI9111_INT_CTRL_ISC0;
286
287	if (irq_1_source == irq_on_external_trigger)
288		flags |= PCI9111_INT_CTRL_ISC1;
289
290	outb(flags, dev->iobase + PCI9111_INT_CTRL_REG);
291}
292
293static void pci9111_fifo_reset(struct comedi_device *dev)
294{
295	unsigned long int_ctrl_reg = dev->iobase + PCI9111_INT_CTRL_REG;
296
297	/* To reset the FIFO, set FFEN sequence as 0 -> 1 -> 0 */
298	outb(0, int_ctrl_reg);
299	outb(PCI9111_INT_CTRL_FFEN, int_ctrl_reg);
300	outb(0, int_ctrl_reg);
301}
302
303static int pci9111_ai_cancel(struct comedi_device *dev,
304			     struct comedi_subdevice *s)
305{
306	struct pci9111_private_data *dev_private = dev->private;
307
308	/*  Disable interrupts */
309	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
310				  true, false);
311
312	pci9111_trigger_source_set(dev, software);
313
314	pci9111_autoscan_set(dev, false);
315
316	pci9111_fifo_reset(dev);
317
318	return 0;
319}
320
321static int pci9111_ai_do_cmd_test(struct comedi_device *dev,
322				  struct comedi_subdevice *s,
323				  struct comedi_cmd *cmd)
324{
325	struct pci9111_private_data *dev_private = dev->private;
326	int tmp;
327	int error = 0;
328	int range, reference;
329	int i;
330
331	/* Step 1 : check if triggers are trivially valid */
332
333	error |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
334	error |= cfc_check_trigger_src(&cmd->scan_begin_src,
335					TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
336	error |= cfc_check_trigger_src(&cmd->convert_src,
337					TRIG_TIMER | TRIG_EXT);
338	error |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
339	error |= cfc_check_trigger_src(&cmd->stop_src,
340					TRIG_COUNT | TRIG_NONE);
341
342	if (error)
343		return 1;
344
345	/* Step 2a : make sure trigger sources are unique */
346
347	error |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
348	error |= cfc_check_trigger_is_unique(cmd->convert_src);
349	error |= cfc_check_trigger_is_unique(cmd->stop_src);
350
351	/* Step 2b : and mutually compatible */
352
353	if ((cmd->convert_src == TRIG_TIMER) &&
354	    !((cmd->scan_begin_src == TRIG_TIMER) ||
355	      (cmd->scan_begin_src == TRIG_FOLLOW)))
356		error |= -EINVAL;
357	if ((cmd->convert_src == TRIG_EXT) &&
358	    !((cmd->scan_begin_src == TRIG_EXT) ||
359	      (cmd->scan_begin_src == TRIG_FOLLOW)))
360		error |= -EINVAL;
361
362	if (error)
363		return 2;
364
365	/* Step 3: check if arguments are trivially valid */
366
367	error |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
368
369	if (cmd->convert_src == TRIG_TIMER)
370		error |= cfc_check_trigger_arg_min(&cmd->convert_arg,
371					PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
372	else	/* TRIG_EXT */
373		error |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
374
375	if (cmd->scan_begin_src == TRIG_TIMER)
376		error |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
377					PCI9111_AI_ACQUISITION_PERIOD_MIN_NS);
378	else	/* TRIG_FOLLOW || TRIG_EXT */
379		error |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
380
381	error |= cfc_check_trigger_arg_is(&cmd->scan_end_arg,
382					  cmd->chanlist_len);
383
384	if (cmd->stop_src == TRIG_COUNT)
385		error |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
386	else	/* TRIG_NONE */
387		error |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
388
389	if (error)
390		return 3;
391
392	/*  Step 4 : fix up any arguments */
393
394	if (cmd->convert_src == TRIG_TIMER) {
395		tmp = cmd->convert_arg;
396		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
397					       &dev_private->div1,
398					       &dev_private->div2,
399					       &cmd->convert_arg,
400					       cmd->flags & TRIG_ROUND_MASK);
401		if (tmp != cmd->convert_arg)
402			error++;
403	}
404	/*  There's only one timer on this card, so the scan_begin timer must */
405	/*  be a multiple of chanlist_len*convert_arg */
406
407	if (cmd->scan_begin_src == TRIG_TIMER) {
408
409		unsigned int scan_begin_min;
410		unsigned int scan_begin_arg;
411		unsigned int scan_factor;
412
413		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
414
415		if (cmd->scan_begin_arg != scan_begin_min) {
416			if (scan_begin_min < cmd->scan_begin_arg) {
417				scan_factor =
418				    cmd->scan_begin_arg / scan_begin_min;
419				scan_begin_arg = scan_factor * scan_begin_min;
420				if (cmd->scan_begin_arg != scan_begin_arg) {
421					cmd->scan_begin_arg = scan_begin_arg;
422					error++;
423				}
424			} else {
425				cmd->scan_begin_arg = scan_begin_min;
426				error++;
427			}
428		}
429	}
430
431	if (error)
432		return 4;
433
434	/*  Step 5 : check channel list */
435
436	if (cmd->chanlist) {
437
438		range = CR_RANGE(cmd->chanlist[0]);
439		reference = CR_AREF(cmd->chanlist[0]);
440
441		if (cmd->chanlist_len > 1) {
442			for (i = 0; i < cmd->chanlist_len; i++) {
443				if (CR_CHAN(cmd->chanlist[i]) != i) {
444					comedi_error(dev,
445						     "entries in chanlist must be consecutive "
446						     "channels,counting upwards from 0\n");
447					error++;
448				}
449				if (CR_RANGE(cmd->chanlist[i]) != range) {
450					comedi_error(dev,
451						     "entries in chanlist must all have the same gain\n");
452					error++;
453				}
454				if (CR_AREF(cmd->chanlist[i]) != reference) {
455					comedi_error(dev,
456						     "entries in chanlist must all have the same reference\n");
457					error++;
458				}
459			}
460		}
461	}
462
463	if (error)
464		return 5;
465
466	return 0;
467
468}
469
470static int pci9111_ai_do_cmd(struct comedi_device *dev,
471			     struct comedi_subdevice *s)
472{
473	struct pci9111_private_data *dev_private = dev->private;
474	struct comedi_cmd *async_cmd = &s->async->cmd;
475
476	if (!dev->irq) {
477		comedi_error(dev,
478			     "no irq assigned for PCI9111, cannot do hardware conversion");
479		return -1;
480	}
481	/*  Set channel scan limit */
482	/*  PCI9111 allows only scanning from channel 0 to channel n */
483	/*  TODO: handle the case of an external multiplexer */
484
485	if (async_cmd->chanlist_len > 1) {
486		outb(async_cmd->chanlist_len - 1,
487			dev->iobase + PCI9111_AI_CHANNEL_REG);
488		pci9111_autoscan_set(dev, true);
489	} else {
490		outb(CR_CHAN(async_cmd->chanlist[0]),
491			dev->iobase + PCI9111_AI_CHANNEL_REG);
492		pci9111_autoscan_set(dev, false);
493	}
494
495	/*  Set gain */
496	/*  This is the same gain on every channel */
497
498	outb(CR_RANGE(async_cmd->chanlist[0]) & PCI9111_AI_RANGE_MASK,
499		dev->iobase + PCI9111_AI_RANGE_STAT_REG);
500
501	/* Set counter */
502
503	switch (async_cmd->stop_src) {
504	case TRIG_COUNT:
505		dev_private->stop_counter =
506		    async_cmd->stop_arg * async_cmd->chanlist_len;
507		dev_private->stop_is_none = 0;
508		break;
509
510	case TRIG_NONE:
511		dev_private->stop_counter = 0;
512		dev_private->stop_is_none = 1;
513		break;
514
515	default:
516		comedi_error(dev, "Invalid stop trigger");
517		return -1;
518	}
519
520	/*  Set timer pacer */
521
522	dev_private->scan_delay = 0;
523	switch (async_cmd->convert_src) {
524	case TRIG_TIMER:
525		pci9111_trigger_source_set(dev, software);
526		pci9111_timer_set(dev);
527		pci9111_fifo_reset(dev);
528		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
529					     irq_on_timer_tick);
530		pci9111_trigger_source_set(dev, timer_pacer);
531		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
532					  false, true, true);
533
534		if (async_cmd->scan_begin_src == TRIG_TIMER) {
535			dev_private->scan_delay =
536				(async_cmd->scan_begin_arg /
537				 (async_cmd->convert_arg *
538				  async_cmd->chanlist_len)) - 1;
539		}
540
541		break;
542
543	case TRIG_EXT:
544
545		pci9111_trigger_source_set(dev, external);
546		pci9111_fifo_reset(dev);
547		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
548					     irq_on_timer_tick);
549		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
550					  false, true, true);
551
552		break;
553
554	default:
555		comedi_error(dev, "Invalid convert trigger");
556		return -1;
557	}
558
559	dev_private->stop_counter *= (1 + dev_private->scan_delay);
560	dev_private->chanlist_len = async_cmd->chanlist_len;
561	dev_private->chunk_counter = 0;
562	dev_private->chunk_num_samples =
563	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
564
565	return 0;
566}
567
568static void pci9111_ai_munge(struct comedi_device *dev,
569			     struct comedi_subdevice *s, void *data,
570			     unsigned int num_bytes,
571			     unsigned int start_chan_index)
572{
573	short *array = data;
574	unsigned int maxdata = s->maxdata;
575	unsigned int invert = (maxdata + 1) >> 1;
576	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
577	unsigned int num_samples = num_bytes / sizeof(short);
578	unsigned int i;
579
580	for (i = 0; i < num_samples; i++)
581		array[i] = ((array[i] >> shift) & maxdata) ^ invert;
582}
583
584static irqreturn_t pci9111_interrupt(int irq, void *p_device)
585{
586	struct comedi_device *dev = p_device;
587	struct pci9111_private_data *dev_private = dev->private;
588	struct comedi_subdevice *s = dev->read_subdev;
589	struct comedi_async *async;
590	unsigned int status;
591	unsigned long irq_flags;
592	unsigned char intcsr;
593
594	if (!dev->attached) {
595		/*  Ignore interrupt before device fully attached. */
596		/*  Might not even have allocated subdevices yet! */
597		return IRQ_NONE;
598	}
599
600	async = s->async;
601
602	spin_lock_irqsave(&dev->spinlock, irq_flags);
603
604	/*  Check if we are source of interrupt */
605	intcsr = inb(dev_private->lcr_io_base + PLX9052_INTCSR);
606	if (!(((intcsr & PLX9052_INTCSR_PCIENAB) != 0) &&
607	      (((intcsr & PCI9111_LI1_ACTIVE) == PCI9111_LI1_ACTIVE) ||
608	       ((intcsr & PCI9111_LI2_ACTIVE) == PCI9111_LI2_ACTIVE)))) {
609		/*  Not the source of the interrupt. */
610		/*  (N.B. not using PLX9052_INTCSR_SOFTINT) */
611		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
612		return IRQ_NONE;
613	}
614
615	if ((intcsr & PCI9111_LI1_ACTIVE) == PCI9111_LI1_ACTIVE) {
616		/*  Interrupt comes from fifo_half-full signal */
617
618		status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
619
620		/* '0' means FIFO is full, data may have been lost */
621		if (!(status & PCI9111_AI_STAT_FF_FF)) {
622			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
623			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
624			outb(0, dev->iobase + PCI9111_INT_CLR_REG);
625			pci9111_ai_cancel(dev, s);
626			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
627			comedi_event(dev, s);
628
629			return IRQ_HANDLED;
630		}
631
632		/* '0' means FIFO is half-full */
633		if (!(status & PCI9111_AI_STAT_FF_HF)) {
634			unsigned int num_samples;
635			unsigned int bytes_written = 0;
636
637			num_samples =
638			    PCI9111_FIFO_HALF_SIZE >
639			    dev_private->stop_counter
640			    && !dev_private->
641			    stop_is_none ? dev_private->stop_counter :
642			    PCI9111_FIFO_HALF_SIZE;
643			insw(dev->iobase + PCI9111_AI_FIFO_REG,
644			     dev_private->ai_bounce_buffer, num_samples);
645
646			if (dev_private->scan_delay < 1) {
647				bytes_written =
648				    cfc_write_array_to_buffer(s,
649							      dev_private->
650							      ai_bounce_buffer,
651							      num_samples *
652							      sizeof(short));
653			} else {
654				int position = 0;
655				int to_read;
656
657				while (position < num_samples) {
658					if (dev_private->chunk_counter <
659					    dev_private->chanlist_len) {
660						to_read =
661						    dev_private->chanlist_len -
662						    dev_private->chunk_counter;
663
664						if (to_read >
665						    num_samples - position)
666							to_read =
667							    num_samples -
668							    position;
669
670						bytes_written +=
671						    cfc_write_array_to_buffer
672						    (s,
673						     dev_private->ai_bounce_buffer
674						     + position,
675						     to_read * sizeof(short));
676					} else {
677						to_read =
678						    dev_private->chunk_num_samples
679						    -
680						    dev_private->chunk_counter;
681						if (to_read >
682						    num_samples - position)
683							to_read =
684							    num_samples -
685							    position;
686
687						bytes_written +=
688						    sizeof(short) * to_read;
689					}
690
691					position += to_read;
692					dev_private->chunk_counter += to_read;
693
694					if (dev_private->chunk_counter >=
695					    dev_private->chunk_num_samples)
696						dev_private->chunk_counter = 0;
697				}
698			}
699
700			dev_private->stop_counter -=
701			    bytes_written / sizeof(short);
702		}
703	}
704
705	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
706		async->events |= COMEDI_CB_EOA;
707		pci9111_ai_cancel(dev, s);
708	}
709
710	outb(0, dev->iobase + PCI9111_INT_CLR_REG);
711
712	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
713
714	comedi_event(dev, s);
715
716	return IRQ_HANDLED;
717}
718
719static int pci9111_ai_insn_read(struct comedi_device *dev,
720				struct comedi_subdevice *s,
721				struct comedi_insn *insn, unsigned int *data)
722{
723	unsigned int chan = CR_CHAN(insn->chanspec);
724	unsigned int range = CR_RANGE(insn->chanspec);
725	unsigned int maxdata = s->maxdata;
726	unsigned int invert = (maxdata + 1) >> 1;
727	unsigned int shift = (maxdata == 0xffff) ? 0 : 4;
728	unsigned int status;
729	int timeout;
730	int i;
731
732	outb(chan, dev->iobase + PCI9111_AI_CHANNEL_REG);
733
734	status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
735	if ((status & PCI9111_AI_RANGE_MASK) != range) {
736		outb(range & PCI9111_AI_RANGE_MASK,
737			dev->iobase + PCI9111_AI_RANGE_STAT_REG);
738	}
739
740	pci9111_fifo_reset(dev);
741
742	for (i = 0; i < insn->n; i++) {
743		/* Generate a software trigger */
744		outb(0, dev->iobase + PCI9111_SOFT_TRIG_REG);
745
746		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
747
748		while (timeout--) {
749			status = inb(dev->iobase + PCI9111_AI_RANGE_STAT_REG);
750			/* '1' means FIFO is not empty */
751			if (status & PCI9111_AI_STAT_FF_EF)
752				goto conversion_done;
753		}
754
755		comedi_error(dev, "A/D read timeout");
756		data[i] = 0;
757		pci9111_fifo_reset(dev);
758		return -ETIME;
759
760conversion_done:
761
762		data[i] = inw(dev->iobase + PCI9111_AI_FIFO_REG);
763		data[i] = ((data[i] >> shift) & maxdata) ^ invert;
764	}
765
766	return i;
767}
768
769static int pci9111_ao_insn_write(struct comedi_device *dev,
770				 struct comedi_subdevice *s,
771				 struct comedi_insn *insn,
772				 unsigned int *data)
773{
774	struct pci9111_private_data *dev_private = dev->private;
775	unsigned int val = 0;
776	int i;
777
778	for (i = 0; i < insn->n; i++) {
779		val = data[i];
780		outw(val, dev->iobase + PCI9111_AO_REG);
781	}
782	dev_private->ao_readback = val;
783
784	return insn->n;
785}
786
787static int pci9111_ao_insn_read(struct comedi_device *dev,
788				struct comedi_subdevice *s,
789				struct comedi_insn *insn,
790				unsigned int *data)
791{
792	struct pci9111_private_data *dev_private = dev->private;
793	int i;
794
795	for (i = 0; i < insn->n; i++)
796		data[i] = dev_private->ao_readback;
797
798	return insn->n;
799}
800
801static int pci9111_di_insn_bits(struct comedi_device *dev,
802				struct comedi_subdevice *s,
803				struct comedi_insn *insn,
804				unsigned int *data)
805{
806	data[1] = inw(dev->iobase + PCI9111_DIO_REG);
807
808	return insn->n;
809}
810
811static int pci9111_do_insn_bits(struct comedi_device *dev,
812				struct comedi_subdevice *s,
813				struct comedi_insn *insn,
814				unsigned int *data)
815{
816	unsigned int mask = data[0];
817	unsigned int bits = data[1];
818
819	if (mask) {
820		s->state &= ~mask;
821		s->state |= (bits & mask);
822
823		outw(s->state, dev->iobase + PCI9111_DIO_REG);
824	}
825
826	data[1] = s->state;
827
828	return insn->n;
829}
830
831static int pci9111_reset(struct comedi_device *dev)
832{
833	struct pci9111_private_data *dev_private = dev->private;
834
835	/*  Set trigger source to software */
836	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
837				  true, false);
838
839	pci9111_trigger_source_set(dev, software);
840	pci9111_pretrigger_set(dev, false);
841	pci9111_autoscan_set(dev, false);
842
843	/* Reset 8254 chip */
844	dev_private->div1 = 0;
845	dev_private->div2 = 0;
846	pci9111_timer_set(dev);
847
848	return 0;
849}
850
851static int pci9111_auto_attach(struct comedi_device *dev,
852					 unsigned long context_unused)
853{
854	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
855	struct pci9111_private_data *dev_private;
856	struct comedi_subdevice *s;
857	int ret;
858
859	dev_private = comedi_alloc_devpriv(dev, sizeof(*dev_private));
860	if (!dev_private)
861		return -ENOMEM;
862
863	ret = comedi_pci_enable(dev);
864	if (ret)
865		return ret;
866	dev_private->lcr_io_base = pci_resource_start(pcidev, 1);
867	dev->iobase = pci_resource_start(pcidev, 2);
868
869	pci9111_reset(dev);
870
871	if (pcidev->irq > 0) {
872		ret = request_irq(dev->irq, pci9111_interrupt,
873				  IRQF_SHARED, dev->board_name, dev);
874		if (ret)
875			return ret;
876		dev->irq = pcidev->irq;
877	}
878
879	ret = comedi_alloc_subdevices(dev, 4);
880	if (ret)
881		return ret;
882
883	s = &dev->subdevices[0];
884	dev->read_subdev = s;
885	s->type		= COMEDI_SUBD_AI;
886	s->subdev_flags	= SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
887	s->n_chan	= 16;
888	s->maxdata	= 0xffff;
889	s->len_chanlist	= 16;
890	s->range_table	= &pci9111_ai_range;
891	s->cancel	= pci9111_ai_cancel;
892	s->insn_read	= pci9111_ai_insn_read;
893	s->do_cmdtest	= pci9111_ai_do_cmd_test;
894	s->do_cmd	= pci9111_ai_do_cmd;
895	s->munge	= pci9111_ai_munge;
896
897	s = &dev->subdevices[1];
898	s->type		= COMEDI_SUBD_AO;
899	s->subdev_flags	= SDF_WRITABLE | SDF_COMMON;
900	s->n_chan	= 1;
901	s->maxdata	= 0x0fff;
902	s->len_chanlist	= 1;
903	s->range_table	= &range_bipolar10;
904	s->insn_write	= pci9111_ao_insn_write;
905	s->insn_read	= pci9111_ao_insn_read;
906
907	s = &dev->subdevices[2];
908	s->type		= COMEDI_SUBD_DI;
909	s->subdev_flags	= SDF_READABLE;
910	s->n_chan	= 16;
911	s->maxdata	= 1;
912	s->range_table	= &range_digital;
913	s->insn_bits	= pci9111_di_insn_bits;
914
915	s = &dev->subdevices[3];
916	s->type		= COMEDI_SUBD_DO;
917	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
918	s->n_chan	= 16;
919	s->maxdata	= 1;
920	s->range_table	= &range_digital;
921	s->insn_bits	= pci9111_do_insn_bits;
922
923	dev_info(dev->class_dev, "%s attached\n", dev->board_name);
924
925	return 0;
926}
927
928static void pci9111_detach(struct comedi_device *dev)
929{
930	if (dev->iobase)
931		pci9111_reset(dev);
932	if (dev->irq != 0)
933		free_irq(dev->irq, dev);
934	comedi_pci_disable(dev);
935}
936
937static struct comedi_driver adl_pci9111_driver = {
938	.driver_name	= "adl_pci9111",
939	.module		= THIS_MODULE,
940	.auto_attach	= pci9111_auto_attach,
941	.detach		= pci9111_detach,
942};
943
944static int pci9111_pci_probe(struct pci_dev *dev,
945			     const struct pci_device_id *id)
946{
947	return comedi_pci_auto_config(dev, &adl_pci9111_driver,
948				      id->driver_data);
949}
950
951static DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
952	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
953	/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
954	{ 0 }
955};
956MODULE_DEVICE_TABLE(pci, pci9111_pci_table);
957
958static struct pci_driver adl_pci9111_pci_driver = {
959	.name		= "adl_pci9111",
960	.id_table	= pci9111_pci_table,
961	.probe		= pci9111_pci_probe,
962	.remove		= comedi_pci_auto_unconfig,
963};
964module_comedi_pci_driver(adl_pci9111_driver, adl_pci9111_pci_driver);
965
966MODULE_AUTHOR("Comedi http://www.comedi.org");
967MODULE_DESCRIPTION("Comedi low-level driver");
968MODULE_LICENSE("GPL");
969