adl_pci9111.c revision 842ec6ba3bdf6de35359726b0428095fdd0f9b45
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) \
269842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
270842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
271842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)
2728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_1_set(data) \
274842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
275842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
276842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)
2778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_2_set(data) \
279842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
280842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson		outb((data >> 8) & 0xFF, \
281842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson			PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
2828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
28352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Function prototypes */
2848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
2860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
287da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev);
2880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
2890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
2900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
2910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index);
2928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2939ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange pci9111_hr_ai_range = {
2948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	5,
2958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.625)
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
3028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
3057ecac4c38a813021155c4207592693ad1949b9b7Mark	{ PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
3067ecac4c38a813021155c4207592693ad1949b9b7Mark	  0, 0, 0 },
3077ecac4c38a813021155c4207592693ad1949b9b7Mark	/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,
3087ecac4c38a813021155c4207592693ad1949b9b7Mark	 *   0, 0, 0 }, */
3097ecac4c38a813021155c4207592693ad1949b9b7Mark	{ 0 }
3108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
3138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
31452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
31552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
31652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
3178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
318940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
31952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
3208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
32152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
32252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
32352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
32552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
32752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
32852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
330940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
332940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci9111_hr",
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = PCI9111_HR_DEVICE_ID,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution = PCI9111_HR_AI_RESOLUTION,
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution = PCI9111_AO_RESOLUTION,
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range_list = &pci9111_hr_ai_range,
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_range_list = &range_bipolar10,
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
348842ec6ba3bdf6de35359726b0428095fdd0f9b45Maurice Dawson	(sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
350139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
35168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PCI9111_DRIVER_NAME,
35268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
35368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pci9111_attach,
35468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pci9111_detach,
3558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
357727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
358727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					      const struct pci_device_id *ent)
359727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
360727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
361727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
362727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
363727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
364727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
365727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
366727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
367727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
368727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver pci9111_driver_pci_driver = {
369727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = pci9111_pci_table,
370727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &pci9111_driver_pci_probe,
371727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&pci9111_driver_pci_remove)
372727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
373727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
374727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init pci9111_driver_init_module(void)
375727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
376727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
377727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
378727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&pci9111_driver);
379727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
380727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
381727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
382727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
383727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&pci9111_driver_pci_driver);
384727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
385727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
386727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit pci9111_driver_cleanup_module(void)
387727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
388727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&pci9111_driver_pci_driver);
389727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&pci9111_driver);
390727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
391727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
392727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(pci9111_driver_init_module);
393727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(pci9111_driver_cleanup_module);
3948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
39552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
3968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
397c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
3988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
39952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
4008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4017ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned long lcr_io_base; /* Local configuration register base
4027ecac4c38a813021155c4207592693ad1949b9b7Mark				    * address */
4038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
4048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
4068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
4078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
4098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
4108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
4118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
4128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
4148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4157ecac4c38a813021155c4207592693ad1949b9b7Mark	unsigned int timer_divisor_1; /* Divisor values for the 8254 timer
4167ecac4c38a813021155c4207592693ad1949b9b7Mark				       * pacer */
417525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	unsigned int timer_divisor_2;
4188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
4208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
421790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
422c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
4238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4247ecac4c38a813021155c4207592693ad1949b9b7Mark#define dev_private	((struct pci9111_private_data *)dev->private)
4258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
42752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
42852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
4318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
4338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
4348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
4358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
4368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
4378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
4388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
4398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
4408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
4420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_enable,
4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_active_high,
4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_enable,
4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_active_high,
4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool interrupt_enable)
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
4498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
4518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
4528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
4538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
4548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
4558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
4608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
4618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
46552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
46652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
46752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
46952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
471da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_0 |
4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4885f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
4898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
4918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
4928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
494655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
4958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
4968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
4978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
498655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
500da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       enum pci9111_trigger_sources source)
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
5088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
5098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
5108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
5138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
5178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
5188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
524da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
5298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
5318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
536da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
5378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
5438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5483ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
5498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
5508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
5513ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
5528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
55352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
5548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
5558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
55652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
5578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
558da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
5590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC0_sources irq_0_source,
5600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC1_sources irq_1_source)
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
5658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
57552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
57652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
57752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
57952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_cancel(struct comedi_device *dev,
5840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
5858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
58652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
5908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
5928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
5968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
5988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
6008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
60452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6067ecac4c38a813021155c4207592693ad1949b9b7Mark#define pci9111_check_trigger_src(src, flags)	do {			\
6077ecac4c38a813021155c4207592693ad1949b9b7Mark		tmp = src;						\
6087ecac4c38a813021155c4207592693ad1949b9b7Mark		src &= flags;						\
6097ecac4c38a813021155c4207592693ad1949b9b7Mark		if (!src || tmp != src)					\
6107ecac4c38a813021155c4207592693ad1949b9b7Mark			error++;					\
6117ecac4c38a813021155c4207592693ad1949b9b7Mark	} while (false);
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
614da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
6150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
6168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
6178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
6188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
6198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
6208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
6210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
6228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
62352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
6248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
6270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
6288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
6308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
6348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6357ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  step 2 : make sure trigger sources are unique and mutually
6367ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  compatible */
6378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
6420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
6430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_EXT))
6448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6462306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
6478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_TIMER) ||
6502306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
6530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_EXT) ||
6542306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6562306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom
6578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
6598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
6618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
6658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
66652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
6940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
6958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6987ecac4c38a813021155c4207592693ad1949b9b7Mark	if ((cmd->scan_begin_src == TRIG_FOLLOW)
6997ecac4c38a813021155c4207592693ad1949b9b7Mark	    && (cmd->scan_begin_arg != 0)) {
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
7058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
7090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_end_arg != cmd->chanlist_len)) {
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
7118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
7168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
72652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
7298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
7310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
7320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
7330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
7340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
7358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
73852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
73952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
7408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
7428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
7448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
7458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
7468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
7488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
7520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg / scan_begin_min;
7538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
7548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
7558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
7598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
7608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
7678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
76852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
7698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must be consecutive "
7800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "channels,counting upwards from 0\n");
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same gain\n");
7868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same reference\n");
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
7960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     (board->ai_channel_nbr - 1))
7970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || (CR_CHAN(cmd->chanlist[0]) < 0)) {
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
7990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "channel number is out of limits\n");
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
8028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
8038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
8068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
8078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
8098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
81252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
8138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_do_cmd(struct comedi_device *dev,
8150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *subdevice)
8168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
817ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
8210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for PCI9111, cannot do hardware conversion");
8228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
82452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
82552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
82652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
8278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
8308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
8318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
8328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
8338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
8348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
83652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
83752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
8408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
8428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
8448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
8458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
8460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    async_cmd->stop_arg * async_cmd->chanlist_len;
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
8538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
8578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
86052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
8638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
8648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
8658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
8660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
8670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
8680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async_cmd->convert_arg),
8690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async_cmd->
8700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
8718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_1,
8740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_2);
8758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8866c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		if (async_cmd->scan_begin_src == TRIG_TIMER) {
8876c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott			dev_private->scan_delay =
8886c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				(async_cmd->scan_begin_arg /
8896c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				 (async_cmd->convert_arg *
8906c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott				  async_cmd->chanlist_len)) - 1;
8916c2fd308045ba902fbe9f4408daa7b949fa8f5a1Ian Abbott		}
8928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
8968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
8988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
9000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
9018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
9020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
9058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
9078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
9088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
9098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
9128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
9148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
9150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
9168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
9188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
9200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_trigger_and_autoscan_get());
9218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
9220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_interrupt_and_fifo_get());
9238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
9248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->stop_counter);
9268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
9270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->scan_delay);
9288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
9290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chanlist_len);
9308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
9310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chunk_num_samples);
9328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
9380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
9390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
9400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index)
9418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
942790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
943790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
9448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
9450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
9468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
9488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
9498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
9510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
9528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
9550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_AI_RESOLUTION_2_CMP_BIT;
9568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
95952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
96052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
96152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
9628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
9648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
96570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
9668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
96771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
96834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
969d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
9708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
9718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
9728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
97452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
97552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
9768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9815f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
9828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
98352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     PLX9050_REGISTER_INTERRUPT_CONTROL);
9868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
9900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
99152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
99252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
9935f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
9980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
99952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
10008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
10020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
10058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
10068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
10078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
10088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
10108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
10148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
10178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
10188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
10210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE >
10220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    dev_private->stop_counter
10230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    && !dev_private->
10240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    stop_is_none ? dev_private->stop_counter :
10250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE;
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
10270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     dev_private->ai_bounce_buffer, num_samples);
10288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
10308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
10310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cfc_write_array_to_buffer(subdevice,
10320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      dev_private->
10330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      ai_bounce_buffer,
10340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      num_samples *
10350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      sizeof(short));
10368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
10378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
10388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
10398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
10418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
10420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chanlist_len) {
10438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chanlist_len -
10450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    cfc_write_array_to_buffer
10550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    (subdevice,
10560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     dev_private->ai_bounce_buffer
10570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     + position,
10580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     to_read * sizeof(short));
10598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
10608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_num_samples
10620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    -
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    sizeof(short) * to_read;
10728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chunk_num_samples)
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
10840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    bytes_written / sizeof(short);
10858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
10918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
10948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10985f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
11018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
11038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
110552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
110652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
110752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
110952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
11128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1113da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
11140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
11180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
11198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
11218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
11240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_CHAN((&insn->chanspec)[0]),
11250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_RANGE((&insn->chanspec)[0]), insn->n);
11268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
11298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11302306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
11318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
11328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
11348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
11378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
11398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
11418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
11428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
11438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
11478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
11488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
11498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralconversion_done:
11518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11522306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (resolution == PCI9111_HR_AI_RESOLUTION)
11538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
11542306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		else
11558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
11568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
11600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_channel_get(),
11610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
11628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
116752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1170da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
11710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      struct comedi_subdevice *s, struct comedi_insn *insn,
11720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      unsigned int *data)
11738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1186da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
11870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
11880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11922306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	for (i = 0; i < insn->n; i++)
11938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
11948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
119852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
119952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
120052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
12038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1204da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
12050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1208790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
12118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
121652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
12178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1218da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
12190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1222790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
122452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
122552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
122652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
12278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
12298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
12318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
12328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
12338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
12348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
124252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
124352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
124452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
124652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
12478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1248da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
12498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
125052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
12518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
12530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
12548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
12568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
12578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
12588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
125952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
12608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
12628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
12638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
12678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
126952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
127052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
127152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
12740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
12758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
127634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
127820fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pci_device = NULL;
12798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1280940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12822306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
12838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
128452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
12878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
128820fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pci_device) {
12898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
12908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
12918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
12920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pci_device->device) {
12937ecac4c38a813021155c4207592693ad1949b9b7Mark					/* was a particular bus/slot
12947ecac4c38a813021155c4207592693ad1949b9b7Mark					 * requested? */
12958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
12960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    || (it->options[1] != 0)) {
12977ecac4c38a813021155c4207592693ad1949b9b7Mark						/* are we on the wrong
12987ecac4c38a813021155c4207592693ad1949b9b7Mark						 * bus/slot? */
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
13000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    it->options[0]
13010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    ||
13020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    PCI_SLOT(pci_device->devfn)
13030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    != it->options[1]) {
13048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
13058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
13068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
13078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
13090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					board =
13100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    (struct pci9111_board *)
13110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev->board_ptr;
13128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
13138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
13148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
13158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
13168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
13200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, it->options[0], it->options[1]);
13218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
13228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
13248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
13260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor,
13270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_boards[i].name,
13280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci_device->bus->number,
13290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_SLOT(pci_device->devfn),
13300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_FUNC(pci_device->devfn), pci_device->irq);
13318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
133252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
13338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13347ecac4c38a813021155c4207592693ad1949b9b7Mark	/*  Read local configuration register base address
13357ecac4c38a813021155c4207592693ad1949b9b7Mark	 *  [PCI_BASE_ADDRESS #1]. */
13368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
13388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
13398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk
13410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
13420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     dev->minor, lcr_io_base, lcr_io_range);
13438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
134452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
13458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
13460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
13470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("comedi%d: Failed to enable PCI device and request regions\n",
13480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->minor);
13498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
13508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
135152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
13528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
13548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
13558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
13570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, io_base, io_range);
13588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
13608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
13618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
13628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
13658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
13678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
136852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
13698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13725f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(pci_device->irq, pci9111_interrupt,
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk("comedi%d: unable to allocate irq  %u\n",
13750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       dev->minor, pci_device->irq);
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
138152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1383c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	error = alloc_subdevices(dev, 4);
1384c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (error < 0)
13858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
13888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
13918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
139352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
139452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
139552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
13968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
13988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
13998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
14008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
14018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
14028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
14038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
14048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
14058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
14068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
14088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
14098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
14108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
14118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
14128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
14138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
14148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
14158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
14168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
14188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
14198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
14208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
14218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
14248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
14268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
14278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
14288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
14298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
14328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
14348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
14378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
143852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
14398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1440da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
14418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
144252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
14438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1444525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev->private != NULL) {
14458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
14468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
14478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
144952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
14508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14512306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (dev->irq != 0)
14525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
14538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1454525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev_private != NULL && dev_private->pci_device != NULL) {
14552306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (dev->iobase)
14568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
14578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
14588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
146290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
146390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
146490f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
146590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1466