adl_pci9111.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
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) \
1908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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) \
1968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(flags,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
1978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_clear() \
1998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
2008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_software_trigger() \
2028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(0,PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
2038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_fifo_reset() \
2058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(PCI9111_FFEN_SET_FIFO_ENABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
2068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(PCI9111_FFEN_SET_FIFO_DISABLE,PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL); \
2078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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) \
2228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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) \
2288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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) \
2428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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) \
2488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outw(bits,PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_control_set(flags) \
2518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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); \
2558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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); \
2598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  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); \
2638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb( (data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
2648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
26552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Function prototypes */
2668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
267da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it);
268da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev);
269da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
2708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	void *data, unsigned int num_bytes, unsigned int start_chan_index);
2718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2729ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange pci9111_hr_ai_range = {
2738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	5,
2748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
2758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			BIP_RANGE(10),
2768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			BIP_RANGE(5),
2778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			BIP_RANGE(2.5),
2788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			BIP_RANGE(1.25),
2798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			BIP_RANGE(0.625)
2808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
2818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
2828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
2848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0,
2858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		0, 0},
28652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
2878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{0}
2888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
2898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
2918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
29252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
29352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
29452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
2958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
296940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
29752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
2988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
29952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
30052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
30152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
30352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
30552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
30652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
308940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
310940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      name:	"pci9111_hr",
3138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      device_id:PCI9111_HR_DEVICE_ID,
3148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ai_channel_nbr:PCI9111_AI_CHANNEL_NBR,
3158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ao_channel_nbr:PCI9111_AO_CHANNEL_NBR,
3168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ai_resolution:PCI9111_HR_AI_RESOLUTION,
3178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ai_resolution_mask:PCI9111_HR_AI_RESOLUTION_MASK,
3188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ao_resolution:PCI9111_AO_RESOLUTION,
3198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ao_resolution_mask:PCI9111_AO_RESOLUTION_MASK,
3208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ai_range_list:&pci9111_hr_ai_range,
3218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      ao_range_list:&range_bipolar10,
3228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      ai_acquisition_period_min_ns:PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
326940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton  (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
328139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
3298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      driver_name:PCI9111_DRIVER_NAME,
3308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      module:THIS_MODULE,
3318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      attach:pci9111_attach,
3328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      detach:pci9111_detach,
3338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudCOMEDI_PCI_INITCLEANUP(pci9111_driver, pci9111_pci_table);
3368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
33752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
3388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
339c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
3408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
34152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
3428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
34352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long lcr_io_base;	/*  Local configuration register base address */
3448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
3458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
3478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
3488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
3508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
3518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
3528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
3538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
35452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
3558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
35652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int timer_divisor_1;	/*  Divisor values for the 8254 timer pacer */
3578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timer_divisor_2;
3588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
35952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
3608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
361790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
362c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
3638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
364c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton#define dev_private 	((struct pci9111_private_data *)dev->private)
3658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
36652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
36752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
36852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
3698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
3718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
3738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
3748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
3758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
3768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
3778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
3788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
3798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
3808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
3828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bool LINTi1_enable,
3838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bool LINTi1_active_high,
3848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bool LINTi2_enable, bool LINTi2_active_high, bool interrupt_enable)
3858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
3868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
3878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
3898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
3908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
3918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
3928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
3938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
3948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
3958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
3968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
3988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
3998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
40352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
40452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
40552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
40752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
409da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_READ_LOAD_LSB_MSB |
4138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_MODE_0 | PCI9111_8254_BINARY_COUNTER);
4148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_READ_LOAD_LSB_MSB |
4178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_MODE_2 | PCI9111_8254_BINARY_COUNTER);
4188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_READ_LOAD_LSB_MSB |
4218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI9111_8254_MODE_2 | PCI9111_8254_BINARY_COUNTER);
4228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_udelay(1);
4248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
4268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
4278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
429655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
4308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
4318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
433655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
4348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
435da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
436655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton	enum pci9111_trigger_sources source)
4378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
4438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
4448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
4458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
4498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
4528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
4538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
4548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
4558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
459da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
4608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
4668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
4678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
471da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
4728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
4768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
4788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
4798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
4818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4833ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
4848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
4858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
4863ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
4878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
48852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
4898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
4908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
49152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
4928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
493da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
49452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	enum pci9111_ISC0_sources irq_0_source, enum pci9111_ISC1_sources irq_1_source)
4958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
50952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
51052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
51152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
51352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
517da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
5188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
51952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		true, false);
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
5298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
5318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
5338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
53752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_check_trigger_src(src,flags) \
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  tmp = src; \
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  src &= flags; \
5428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  if (!src || tmp != src) error++
5438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
545da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
546da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s, struct comedi_cmd *cmd)
5478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
5498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
5508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
5518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
552940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	struct pci9111_board *board = (struct pci9111_board *) dev->board_ptr;
5538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
55452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
5558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
5578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
5588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
5598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
5608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
5628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
5648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
5658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
56652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  step 2 : make sure trigger sources are unique and mutually compatible */
5678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
5698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(cmd->scan_begin_src != TRIG_FOLLOW) &&
5738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(cmd->scan_begin_src != TRIG_EXT))
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT)) {
5778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
5808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		!((cmd->scan_begin_src == TRIG_TIMER) ||
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			(cmd->scan_begin_src == TRIG_FOLLOW))) {
5828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
5858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		!((cmd->scan_begin_src == TRIG_EXT) ||
5868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			(cmd->scan_begin_src == TRIG_FOLLOW))) {
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
5918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
5938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
5968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
5978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
59852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
6278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
6288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) {
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
6358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
6408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(cmd->scan_end_arg != cmd->chanlist_len)) {
6418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
6428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
6468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
6478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
6508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
6518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
6568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
65752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
6588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
6608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
6618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
6628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(dev_private->timer_divisor_1),
6638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(dev_private->timer_divisor_2),
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
6658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
6668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
66852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
66952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
6748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
6758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
6768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
6818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
6828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg / scan_begin_min;
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
6848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
6858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
6918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
6938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
69852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
6998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						"entries in chanlist must be consecutive "
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						"channels,counting upwards from 0\n");
7118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						"entries in chanlist must all have the same gain\n");
7168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						"entries in chanlist must all have the same reference\n");
7218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
7268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					(board->ai_channel_nbr - 1))
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				|| (CR_CHAN(cmd->chanlist[0]) < 0)) {
7288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
7298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					"channel number is out of limits\n");
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
7398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
7418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
74252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
7438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
744da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *subdevice)
7458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
746ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
7478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			"no irq assigned for PCI9111, cannot do hardware conversion");
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
7528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
75352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
75452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
75552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
7588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
7598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
7608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
7618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
76552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
76652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
7678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
7698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
7758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async_cmd->stop_arg * async_cmd->chanlist_len;
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
7778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
7808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
7858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
7868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
7878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
78952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
7908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
7928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
7948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(dev_private->timer_divisor_1),
7968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(dev_private->timer_divisor_2),
7978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&(async_cmd->convert_arg),
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async_cmd->flags & TRIG_ROUND_MASK);
7998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->timer_divisor_1,
8028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->timer_divisor_2);
8038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			irq_on_timer_tick);
8108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			false, true, true);
8138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->scan_delay =
8158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			(async_cmd->scan_begin_arg / (async_cmd->convert_arg *
8168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				async_cmd->chanlist_len)) - 1;
8178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
8218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
8238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			irq_on_timer_tick);
8268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			false, true, true);
8288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
8338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
8378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
8408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->chanlist_len * (1 + dev_private->scan_delay);
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
8448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
8458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_and_autoscan_get());
8468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_and_fifo_get());
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
8508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter);
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->scan_delay);
8538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->chanlist_len);
8558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
8568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->chunk_num_samples);
8578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
8608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
862da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
8638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	void *data, unsigned int num_bytes, unsigned int start_chan_index)
8648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
865790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
866790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
8678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
868940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton		((struct pci9111_board *) dev->board_ptr)->ai_resolution;
8698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
8718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
8738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				(array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
8748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
8758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
8768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
8778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
8788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				PCI9111_AI_RESOLUTION_2_CMP_BIT;
8798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
88252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
88352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
88452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
8858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
8878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
88870265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
8898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
89071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
89134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
892d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
8938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
8948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
8958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
89752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
89852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
8998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
9058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
90652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PLX9050_REGISTER_INTERRUPT_CONTROL);
9098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			&& (((intcsr & (PLX9050_LINTI1_ENABLE |
9118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							PLX9050_LINTI1_STATUS))
9128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					==
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					(PLX9050_LINTI1_ENABLE |
9148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						PLX9050_LINTI1_STATUS))
9158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				|| ((intcsr & (PLX9050_LINTI2_ENABLE |
9168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							PLX9050_LINTI2_STATUS))
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					==
9188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					(PLX9050_LINTI2_ENABLE |
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						PLX9050_LINTI2_STATUS))))) {
92052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
92152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
9228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
9278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		(PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
92852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
9298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
9318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_spin_unlock_irqrestore(&dev->spinlock,
9328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				irq_flags);
9338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
9348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
9368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
9378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
9388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
9408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
9418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
9438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
9448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
9458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
9478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
9488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
9518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				PCI9111_FIFO_HALF_SIZE >
9528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				dev_private->stop_counter
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				&& !dev_private->stop_is_none ? dev_private->
9548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				stop_counter : PCI9111_FIFO_HALF_SIZE;
9558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
9568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				dev_private->ai_bounce_buffer, num_samples);
9578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
9598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
9608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cfc_write_array_to_buffer(subdevice,
9618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->ai_bounce_buffer,
962790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton					num_samples * sizeof(short));
9638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
9648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
9658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
9668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
9688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
9698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chanlist_len) {
9708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
9718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							dev_private->
9728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							chanlist_len -
9738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							dev_private->
9748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							chunk_counter;
9758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
9778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							num_samples - position)
9788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
9798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud								num_samples -
9808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud								position;
9818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
9838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							cfc_write_array_to_buffer
9848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							(subdevice,
9858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							dev_private->
9868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							ai_bounce_buffer +
9878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							position,
9888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read *
989790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton							sizeof(short));
9908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
9918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
9928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							dev_private->
9938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							chunk_num_samples -
9948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							dev_private->
9958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							chunk_counter;
9968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
9978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							num_samples - position)
9988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
9998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud								num_samples -
10008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud								position;
10018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
1003790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton							sizeof(short) *
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read;
10058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_num_samples)
10128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
1017790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton				bytes_written / sizeof(short);
10188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
10248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
10278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
10288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
10308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
10348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
10368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
10378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
103852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
103952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
104052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
10418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
104252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
10438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
10458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1046da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
1047da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
10488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
10498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
1050940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton		((struct pci9111_board *) dev->board_ptr)->ai_resolution;
10518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
10538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
10558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
10568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		CR_CHAN((&insn->chanspec)[0]),
10578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		CR_RANGE((&insn->chanspec)[0]), insn->n);
10588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
10618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0])) {
10638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
10648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
10678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
10698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
10708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
10728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
10748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
10758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
10768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
10808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	      conversion_done:
10848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION) {
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
10878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
10938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
10948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_get(),
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
10968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
110152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1104da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
1105da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
11068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
111752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1119da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
1120da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
11218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
11268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
113152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
113252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
113352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
113552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1137da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
1138da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
11398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1140790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
11418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
11438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
114852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
11498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1150da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
1151da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *subdevice, struct comedi_insn *insn, unsigned int *data)
11528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1153790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
11548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
115552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
115652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
115752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
11588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
11608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
11628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
11638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
11658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
11678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
11698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
11718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
117352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
117452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
117552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
117752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
11788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1179da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
11808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
118152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
11848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		true, false);
11858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
11878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
11888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
11898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
119052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
11918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
11938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
11948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
11968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
11988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
120152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
120252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1204da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_attach(struct comedi_device *dev, struct comedi_devconfig *it)
12058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
120634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
12088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
12098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1210940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1212c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0) {
12138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
12148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
121552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
12188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
12208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_device != NULL;
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_device =
12228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
12238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
12248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
12258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
12268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					pci_device->device) {
122752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton					/*  was a particular bus/slot requested? */
12288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
12298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						|| (it->options[1] != 0)) {
123052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton						/*  are we on the wrong bus/slot? */
12318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
12328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							it->options[0]
12338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							|| PCI_SLOT(pci_device->
12348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud								devfn) !=
12358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							it->options[1]) {
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
12378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
12388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
12398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
1241940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton					board = (struct pci9111_board *) dev->
12428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						board_ptr;
12438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
12448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
12458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
12468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
12478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
12488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
12498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
12518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev->minor, it->options[0], it->options[1]);
12528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
12538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud      found:
12558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
12578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev->minor,
12588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_boards[i].name,
12598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_device->bus->number,
12608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI_SLOT(pci_device->devfn),
12618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		PCI_FUNC(pci_device->devfn), pci_device->irq);
12628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
126352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
12648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (board->device_id) {
12668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	};
12678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
126852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
12698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
12718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
12728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n", dev->minor, lcr_io_base, lcr_io_range);
12748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
127552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
12768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
12778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk("comedi%d: Failed to enable PCI device and request regions\n", dev->minor);
12788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
12798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
128052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
12818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
12838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
12848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
12868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev->minor, io_base, io_range);
12878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
12898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
12908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
12918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
12928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
12938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
12948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
12968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
129752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
12988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (comedi_request_irq(pci_device->irq,
13028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				pci9111_interrupt,
13038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk("comedi%d: unable to allocate irq  %u\n",
13058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				dev->minor, pci_device->irq);
13068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
131152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((error = alloc_subdevices(dev, 4)) < 0)
13148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
13178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
13188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
13208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
13218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
132252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
132352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
132452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
13278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
13288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
13298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
13308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
13318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
13328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
13338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
13348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
13358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
13378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
13388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
13398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
13408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
13418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
13428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
13438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
13448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
13458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
13478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
13488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
13498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
13508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
13518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
13528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
13538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
13558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
13568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
13578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
13588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
13598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
13608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
13618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
13658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
13668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
136752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
13688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1369da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
13708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
137152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
13728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev->private != 0) {
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
13758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
137852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
13798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev->irq != 0) {
13818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_free_irq(dev->irq, dev);
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (dev_private != 0 && dev_private->pci_device != 0) {
13858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev->iobase) {
13868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
13878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
1393