adl_pci9111.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
18cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
28cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
38cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud   comedi/drivers/adl_pci9111.c
48cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
58cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud   Hardware driver for PCI9111 ADLink cards:
68cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
78cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud     PCI-9111HR
88cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
98cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud   Copyright (C) 2002-2005 Emmanuel Pacaud <emmanuel.pacaud@univ-poitiers.fr>
108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    This program is free software; you can redistribute it and/or modify
128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    it under the terms of the GNU General Public License as published by
138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    the Free Software Foundation; either version 2 of the License, or
148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    (at your option) any later version.
158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    This program is distributed in the hope that it will be useful,
178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    but WITHOUT ANY WARRANTY; without even the implied warranty of
188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    GNU General Public License for more details.
208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    You should have received a copy of the GNU General Public License
228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    along with this program; if not, write to the Free Software
238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    Foundation, 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
358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - ai_insn read
368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - ao_insn read/write
378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - di_insn read
388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - do_insn read/write
398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - ai_do_cmd mode with the following sources:
408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    - start_src 		TRIG_NOW
428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    - scan_begin_src 		TRIG_FOLLOW	TRIG_TIMER	TRIG_EXT
438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    - convert_src				TRIG_TIMER	TRIG_EXT
448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    - scan_end_src		TRIG_COUNT
458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    - stop_src			TRIG_COUNT	TRIG_NONE
468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    The scanned channels must be consecutive and start from 0. They must
488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    all have the same range and aref.
498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudConfiguration options:
518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    [0] - PCI bus number (optional)
538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    [1] - PCI slot number (optional)
548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    If bus/slot is not specified, the first available PCI
568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    device will be used.
578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudCHANGELOG:
628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  2005/02/17 Extend AI streaming capabilities. Now, scan_begin_arg can be
648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  a multiple of chanlist_len*convert_arg.
658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  2002/02/19 Fixed the two's complement conversion in pci9111_(hr_)ai_get_data.
668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  2002/02/18 Added external trigger support for analog input.
678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudTODO:
698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - Really test implemented functionality.
718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - Add support for the PCI-9111DG with a probe routine to identify the card type
728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    (perhaps with the help of the channel number readback of the A/D Data register).
738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - Add external multiplexer support.
748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "../comedidev.h"
788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include <linux/delay.h>
8070265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "8253.h"
838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_pci.h"
848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_fc.h"
858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DRIVER_NAME 	"adl_pci9111"
878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_DEVICE_ID 	0x9111
888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  TODO: Add other pci9111 board id */
908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_IO_RANGE 	0x0100
928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_SIZE	512
948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_CHANNEL_NBR			16
968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION			12
988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_MASK		0x0FFF
998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_2_CMP_BIT		0x0800
1008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION		16
1028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_MASK		0xFFFF
1038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT	0x8000
1048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
1068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_CHANNEL_NBR			1
1078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_AO_RESOLUTION			12
1088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_RESOLUTION_MASK		0x0FFF
1098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DI_CHANNEL_NBR			16
1108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_DO_CHANNEL_NBR			16
1118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DO_MASK				0xFFFF
1128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_SETTING_DELAY		10
1148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_UDELAY_US	2
1158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
1168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_CLOCK_PERIOD_NS		500
1188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_0			0x00
1208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_1			0x40
1218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_2			0x80
1228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_LATCH		0x00
1238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_ONLY		0x10
1248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_MSB_ONLY		0x20
1258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_MSB		0x30
1268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_0			0x00
1278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_1			0x02
1288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_2			0x04
1298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_3			0x06
1308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_4			0x08
1318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_5			0x0A
1328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BINARY_COUNTER		0x00
1338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BCD_COUNTER		0x01
1348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/* IO address map */
1368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton#define PCI9111_REGISTER_AD_FIFO_VALUE 			0x00	/*  AD Data stored in FIFO */
1388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_DA_OUTPUT 			0x00
1398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_DIGITAL_IO 			0x02
1408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_EXTENDED_IO_PORTS 		0x04
14152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton#define PCI9111_REGISTER_AD_CHANNEL_CONTROL 		0x06	/*  Channel selection */
1428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_AD_CHANNEL_READBACK 		0x06
1438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE 		0x08
1448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_RANGE_STATUS_READBACK 		0x08
1458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL 		0x0A
1468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK 	0x0A
1478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_SOFTWARE_TRIGGER 		0x0E
1488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_INTERRUPT_CONTROL 		0x0C
1498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_0			0x40
1508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_1			0x42
1518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_2 		0X44
1528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_CONTROL			0x46
1538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_INTERRUPT_CLEAR 		0x48
1548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TRIGGER_MASK 				0x0F
1568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_PTRG_OFF 				(0 << 3)
1578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_PTRG_ON 				(1 << 3)
1588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_EXTERNAL				(1 << 2)
1598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_INTERNAL				(0 << 2)
1608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_SOFTWARE_TRIGGER			(0 << 1)
1618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_TIMER_PACER			(1 << 1)
1628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_ON				(1 << 0)
1638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_OFF				(0 << 0)
1648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
1668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL		(1 << 0)
1678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK  		(0 << 1)
1688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG 		(1 << 1)
1698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FFEN_SET_FIFO_ENABLE 			(0 << 2)
1708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FFEN_SET_FIFO_DISABLE			(1 << 2)
1718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_CHANNEL_MASK				0x0F
1738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_MASK				0x07
1758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_EMPTY_MASK				0x10
1768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_FULL_MASK			0x20
1778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_FULL_MASK				0x40
1788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AD_BUSY_MASK				0x80
1798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_IO_BASE dev->iobase
1818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
1838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud * Define inlined function
1848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud */
1858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_get() \
1878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
1888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_set(flags) \
190f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
1918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_and_fifo_get() \
1938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) &0x03)
1948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_and_fifo_set(flags) \
196f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
1978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_clear() \
199f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
2008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_software_trigger() \
202f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
2038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_fifo_reset() \
205f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
206f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(PCI9111_FFEN_SET_FIFO_DISABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
207f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(PCI9111_FFEN_SET_FIFO_ENABLE, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
2088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_full() \
2108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    PCI9111_FIFO_FULL_MASK)==0)
2128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_half_full() \
2148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    PCI9111_FIFO_HALF_FULL_MASK)==0)
2168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_empty() \
2188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud    PCI9111_FIFO_EMPTY_MASK)==0)
2208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ai_channel_set(channel) \
222f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb((channel)&PCI9111_CHANNEL_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
2238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ai_channel_get() \
2258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)&PCI9111_CHANNEL_MASK
2268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ai_range_set(range) \
228f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb((range)&PCI9111_RANGE_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
2298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ai_range_get() \
2318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)&PCI9111_RANGE_MASK
2328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ai_get_data() \
2348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)&PCI9111_AI_RESOLUTION_MASK) \
2358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ^ PCI9111_AI_RESOLUTION_2_CMP_BIT
2368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_hr_ai_get_data() \
2388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \
2398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT
2408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ao_set_data(data) \
242f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
2438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_di_get_bits() \
2458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_do_set_bits(bits) \
248f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_control_set(flags) \
251f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
2528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_0_set(data) \
2548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
25553106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)
2568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_1_set(data) \
2588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
25953106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)
2608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_2_set(data) \
2628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
26353106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
2648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
26552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Function prototypes */
2668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
2680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
269da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev);
2700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
2710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
2720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
2730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index);
2748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2759ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange pci9111_hr_ai_range = {
2768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	5,
2778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.625)
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
2848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
2858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	{
2880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID,
2890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    PCI_ANY_ID, 0, 0, 0},
2900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
2910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	{
2920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	0}
2938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
2948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
2968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
29752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
29852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
29952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
3008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
301940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
30252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
3038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
30452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
30552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
30652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
30852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
31052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
31152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
313940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
315940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci9111_hr",
3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = PCI9111_HR_DEVICE_ID,
3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution = PCI9111_HR_AI_RESOLUTION,
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution = PCI9111_AO_RESOLUTION,
3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range_list = &pci9111_hr_ai_range,
3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_range_list = &range_bipolar10,
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
331940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton  (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
333139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
33468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PCI9111_DRIVER_NAME,
33568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
33668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pci9111_attach,
33768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pci9111_detach,
3388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudCOMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
3418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
34252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
3438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
344c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
3458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
34652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
3478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
34852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long lcr_io_base;	/*  Local configuration register base address */
3498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
3508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
3528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
3538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
3558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
3568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
3578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
3588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
35952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
3608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
36152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int timer_divisor_1;	/*  Divisor values for the 8254 timer pacer */
3628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timer_divisor_2;
3638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
36452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
3658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
366790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
367c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
3688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
369c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton#define dev_private 	((struct pci9111_private_data *)dev->private)
3708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
37152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
37252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
37352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
3748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
3768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
3788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
3798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
3808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
3818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
3828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
3838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
3848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
3858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
3870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_enable,
3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_active_high,
3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_enable,
3900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_active_high,
3910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool interrupt_enable)
3928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
3938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
3948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
3968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
3978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
3988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
3998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
4008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
4018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
4028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
4038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
4058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
4068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
41152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
41252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
416da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_0 |
4210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4335f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
4348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
4368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
4378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
439655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
4408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
4428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
443655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
4448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
445da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       enum pci9111_trigger_sources source)
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
4518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
4538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
4548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
4558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
4598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
4638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
4658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
469da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
4708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
4748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
4768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
481da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
4828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
4868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
4888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
4898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4933ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
4948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
4958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
4963ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
4978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
49852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
5008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
50152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
503da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
5040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC0_sources irq_0_source,
5050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC1_sources irq_1_source)
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
5108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
52052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
52152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
52252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
52452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_cancel(struct comedi_device *dev,
5290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
5308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
53152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
5378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
5438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
5458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
5478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
54952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
5508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
551f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton#define pci9111_check_trigger_src(src, flags) \
5528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  tmp = src; \
5538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  src &= flags; \
5548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  if (!src || tmp != src) error++
5558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
557da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
5580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
5598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
5628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
5638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
5640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
5658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
56652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
5678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
5698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
5700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
5718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
5738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
5768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
5778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
57852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  step 2 : make sure trigger sources are unique and mutually compatible */
5798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
5840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
5850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_EXT))
5868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) {
5898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
5920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_TIMER) ||
5930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      (cmd->scan_begin_src == TRIG_FOLLOW))) {
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
5970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_EXT) ||
5980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      (cmd->scan_begin_src == TRIG_FOLLOW))) {
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
6098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
61052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
6118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
6380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
6408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) {
6438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
6478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
6520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_end_arg != cmd->chanlist_len)) {
6538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
6548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
6588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
6598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
6628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
6638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
6688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
66952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
6738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
6740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
6750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
6760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
6770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
68152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
68252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
6858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
6918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
6938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
6948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
6950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg / scan_begin_min;
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
6988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
6998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
7038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
71152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must be consecutive "
7230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "channels,counting upwards from 0\n");
7248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same gain\n");
7298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same reference\n");
7348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
7388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
7390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     (board->ai_channel_nbr - 1))
7400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || (CR_CHAN(cmd->chanlist[0]) < 0)) {
7418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
7420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "channel number is out of limits\n");
7438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
7528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
7548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
75552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_do_cmd(struct comedi_device *dev,
7580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *subdevice)
7598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
760ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
7618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
7640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for PCI9111, cannot do hardware conversion");
7658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
7668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
76752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
76852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
76952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
7708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
7758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
7778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
77952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
78052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
7858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
7878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
7888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    async_cmd->stop_arg * async_cmd->chanlist_len;
7908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
7928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
7948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
7968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
7978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
7998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
80352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
8048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
8068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
8078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
8088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
8090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
8100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
8110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async_cmd->convert_arg),
8120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async_cmd->
8130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
8148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_1,
8170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_2);
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->scan_delay =
8300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
8310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						  async_cmd->chanlist_len)) - 1;
8328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
8368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
8538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
8550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
8568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
8598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
8600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_trigger_and_autoscan_get());
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
8620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_interrupt_and_fifo_get());
8638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
8648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
8650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->stop_counter);
8668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
8670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->scan_delay);
8688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
8690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chanlist_len);
8708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chunk_num_samples);
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
8758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
8780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
8790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
8800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index)
8818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
882790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
883790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
8848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
8850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
8868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
8888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
8898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
8900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
8910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
8928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
8938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
8940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
8950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_AI_RESOLUTION_2_CMP_BIT;
8968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
89952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
90052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
90152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
9028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
90570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
9068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
90771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
90834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
909d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
9118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
9128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
91452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
91552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
9168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9215f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
9228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
92352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     PLX9050_REGISTER_INTERRUPT_CONTROL);
9268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
9300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
93152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
93252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
9335f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
9380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
93952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
9408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
9420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
9448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
9458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
9468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
9478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
9488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
9508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
9518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
9548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
9558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
9578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
9588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
9610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE >
9620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    dev_private->stop_counter
9630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    && !dev_private->
9640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    stop_is_none ? dev_private->stop_counter :
9650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE;
9668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
9670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     dev_private->ai_bounce_buffer, num_samples);
9688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
9708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
9710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cfc_write_array_to_buffer(subdevice,
9720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      dev_private->
9730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      ai_bounce_buffer,
9740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      num_samples *
9750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      sizeof(short));
9768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
9778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
9788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
9798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
9818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
9820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chanlist_len) {
9838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
9840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chanlist_len -
9850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
9868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
9880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
9898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
9900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
9910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
9928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    cfc_write_array_to_buffer
9950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    (subdevice,
9960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     dev_private->ai_bounce_buffer
9970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     + position,
9980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     to_read * sizeof(short));
9998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
10008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_num_samples
10020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    -
10030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    sizeof(short) * to_read;
10128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chunk_num_samples)
10198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
10240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    bytes_written / sizeof(short);
10258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
10318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
10348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
10358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
10378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10385f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
10418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
10438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
10448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
104552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
104652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
104752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
10488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
104952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
10508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
10528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1053da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
10540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
10550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
10568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
10578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
10580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
10598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
10618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
10638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
10640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_CHAN((&insn->chanspec)[0]),
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_RANGE((&insn->chanspec)[0]), insn->n);
10668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
10698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) {
10718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
10728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
10758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
10778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
10788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
10808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
10848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
10878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralconversion_done:
10928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION) {
10948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
10968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
11020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_channel_get(),
11030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
11048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
110952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1112da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
11130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      struct comedi_subdevice *s, struct comedi_insn *insn,
11140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      unsigned int *data)
11158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
112652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1128da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
11290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
11300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
114152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
114252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
114352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
114552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1147da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
11480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1151790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
11528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
11548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
11558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
11578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
115952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
11608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1161da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
11620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1165790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
116752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
116852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
116952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
11708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
11728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
11748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
11758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
11768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
11778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
11798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
11818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
118652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
118752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
11908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1191da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
11928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
119352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
11948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
11960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
11978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
11998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
12008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
12018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
12038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
12058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
12068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
12088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
12108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
121252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
121352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
121452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
12170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
12188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
121934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
12228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1223940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1225c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) {
12268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
12278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
122852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
12318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
12330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_device != NULL;
12340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
12358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
12378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
12380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pci_device->device) {
123952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton					/*  was a particular bus/slot requested? */
12408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
12410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    || (it->options[1] != 0)) {
124252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton						/*  are we on the wrong bus/slot? */
12438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
12440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    it->options[0]
12450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    ||
12460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    PCI_SLOT(pci_device->devfn)
12470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    != it->options[1]) {
12488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
12498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
12508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
12518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
12530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					board =
12540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    (struct pci9111_board *)
12550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev->board_ptr;
12568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
12578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
12588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
12598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
12608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
12618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
12628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
12640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, it->options[0], it->options[1]);
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
12668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
12688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
12700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor,
12710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_boards[i].name,
12720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci_device->bus->number,
12730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_SLOT(pci_device->devfn),
12740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_FUNC(pci_device->devfn), pci_device->irq);
12758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
127652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
12778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (board->device_id) {
12798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	};
12808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
128152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
12828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
12848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
12858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk
12870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
12880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     dev->minor, lcr_io_base, lcr_io_range);
12898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
129052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
12918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
12920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
12930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("comedi%d: Failed to enable PCI device and request regions\n",
12940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->minor);
12958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
12968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
129752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
12988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
13008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
13018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
13030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, io_base, io_range);
13048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
13068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
13078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
13088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
13098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
13108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
13118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
13138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
131452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
13158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13185f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(pci_device->irq, pci9111_interrupt,
13198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk("comedi%d: unable to allocate irq  %u\n",
13210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       dev->minor, pci_device->irq);
13228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
132752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1329c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	error = alloc_subdevices(dev, 4);
1330c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (error < 0)
13318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
13348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
13358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
13378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
13388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
133952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
134052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
134152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
13428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
13448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
13458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
13468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
13478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
13488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
13498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
13508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
13518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
13528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
13548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
13558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
13568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
13578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
13588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
13598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
13608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
13618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
13628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
13658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
13668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
13678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
13688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
13698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
13708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
13728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
13758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
13778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
13788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
13808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
13838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
138452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
13858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1386da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
13878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
138852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev->private != 0) {
13918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
13938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
139552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
13968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev->irq != 0) {
13985f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
13998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev_private != 0 && dev_private->pci_device != 0) {
14028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev->iobase) {
14038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
14048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
14058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
14068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
1410