adl_pci9111.c revision 8522e70b44021d1cc44de1f6c491ac21cc8f4f3d
18cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
28cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsoncomedi/drivers/adl_pci9111.c
48cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonHardware driver for PCI9111 ADLink cards:
68cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonPCI-9111HR
88cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonCopyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonThis program is free software; you can redistribute it and/or modify
12842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsonit under the terms of the GNU General Public License as published by
13842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsonthe Free Software Foundation; either version 2 of the License, or
14842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson(at your option) any later version.
158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
16842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonThis program is distributed in the hope that it will be useful,
17842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsonbut WITHOUT ANY WARRANTY; without even the implied warranty of
18842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonGNU General Public License for more details.
208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
21842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonYou should have received a copy of the GNU General Public License
22842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsonalong with this program; if not, write to the Free Software
23842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonFoundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudDriver: adl_pci9111
288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudDescription: Adlink PCI-9111HR
298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudAuthor: Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudDevices: [ADLink] PCI-9111HR (adl_pci9111)
318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudStatus: experimental
328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudSupports:
348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
35842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- ai_insn read
36842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- ao_insn read/write
37842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- di_insn read
38842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- do_insn read/write
39842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- ai_do_cmd mode with the following sources:
408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- start_src		TRIG_NOW
42842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- scan_begin_src	TRIG_FOLLOW	TRIG_TIMER	TRIG_EXT
43842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- convert_src				TRIG_TIMER	TRIG_EXT
44842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- scan_end_src		TRIG_COUNT
45842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- stop_src		TRIG_COUNT	TRIG_NONE
468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
47842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonThe scanned channels must be consecutive and start from 0. They must
48842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsonall have the same range and aref.
498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudConfiguration options:
518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
52842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	[0] - PCI bus number (optional)
53842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	[1] - PCI slot number (optional)
548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
55842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice DawsonIf bus/slot is not specified, the first available PCI
56842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsondevice will be used.
578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudCHANGELOG:
628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
63842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
64842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawsona multiple of chanlist_len*convert_arg.
65842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
66842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson2002/02/18 Added external trigger support for analog input.
678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudTODO:
698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
70842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- Really test implemented functionality.
71842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- Add support for the PCI-9111DG with a probe routine to identify
72842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	  the card type (perhaps with the help of the channel number readback
73842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	  of the A/D Data register).
74842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	- Add external multiplexer support.
758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "../comedidev.h"
798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include <linux/delay.h>
8170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "8253.h"
848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_pci.h"
858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_fc.h"
868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
872f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_DRIVER_NAME	"adl_pci9111"
882f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_HR_DEVICE_ID	0x9111
898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  TODO: Add other pci9111 board id */
918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
922f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_IO_RANGE	0x0100
938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_SIZE	512
958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_CHANNEL_NBR			16
978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION			12
998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_MASK		0x0FFF
1008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_2_CMP_BIT		0x0800
1018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION		16
1038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_MASK		0xFFFF
1048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT	0x8000
1058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
1078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_CHANNEL_NBR			1
1088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_AO_RESOLUTION			12
1098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_RESOLUTION_MASK		0x0FFF
1108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DI_CHANNEL_NBR			16
1118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_DO_CHANNEL_NBR			16
1128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DO_MASK				0xFFFF
1138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_SETTING_DELAY		10
1158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_UDELAY_US	2
1168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
1178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_CLOCK_PERIOD_NS		500
1198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_0			0x00
1218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_1			0x40
1228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_2			0x80
1238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_LATCH		0x00
1248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_ONLY		0x10
1258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_MSB_ONLY		0x20
1268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_MSB		0x30
1278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_0			0x00
1288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_1			0x02
1298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_2			0x04
1308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_3			0x06
1318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_4			0x08
1328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_5			0x0A
1338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BINARY_COUNTER		0x00
1348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BCD_COUNTER		0x01
1358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/* IO address map */
1378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1382f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_FIFO_VALUE			0x00 /* AD Data stored
1392f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor								in FIFO */
1402f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_DA_OUTPUT			0x00
1412f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_DIGITAL_IO			0x02
1422f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_EXTENDED_IO_PORTS		0x04
1432f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_CHANNEL_CONTROL		0x06 /* Channel
1442f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor								selection */
1452f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_CHANNEL_READBACK		0x06
1462f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE		0x08
1472f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_RANGE_STATUS_READBACK		0x08
1482f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL		0x0A
1492f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK	0x0A
1502f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_SOFTWARE_TRIGGER		0x0E
1512f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INTERRUPT_CONTROL		0x0C
1528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_0			0x40
1538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_1			0x42
1542f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_8254_COUNTER_2			0X44
1558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_CONTROL			0x46
1562f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INTERRUPT_CLEAR		0x48
1578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1582f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_TRIGGER_MASK				0x0F
1592f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_PTRG_OFF				(0 << 3)
1602f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_PTRG_ON					(1 << 3)
1618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_EXTERNAL				(1 << 2)
1628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_INTERNAL				(0 << 2)
1638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_SOFTWARE_TRIGGER			(0 << 1)
1648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_TIMER_PACER			(1 << 1)
1658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_ON				(1 << 0)
1668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_OFF				(0 << 0)
1678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
1698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL		(1 << 0)
1702f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK		(0 << 1)
1712f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG			(1 << 1)
1722f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_FFEN_SET_FIFO_ENABLE			(0 << 2)
1738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FFEN_SET_FIFO_DISABLE			(1 << 2)
1748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_CHANNEL_MASK				0x0F
1768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_MASK				0x07
1788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_EMPTY_MASK				0x10
1798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_FULL_MASK			0x20
1808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_FULL_MASK				0x40
1818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AD_BUSY_MASK				0x80
1828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1832f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_IO_BASE (dev->iobase)
1848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
1868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud * Define inlined function
1878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud */
1888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_get() \
190842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
1918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_set(flags) \
193842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
1948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
195842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_interrupt_and_fifo_get() \
196842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) \
197842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		>> 4) & 0x03)
1988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_and_fifo_set(flags) \
200842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
2018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_clear() \
203842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
2048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_software_trigger() \
206842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
2078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
208842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_fifo_reset() do { \
209842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
210842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
211842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(PCI9111_FFEN_SET_FIFO_DISABLE, \
212842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
213842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(PCI9111_FFEN_SET_FIFO_ENABLE, \
214842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
215842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	} while (0)
2168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_full() \
218842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
219842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_FIFO_FULL_MASK) == 0)
2208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_half_full() \
222842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
223842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_FIFO_HALF_FULL_MASK) == 0)
2248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_empty() \
226842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
227842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_FIFO_EMPTY_MASK) == 0)
2288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
229842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ai_channel_set(channel) \
230842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb((channel)&PCI9111_CHANNEL_MASK, \
231842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
2328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
233842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ai_channel_get() \
234842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK) \
235842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		&PCI9111_CHANNEL_MASK)
2368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
237842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ai_range_set(range) \
238842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb((range)&PCI9111_RANGE_MASK, \
239842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
2408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
241842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ai_range_get() \
242842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK) \
243842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		&PCI9111_RANGE_MASK)
2448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
245842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ai_get_data() \
246842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4) \
247842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		&PCI9111_AI_RESOLUTION_MASK) \
248842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson			^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
2498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
250842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_hr_ai_get_data() \
251842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) \
252842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		&PCI9111_HR_AI_RESOLUTION_MASK) \
253842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson			^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT)
2548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
255842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson#define pci9111_ao_set_data(data) \
256842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outw(data&PCI9111_AO_RESOLUTION_MASK, \
257842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
2588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_di_get_bits() \
260842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_do_set_bits(bits) \
263842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_control_set(flags) \
266842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
2678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_0_set(data) \
2698be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	do { \
2708be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson		outb(data & 0xFF, \
2718be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
272842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
2738be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
2748be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	} while (0)
2758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_1_set(data) \
2778be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	do { \
2788be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson		outb(data & 0xFF, \
2798be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
280842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
2818be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
2828be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	} while (0)
2838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_2_set(data) \
2858be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	do { \
2868be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson		outb(data & 0xFF, \
2878be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
288842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
2898be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
2908be11ffcf59e9bcb5f0a2a2b2e7b43d56c797b98Maurice Dawson	} while (0)
2918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
29252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Function prototypes */
2938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
2950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
296da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev);
2970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index);
3018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3029ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange pci9111_hr_ai_range = {
3038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	5,
3048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
3070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
3080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
3090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.625)
3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
3118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
3147ecac4c38a813021155c4207592693ad1949b9b7Mark	{ PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
3157ecac4c38a813021155c4207592693ad1949b9b7Mark	  0, 0, 0 },
3167ecac4c38a813021155c4207592693ad1949b9b7Mark	/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
3177ecac4c38a813021155c4207592693ad1949b9b7Mark	 *   0, 0, 0 }, */
3187ecac4c38a813021155c4207592693ad1949b9b7Mark	{ 0 }
3198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
3228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
32352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
32452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
32552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
3268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
327940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
32852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
3298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
33052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
33152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
33252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
33452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
33652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
33752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
339940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
341940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci9111_hr",
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = PCI9111_HR_DEVICE_ID,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution = PCI9111_HR_AI_RESOLUTION,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution = PCI9111_AO_RESOLUTION,
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range_list = &pci9111_hr_ai_range,
3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_range_list = &range_bipolar10,
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
357842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
359139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
36068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PCI9111_DRIVER_NAME,
36168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
36268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pci9111_attach,
36368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pci9111_detach,
3648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
366727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
367727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					      const struct pci_device_id *ent)
368727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
369727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
370727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
371727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
372727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
373727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
374727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
375727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
376727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
377727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver pci9111_driver_pci_driver = {
378727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = pci9111_pci_table,
379727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &pci9111_driver_pci_probe,
380727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&pci9111_driver_pci_remove)
381727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
382727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
383727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init pci9111_driver_init_module(void)
384727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
385727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
386727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
387727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&pci9111_driver);
388727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
389727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
390727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
391727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
392727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&pci9111_driver_pci_driver);
393727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
394727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
395727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit pci9111_driver_cleanup_module(void)
396727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
397727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&pci9111_driver_pci_driver);
398727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&pci9111_driver);
399727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
400727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
401727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(pci9111_driver_init_module);
402727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(pci9111_driver_cleanup_module);
4038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
40452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
4058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
406c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
4078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
40852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
4098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4107ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned long lcr_io_base; /* Local configuration register base
4117ecac4c38a813021155c4207592693ad1949b9b7Mark				    * address */
4128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
4138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
4158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
4168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
4188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
4198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
4208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
4218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
4238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4247ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
4257ecac4c38a813021155c4207592693ad1949b9b7Mark				       * pacer */
426525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	unsigned int timer_divisor_2;
4278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
4298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
430790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
431c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4337ecac4c38a813021155c4207592693ad1949b9b7Mark#define dev_private	((struct pci9111_private_data *)dev->private)
4348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
43552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
43652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
43752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
4408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
4428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
4438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
4448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
4458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
4468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
4498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
4510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_enable,
4520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_active_high,
4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_enable,
4540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_active_high,
4550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool interrupt_enable)
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
4608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
4618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
4638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
4658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
4668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
4678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
4698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
4708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
47452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
47552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
47652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
47852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
480da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_0 |
4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
4988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
5008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
5018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
503655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
5048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
5058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
507655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
5088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
509da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
5100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       enum pci9111_trigger_sources source)
5118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
5178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
5188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
5198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
5228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
533da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
5348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
545da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
5468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
5508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
5528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
5538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5573ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
5588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
5598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
5603ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
56252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
5638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
5648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
56552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
5668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
567da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
5680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC0_sources irq_0_source,
5690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC1_sources irq_1_source)
5708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
58452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
58552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
58652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
58852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_cancel(struct comedi_device *dev,
5930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
59552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
6078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
6088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
6098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
6118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
61352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
6148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6157ecac4c38a813021155c4207592693ad1949b9b7Mark#define pci9111_check_trigger_src(src, flags)	do {			\
6167ecac4c38a813021155c4207592693ad1949b9b7Mark		tmp = src;						\
6177ecac4c38a813021155c4207592693ad1949b9b7Mark		src &= flags;						\
6187ecac4c38a813021155c4207592693ad1949b9b7Mark		if (!src || tmp != src)					\
6197ecac4c38a813021155c4207592693ad1949b9b7Mark			error++;					\
6207ecac4c38a813021155c4207592693ad1949b9b7Mark	} while (false);
6218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
623da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
6240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
6278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
6288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
6300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
63252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
6338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
6358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
6360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
6378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
6388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
6408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
6438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6447ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  step 2 : make sure trigger sources are unique and mutually
6457ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  compatible */
6468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
6510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
6520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_EXT))
6538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6552306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
6568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_TIMER) ||
6592306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
6620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_EXT) ||
6632306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6652306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom
6668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
6688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
6748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
67552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
6768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
7030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
7058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7077ecac4c38a813021155c4207592693ad1949b9b7Mark	if ((cmd->scan_begin_src == TRIG_FOLLOW)
7087ecac4c38a813021155c4207592693ad1949b9b7Mark	    && (cmd->scan_begin_arg != 0)) {
7098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
7180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_end_arg != cmd->chanlist_len)) {
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
7248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
7288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
7298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
7348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
73552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
7388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
7398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
7400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
7410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
7420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
7430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
7448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
7458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
7468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
74752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
74852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
7538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
7548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
7558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
7578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
7598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
7608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
7610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg / scan_begin_min;
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
7648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
7658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
7688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
7698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
77752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must be consecutive "
7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "channels,counting upwards from 0\n");
7908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same gain\n");
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same reference\n");
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
8028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
8038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
8048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
8050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     (board->ai_channel_nbr - 1))
8060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || (CR_CHAN(cmd->chanlist[0]) < 0)) {
8078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
8080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "channel number is out of limits\n");
8098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
8108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
8118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
8128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
8158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
8168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
82152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
8228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_do_cmd(struct comedi_device *dev,
8240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *subdevice)
8258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
826ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
8278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
8300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for PCI9111, cannot do hardware conversion");
8318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
83352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
83452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
83552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
8368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
8408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
8428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
8438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
84552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
84652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
8538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
8550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    async_cmd->stop_arg * async_cmd->chanlist_len;
8568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
8578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
8608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
8628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
8668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
86952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
8708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
8738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
8748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
8750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
8760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
8770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async_cmd->convert_arg),
8780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async_cmd->
8790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
8808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_1,
8830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_2);
8848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8956c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		if (async_cmd->scan_begin_src == TRIG_TIMER) {
8966c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott			dev_private->scan_delay =
8976c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				(async_cmd->scan_begin_arg /
8986c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				 (async_cmd->convert_arg *
8996c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				  async_cmd->chanlist_len)) - 1;
9006c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		}
9018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
9058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
9078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
9088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
9090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
9110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
9128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
9148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
9168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
9188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
9218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
9228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
9238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
9240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
9258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
9278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
9288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
9290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_trigger_and_autoscan_get());
9308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
9310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_interrupt_and_fifo_get());
9328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
9338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
9340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->stop_counter);
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
9360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->scan_delay);
9378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
9380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chanlist_len);
9398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
9400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chunk_num_samples);
9418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
9448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
9470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
9480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
9490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index)
9508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
951790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
952790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
9540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
9558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
9578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
9588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
9600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
9618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
9628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
9640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_AI_RESOLUTION_2_CMP_BIT;
9658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
96852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
96952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
97052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
9718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
9738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
97470265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
9758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
97671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
97734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
978d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
9798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
9808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
9818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
98352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
98452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
9858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9905f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
9918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
99252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     PLX9050_REGISTER_INTERRUPT_CONTROL);
9958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
9990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
100052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
100152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
10025f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
10070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
100852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
10098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
10110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
10148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
10178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
10198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
10228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
10238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
10248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
10278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
10300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE >
10310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    dev_private->stop_counter
10320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    && !dev_private->
10330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    stop_is_none ? dev_private->stop_counter :
10340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE;
10358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
10360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     dev_private->ai_bounce_buffer, num_samples);
10378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
10398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
10400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cfc_write_array_to_buffer(subdevice,
10410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      dev_private->
10420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      ai_bounce_buffer,
10430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      num_samples *
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      sizeof(short));
10458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
10468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
10478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
10488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
10508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
10510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chanlist_len) {
10528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chanlist_len -
10540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    cfc_write_array_to_buffer
10640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    (subdevice,
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     dev_private->ai_bounce_buffer
10660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     + position,
10670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     to_read * sizeof(short));
10688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
10698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_num_samples
10710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    -
10720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    sizeof(short) * to_read;
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chunk_num_samples)
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
10930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    bytes_written / sizeof(short);
10948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
11008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
11038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
11048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
11068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11075f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
11128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
111452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
111552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
111652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
111852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
11198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
11218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1122da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
11230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
11270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
11288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
11308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
11330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_CHAN((&insn->chanspec)[0]),
11340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_RANGE((&insn->chanspec)[0]), insn->n);
11358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
11388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11392306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
11408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
11418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
11438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
11488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
11508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
11518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
11528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
11538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
11558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
11568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
11578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
11588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralconversion_done:
11608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11612306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (resolution == PCI9111_HR_AI_RESOLUTION)
11628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
11632306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		else
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
11658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
11690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_channel_get(),
11700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
11718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
117652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1179da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
11800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      struct comedi_subdevice *s, struct comedi_insn *insn,
11810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      unsigned int *data)
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
119352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1195da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
11960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
11970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
12008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12012306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	for (i = 0; i < insn->n; i++)
12028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
12038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
12058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
120852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
120952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
121152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
12128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1213da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
12140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1217790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
12208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
122552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
12268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1227da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
12280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1231790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
123352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
123452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
123552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
12388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
12408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
12418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
12428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
12438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
12458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
125152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
125252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
125352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
125552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
12568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1257da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
12588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
125952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
12608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
12620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
12638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
12668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
12678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
126852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
12698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
12718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
12728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
12748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
12768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
127852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
127952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
128052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
12830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
12848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
128534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
128720fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pci_device = NULL;
12888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1289940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12912306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
12928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
129352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12958522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n",
12968522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson								dev->minor);
12978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
129820fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pci_device) {
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
13008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
13018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
13020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pci_device->device) {
13037ecac4c38a813021155c4207592693ad1949b9b7Mark					/* was a particular bus/slot
13047ecac4c38a813021155c4207592693ad1949b9b7Mark					 * requested? */
13058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
13060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    || (it->options[1] != 0)) {
13077ecac4c38a813021155c4207592693ad1949b9b7Mark						/* are we on the wrong
13087ecac4c38a813021155c4207592693ad1949b9b7Mark						 * bus/slot? */
13098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
13100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    it->options[0]
13110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    ||
13120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    PCI_SLOT(pci_device->devfn)
13130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    != it->options[1]) {
13148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
13158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
13168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
13178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
13190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					board =
13200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    (struct pci9111_board *)
13210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev->board_ptr;
13228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
13238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
13248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
13268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13298522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR
13308522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson		"comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
13318522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson			dev->minor, it->options[0], it->options[1]);
13328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
13338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
13358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13368522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
13370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor,
13380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_boards[i].name,
13390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci_device->bus->number,
13400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_SLOT(pci_device->devfn),
13410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_FUNC(pci_device->devfn), pci_device->irq);
13428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
134352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
13448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13457ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  Read local configuration register base address
13467ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  [PCI_BASE_ADDRESS #1]. */
13478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
13498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
13508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk
13520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
13530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     dev->minor, lcr_io_base, lcr_io_range);
13548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
135552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
13568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
13570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
13580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("comedi%d: Failed to enable PCI device and request regions\n",
13590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->minor);
13608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
13618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
136252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
13658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
13668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13678522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
13680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, io_base, io_range);
13698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
13718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
13728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
13758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
13788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
137952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
13808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13835f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(pci_device->irq, pci9111_interrupt,
13848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13858522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson			printk(KERN_ERR
13868522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson				"comedi%d: unable to allocate irq  %u\n",
13878522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson					dev->minor, pci_device->irq);
13888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
139352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1395c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	error = alloc_subdevices(dev, 4);
1396c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (error < 0)
13978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
14008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
14018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
14038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
14048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
140552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
140652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
140752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
14088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
14108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
14118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
14128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
14138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
14148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
14158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
14168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
14178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
14188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
14208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
14218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
14228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
14238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
14248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
14258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
14268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
14278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
14288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
14308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
14318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
14328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
14338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
14368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
14388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
14398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
14408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
14418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
14448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
14468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
14498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
145052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
14518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1452da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
14538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
145452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
14558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1456525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev->private != NULL) {
14578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
14588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
14598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
146152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
14628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14632306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (dev->irq != 0)
14645f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
14658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1466525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev_private != NULL && dev_private->pci_device != NULL) {
14672306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (dev->iobase)
14688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
14698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
14708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
147490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
147590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
147690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
147790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1478