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