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) = {
3148c0690eaf7a666183fb9c49d275d9f986acd4239Peter Huewe	{ PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID) },
3158c0690eaf7a666183fb9c49d275d9f986acd4239Peter Huewe	/* { PCI_DEVICE(PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID) }, */
3167ecac4c38a813021155c4207592693ad1949b9b7Mark	{ 0 }
3178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
3208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
32152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
32252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
32352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
3248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
325940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
32652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
3278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
32852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
32952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
33052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
33252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
33452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
33552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
337940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
339940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci9111_hr",
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = PCI9111_HR_DEVICE_ID,
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution = PCI9111_HR_AI_RESOLUTION,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution = PCI9111_AO_RESOLUTION,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range_list = &pci9111_hr_ai_range,
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_range_list = &range_bipolar10,
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
355842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
357139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
35868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PCI9111_DRIVER_NAME,
35968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
36068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pci9111_attach,
36168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pci9111_detach,
3628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
364727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
365727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					      const struct pci_device_id *ent)
366727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
367727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
368727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
369727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
370727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
371727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
372727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
373727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
374727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
375727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver pci9111_driver_pci_driver = {
376727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = pci9111_pci_table,
377727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &pci9111_driver_pci_probe,
378727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&pci9111_driver_pci_remove)
379727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
380727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
381727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init pci9111_driver_init_module(void)
382727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
383727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
384727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
385727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&pci9111_driver);
386727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
387727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
388727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
389727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
390727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&pci9111_driver_pci_driver);
391727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
392727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
393727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit pci9111_driver_cleanup_module(void)
394727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
395727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&pci9111_driver_pci_driver);
396727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&pci9111_driver);
397727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
398727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
399727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(pci9111_driver_init_module);
400727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(pci9111_driver_cleanup_module);
4018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
40252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
4038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
404c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
4058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
40652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
4078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4087ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned long lcr_io_base; /* Local configuration register base
4097ecac4c38a813021155c4207592693ad1949b9b7Mark				    * address */
4108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
4118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
4138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
4148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
4168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
4178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
4188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
4198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
4218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4227ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
4237ecac4c38a813021155c4207592693ad1949b9b7Mark				       * pacer */
424525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	unsigned int timer_divisor_2;
4258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
4278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
428790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
429c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
4308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4317ecac4c38a813021155c4207592693ad1949b9b7Mark#define dev_private	((struct pci9111_private_data *)dev->private)
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
43352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
43452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
43552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
4388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
4408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
4428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
4438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
4448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
4458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
4468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
4490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_enable,
4500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_active_high,
4510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_enable,
4520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_active_high,
4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool interrupt_enable)
4548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
4598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
4608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
4618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
4638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
4658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
4678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
4688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
47252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
47352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
47452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
47652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
478da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_0 |
4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4955f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
4968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
4988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
501655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
5038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
5048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
505655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
507da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
5080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       enum pci9111_trigger_sources source)
5098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
5138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
5178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
5208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
5218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
5248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
531da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
5368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
543da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
5488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
5508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
5518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5553ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
5568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
5578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
5583ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
5598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
56052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
5628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
56352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
5648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
565da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
5660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC0_sources irq_0_source,
5670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC1_sources irq_1_source)
5688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
58252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
58352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
58452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
58652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_cancel(struct comedi_device *dev,
5910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
5928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
59352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
5978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
6068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
6078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
6098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
6108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
61152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6137ecac4c38a813021155c4207592693ad1949b9b7Mark#define pci9111_check_trigger_src(src, flags)	do {			\
6147ecac4c38a813021155c4207592693ad1949b9b7Mark		tmp = src;						\
6157ecac4c38a813021155c4207592693ad1949b9b7Mark		src &= flags;						\
6167ecac4c38a813021155c4207592693ad1949b9b7Mark		if (!src || tmp != src)					\
6177ecac4c38a813021155c4207592693ad1949b9b7Mark			error++;					\
6187ecac4c38a813021155c4207592693ad1949b9b7Mark	} while (false);
6198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
621da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
6220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
6238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
6248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
6278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
63052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
6338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
6340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
6358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
6368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
6378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
6388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
6418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6427ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  step 2 : make sure trigger sources are unique and mutually
6437ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  compatible */
6448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
6468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
6490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
6500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_EXT))
6518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6532306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
6548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_TIMER) ||
6572306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
6600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_EXT) ||
6612306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6632306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
6668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
6688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
67352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
6748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
7010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
7038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7057ecac4c38a813021155c4207592693ad1949b9b7Mark	if ((cmd->scan_begin_src == TRIG_FOLLOW)
7067ecac4c38a813021155c4207592693ad1949b9b7Mark	    && (cmd->scan_begin_arg != 0)) {
7078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
7118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
7160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_end_arg != cmd->chanlist_len)) {
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
7188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
7228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
7238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
7268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
7328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
73352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
7348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
7380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
7390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
7400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
7410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
7428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
7438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
7448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
74552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
74652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
7478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
7528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
7538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
7558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
7578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
7588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
7590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg / scan_begin_min;
7608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
7618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
7668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
7678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
77552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must be consecutive "
7870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "channels,counting upwards from 0\n");
7888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same gain\n");
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same reference\n");
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
8028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
8030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     (board->ai_channel_nbr - 1))
8040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || (CR_CHAN(cmd->chanlist[0]) < 0)) {
8058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
8060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "channel number is out of limits\n");
8078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
8088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
8098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
8108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
8138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
8148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
8168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
81952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_do_cmd(struct comedi_device *dev,
8220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *subdevice)
8238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
824ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
8258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
8278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
8280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for PCI9111, cannot do hardware conversion");
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
83152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
83252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
83352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
8348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
8368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
8378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
8408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
84352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
84452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
8458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
8530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    async_cmd->stop_arg * async_cmd->chanlist_len;
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
8558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
8588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
8598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
8608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
8648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
86752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
8688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
8708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
8718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
8730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
8740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
8750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async_cmd->convert_arg),
8760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async_cmd->
8770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
8788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_1,
8810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_2);
8828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8936c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		if (async_cmd->scan_begin_src == TRIG_TIMER) {
8946c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott			dev_private->scan_delay =
8956c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				(async_cmd->scan_begin_arg /
8966c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				 (async_cmd->convert_arg *
8976c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				  async_cmd->chanlist_len)) - 1;
8986c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		}
8998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
9018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
9058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
9068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
9070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
9088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
9090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
9128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
9148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
9158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
9168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
9208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
9218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
9220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
9238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
9258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
9268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
9270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_trigger_and_autoscan_get());
9288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
9290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_interrupt_and_fifo_get());
9308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
9318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->stop_counter);
9338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
9340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->scan_delay);
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
9360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chanlist_len);
9378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
9380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chunk_num_samples);
9398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
9428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
9450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
9460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
9470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index)
9488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
949790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
950790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
9518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
9520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
9558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
9568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
9580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
9598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
9608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
9620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_AI_RESOLUTION_2_CMP_BIT;
9638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
96652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
96752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
96852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
9698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
9718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
97270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
9738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
97471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
97534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
976d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
9778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
9788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
9798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
98152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
98252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
9838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9885f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
9898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
99052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     PLX9050_REGISTER_INTERRUPT_CONTROL);
9938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
9970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
99852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
99952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
10005f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
10028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
10050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
100652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
10078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
10090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
10118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
10128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
10148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
10178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
10208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
10218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
10228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
10248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
10258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
10280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE >
10290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    dev_private->stop_counter
10300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    && !dev_private->
10310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    stop_is_none ? dev_private->stop_counter :
10320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE;
10338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
10340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     dev_private->ai_bounce_buffer, num_samples);
10358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
10378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
10380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cfc_write_array_to_buffer(subdevice,
10390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      dev_private->
10400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      ai_bounce_buffer,
10410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      num_samples *
10420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      sizeof(short));
10438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
10448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
10458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
10468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
10488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
10490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chanlist_len) {
10508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chanlist_len -
10520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    cfc_write_array_to_buffer
10620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    (subdevice,
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     dev_private->ai_bounce_buffer
10640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     + position,
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     to_read * sizeof(short));
10668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
10678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_num_samples
10690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    -
10700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    sizeof(short) * to_read;
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chunk_num_samples)
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
10910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    bytes_written / sizeof(short);
10928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
10988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
11018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
11028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
11048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
11068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
111252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
111352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
111452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
111652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
11178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
11198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1120da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
11210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
11250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
11268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
11288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
11310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_CHAN((&insn->chanspec)[0]),
11320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_RANGE((&insn->chanspec)[0]), insn->n);
11338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11372306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
11388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
11398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
11418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
11488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
11498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
11508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
11518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
11538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
11548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
11558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
11568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralconversion_done:
11588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11592306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (resolution == PCI9111_HR_AI_RESOLUTION)
11608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
11612306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		else
11628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
11638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
11670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_channel_get(),
11680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
11698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
117452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1177da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
11780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      struct comedi_subdevice *s, struct comedi_insn *insn,
11790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      unsigned int *data)
11808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
119152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1193da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
11940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
11950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11992306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	for (i = 0; i < insn->n; i++)
12008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
12018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
12038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
120652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
120752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
12108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1211da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
12120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1215790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
12188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
122352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
12248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1225da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
12260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1229790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
123152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
123252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
123352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
12348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
12388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
12398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
12408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
12418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
12438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
124952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
125052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
125152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
125352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
12548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1255da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
12568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
125752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
12588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
12600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
12618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
12638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
12648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
126652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
12678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
12698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
12708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
12728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
12748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
127652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
127752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
127852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
12810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
12828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
128334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
128520fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pci_device = NULL;
12868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1287940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12892306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
12908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
129152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12938522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: " PCI9111_DRIVER_NAME " driver\n",
12948522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson								dev->minor);
12958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
129620fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pci_device) {
12978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
12988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
13000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pci_device->device) {
13017ecac4c38a813021155c4207592693ad1949b9b7Mark					/* was a particular bus/slot
13027ecac4c38a813021155c4207592693ad1949b9b7Mark					 * requested? */
13038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
13040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    || (it->options[1] != 0)) {
13057ecac4c38a813021155c4207592693ad1949b9b7Mark						/* are we on the wrong
13067ecac4c38a813021155c4207592693ad1949b9b7Mark						 * bus/slot? */
13078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
13080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    it->options[0]
13090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    ||
13100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    PCI_SLOT(pci_device->devfn)
13110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    != it->options[1]) {
13128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
13138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
13148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
13158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
13170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					board =
13180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    (struct pci9111_board *)
13190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev->board_ptr;
13208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
13218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
13228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
13238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
13248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13278522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR
13288522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson		"comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
13298522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson			dev->minor, it->options[0], it->options[1]);
13308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
13318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
13338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13348522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
13350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor,
13360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_boards[i].name,
13370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci_device->bus->number,
13380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_SLOT(pci_device->devfn),
13390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_FUNC(pci_device->devfn), pci_device->irq);
13408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
134152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
13428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13437ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  Read local configuration register base address
13447ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  [PCI_BASE_ADDRESS #1]. */
13458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
13478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
13488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk
13500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
13510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     dev->minor, lcr_io_base, lcr_io_range);
13528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
135352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
13548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
13550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
13560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("comedi%d: Failed to enable PCI device and request regions\n",
13570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->minor);
13588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
13598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
136052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
13618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13658522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson	printk(KERN_ERR "comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
13660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, io_base, io_range);
13678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
13698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
13708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
13718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
13728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
137752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
13788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(pci_device->irq, pci9111_interrupt,
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13838522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson			printk(KERN_ERR
13848522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson				"comedi%d: unable to allocate irq  %u\n",
13858522e70b44021d1cc44de1f6c491ac21cc8f4f3dMaurice Dawson					dev->minor, pci_device->irq);
13868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
139152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1393c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	error = alloc_subdevices(dev, 4);
1394c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (error < 0)
13958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
13988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
13998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
14018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
14028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
140352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
140452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
140552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
14068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
14088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
14098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
14108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
14118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
14128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
14138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
14148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
14158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
14168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
14188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
14198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
14208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
14218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
14228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
14238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
14248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
14258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
14268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
14288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
14298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
14308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
14318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
14348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
14368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
14378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
14388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
14398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
14428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
14448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
14478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
144852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
14498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1450da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
14518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
145252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
14538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1454525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev->private != NULL) {
14558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
14568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
14578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
145952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
14608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14612306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (dev->irq != 0)
14625f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
14638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1464525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev_private != NULL && dev_private->pci_device != NULL) {
14652306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (dev->iobase)
14668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
14678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
14688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
147290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
147390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
147490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
147590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1476