adl_pci9111.c revision 727b286b44ea359d66f47d241cc2cdad36ed7bdc
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.
712f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  - Add support for the PCI-9111DG with a probe routine to identify the card
722f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    type (perhaps with the help of the channel number readback of the A/D Data
732f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    register).
748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  - Add external multiplexer support.
758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud*/
778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "../comedidev.h"
798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include <linux/delay.h>
8170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "8253.h"
848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_pci.h"
858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#include "comedi_fc.h"
868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
872f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_DRIVER_NAME	"adl_pci9111"
882f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_HR_DEVICE_ID	0x9111
898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  TODO: Add other pci9111 board id */
918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
922f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_IO_RANGE	0x0100
938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_SIZE	512
958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_CHANNEL_NBR			16
978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION			12
998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_MASK		0x0FFF
1008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_RESOLUTION_2_CMP_BIT		0x0800
1018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION		16
1038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_MASK		0xFFFF
1048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_HR_AI_RESOLUTION_2_CMP_BIT	0x8000
1058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_ACQUISITION_PERIOD_MIN_NS	10000
1078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_CHANNEL_NBR			1
1088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_AO_RESOLUTION			12
1098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AO_RESOLUTION_MASK		0x0FFF
1108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DI_CHANNEL_NBR			16
1118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define	PCI9111_DO_CHANNEL_NBR			16
1128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_DO_MASK				0xFFFF
1138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_SETTING_DELAY		10
1158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_UDELAY_US	2
1168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AI_INSTANT_READ_TIMEOUT		100
1178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_CLOCK_PERIOD_NS		500
1198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_0			0x00
1218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_1			0x40
1228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_2			0x80
1238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_COUNTER_LATCH		0x00
1248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_ONLY		0x10
1258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_MSB_ONLY		0x20
1268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_READ_LOAD_LSB_MSB		0x30
1278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_0			0x00
1288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_1			0x02
1298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_2			0x04
1308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_3			0x06
1318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_4			0x08
1328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_MODE_5			0x0A
1338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BINARY_COUNTER		0x00
1348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_8254_BCD_COUNTER		0x01
1358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/* IO address map */
1378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1382f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_FIFO_VALUE			0x00 /* AD Data stored
1392f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor								in FIFO */
1402f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_DA_OUTPUT			0x00
1412f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_DIGITAL_IO			0x02
1422f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_EXTENDED_IO_PORTS		0x04
1432f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_CHANNEL_CONTROL		0x06 /* Channel
1442f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor								selection */
1452f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_CHANNEL_READBACK		0x06
1462f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INPUT_SIGNAL_RANGE		0x08
1472f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_RANGE_STATUS_READBACK		0x08
1482f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_TRIGGER_MODE_CONTROL		0x0A
1492f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK	0x0A
1502f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_SOFTWARE_TRIGGER		0x0E
1512f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INTERRUPT_CONTROL		0x0C
1528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_0			0x40
1538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_COUNTER_1			0x42
1542f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_8254_COUNTER_2			0X44
1558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_REGISTER_8254_CONTROL			0x46
1562f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_REGISTER_INTERRUPT_CLEAR		0x48
1578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1582f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_TRIGGER_MASK				0x0F
1592f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_PTRG_OFF				(0 << 3)
1602f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_PTRG_ON					(1 << 3)
1618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_EXTERNAL				(1 << 2)
1628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_EITS_INTERNAL				(0 << 2)
1638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_SOFTWARE_TRIGGER			(0 << 1)
1648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_TPST_TIMER_PACER			(1 << 1)
1658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_ON				(1 << 0)
1668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ASCAN_OFF				(0 << 0)
1678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_ENDING_OF_AD_CONVERSION (0 << 0)
1698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL		(1 << 0)
1702f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_ISC1_SET_IRQ_ON_TIMER_TICK		(0 << 1)
1712f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_ISC1_SET_IRQ_ON_EXT_TRG			(1 << 1)
1722f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_FFEN_SET_FIFO_ENABLE			(0 << 2)
1738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FFEN_SET_FIFO_DISABLE			(1 << 2)
1748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_CHANNEL_MASK				0x0F
1768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_RANGE_MASK				0x07
1788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_EMPTY_MASK				0x10
1798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_HALF_FULL_MASK			0x20
1808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_FIFO_FULL_MASK				0x40
1818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PCI9111_AD_BUSY_MASK				0x80
1828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1832f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define PCI9111_IO_BASE (dev->iobase)
1848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud/*
1868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud * Define inlined function
1878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud */
1888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_get() \
1908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK)&0x0F)
1918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_trigger_and_autoscan_set(flags) \
193f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_TRIGGER_MODE_CONTROL)
1948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1952f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_interrupt_and_fifo_get()				   \
1962f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_MODE_INTERRUPT_READBACK) >> 4) \
1972f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor   &0x03)
1988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_and_fifo_set(flags) \
200f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL)
2018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_interrupt_clear() \
203f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CLEAR)
2048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_software_trigger() \
206f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(0, PCI9111_IO_BASE+PCI9111_REGISTER_SOFTWARE_TRIGGER)
2078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2082f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_fifo_reset() do {					\
2092f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  outb(PCI9111_FFEN_SET_FIFO_ENABLE,					\
2102f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor       PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL);		\
2112f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  outb(PCI9111_FFEN_SET_FIFO_DISABLE,					\
2122f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor       PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL);		\
2132f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  outb(PCI9111_FFEN_SET_FIFO_ENABLE,					\
2142f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor       PCI9111_IO_BASE+PCI9111_REGISTER_INTERRUPT_CONTROL);		\
2152f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  } while (0)
2168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_full() \
2188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2192f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    PCI9111_FIFO_FULL_MASK) == 0)
2208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_half_full() \
2228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2232f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    PCI9111_FIFO_HALF_FULL_MASK) == 0)
2248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_is_fifo_empty() \
2268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ((inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)& \
2272f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    PCI9111_FIFO_EMPTY_MASK) == 0)
2288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2292f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_ai_channel_set(channel)					\
2302f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  outb((channel)&PCI9111_CHANNEL_MASK,					\
2312f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor       PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_CONTROL)
2328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2332f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_ai_channel_get()					\
2342f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  (inb(PCI9111_IO_BASE+PCI9111_REGISTER_AD_CHANNEL_READBACK)		\
2352f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor   &PCI9111_CHANNEL_MASK)
2368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2372f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_ai_range_set(range)					\
2382f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  outb((range)&PCI9111_RANGE_MASK,					\
2392f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor       PCI9111_IO_BASE+PCI9111_REGISTER_INPUT_SIGNAL_RANGE)
2408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2412f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_ai_range_get()						\
2422f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  (inb(PCI9111_IO_BASE+PCI9111_REGISTER_RANGE_STATUS_READBACK)		\
2432f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor   &PCI9111_RANGE_MASK)
2448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2452f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor#define pci9111_ai_get_data()						\
2462f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor  (((inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE)>>4)		\
2472f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor    &PCI9111_AI_RESOLUTION_MASK)					\
2482f6df34cd3455245c44b420d7c3fb11d1137df79Mark Rankilor   ^ PCI9111_AI_RESOLUTION_2_CMP_BIT)
2498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_hr_ai_get_data() \
2518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  (inw(PCI9111_IO_BASE+PCI9111_REGISTER_AD_FIFO_VALUE) & PCI9111_HR_AI_RESOLUTION_MASK) \
2528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  ^ PCI9111_HR_AI_RESOLUTION_2_CMP_BIT
2538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_ao_set_data(data) \
255f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outw(data&PCI9111_AO_RESOLUTION_MASK, PCI9111_IO_BASE+PCI9111_REGISTER_DA_OUTPUT)
2568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_di_get_bits() \
2588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  inw(PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_do_set_bits(bits) \
261f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outw(bits, PCI9111_IO_BASE+PCI9111_REGISTER_DIGITAL_IO)
2628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_control_set(flags) \
264f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton  outb(flags, PCI9111_IO_BASE+PCI9111_REGISTER_8254_CONTROL)
2658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_0_set(data) \
2678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0); \
26853106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_0)
2698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_1_set(data) \
2718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1); \
27253106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_1)
2738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_8254_counter_2_set(data) \
2758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  outb(data & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2); \
27653106ae68acf6eda9593150a25fc44e30fd5ff68Bill Pemberton  outb((data >> 8) & 0xFF, PCI9111_IO_BASE+PCI9111_REGISTER_8254_COUNTER_2)
2778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
27852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Function prototypes */
2798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
282da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev);
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
2850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
2860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index);
2878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2889ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange pci9111_hr_ai_range = {
2898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	5,
2908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
2910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
2950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.625)
2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
2978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
2988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
2998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic DEFINE_PCI_DEVICE_TABLE(pci9111_pci_table) = {
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	{
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_ADLINK, PCI9111_HR_DEVICE_ID, PCI_ANY_ID,
3020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    PCI_ANY_ID, 0, 0, 0},
3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    /* { PCI_VENDOR_ID_ADLINK, PCI9111_HG_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, */
3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	{
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	0}
3068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel PacaudMODULE_DEVICE_TABLE(pci, pci9111_pci_table);
3098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
31052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
31152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Board specification structure */
31252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  */
3138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
314940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstruct pci9111_board {
31552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const char *name;	/*  driver name */
3168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int device_id;
31752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_channel_nbr;	/*  num of A/D chans */
31852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_channel_nbr;	/*  num of D/A chans */
31952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ai_resolution;	/*  resolution of A/D */
3208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ai_resolution_mask;
32152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_resolution;	/*  resolution of D/A */
3228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int ao_resolution_mask;
32352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ai_range_list;	/*  rangelist for A/D */
32452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	const struct comedi_lrange *ao_range_list;	/*  rangelist for D/A */
3258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int ai_acquisition_period_min_ns;
326940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton};
3278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
328940579fbae1a3a8967fe619562c8e78080dd873dBill Pembertonstatic const struct pci9111_board pci9111_boards[] = {
3298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	{
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci9111_hr",
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = PCI9111_HR_DEVICE_ID,
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_channel_nbr = PCI9111_AI_CHANNEL_NBR,
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_channel_nbr = PCI9111_AO_CHANNEL_NBR,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution = PCI9111_HR_AI_RESOLUTION,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_resolution_mask = PCI9111_HR_AI_RESOLUTION_MASK,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution = PCI9111_AO_RESOLUTION,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_resolution_mask = PCI9111_AO_RESOLUTION_MASK,
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_range_list = &pci9111_hr_ai_range,
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_range_list = &range_bipolar10,
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_acquisition_period_min_ns = PCI9111_AI_ACQUISITION_PERIOD_MIN_NS}
3418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
3438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define pci9111_board_nbr \
344940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton  (sizeof(pci9111_boards)/sizeof(struct pci9111_board))
3458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
346139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver pci9111_driver = {
34768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = PCI9111_DRIVER_NAME,
34868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
34968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = pci9111_attach,
35068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = pci9111_detach,
3518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud};
3528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
353727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit pci9111_driver_pci_probe(struct pci_dev *dev,
354727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas					      const struct pci_device_id *ent)
355727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
356727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, pci9111_driver.driver_name);
357727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
358727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
359727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit pci9111_driver_pci_remove(struct pci_dev *dev)
360727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
361727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
362727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
363727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
364727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver pci9111_driver_pci_driver = {
365727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = pci9111_pci_table,
366727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &pci9111_driver_pci_probe,
367727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&pci9111_driver_pci_remove)
368727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
369727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
370727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init pci9111_driver_init_module(void)
371727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
372727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
373727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
374727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&pci9111_driver);
375727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
376727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
377727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
378727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci9111_driver_pci_driver.name = (char *)pci9111_driver.driver_name;
379727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&pci9111_driver_pci_driver);
380727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
381727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
382727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit pci9111_driver_cleanup_module(void)
383727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
384727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&pci9111_driver_pci_driver);
385727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&pci9111_driver);
386727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
387727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
388727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(pci9111_driver_init_module);
389727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(pci9111_driver_cleanup_module);
3908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
39152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Private data structure */
3928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
393c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pembertonstruct pci9111_private_data {
3948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
39552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long io_range;	/*  PCI6503 io range */
3968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
39752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	unsigned long lcr_io_base;	/*  Local configuration register base address */
3988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long lcr_io_range;
3998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_counter;
4018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int stop_is_none;
4028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int scan_delay;
4048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chanlist_len;
4058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_counter;
4068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned int chunk_num_samples;
4078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
40852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int ao_readback;	/*  Last written analog output data */
4098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
410525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	unsigned int timer_divisor_1;	/*  Divisor values for the 8254 timer pacer */
411525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	unsigned int timer_divisor_2;
4128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
41352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	int is_valid;		/*  Is device valid */
4148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
415790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_bounce_buffer[2 * PCI9111_FIFO_HALF_SIZE];
416c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton};
4178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
418c350fa1944f4ec1fe392ce0f3fc879f3899bb15dBill Pemberton#define dev_private 	((struct pci9111_private_data *)dev->private)
4198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
42052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
42152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  PLX9050 SECTION */
42252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_REGISTER_INTERRUPT_CONTROL 0x4c
4258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ENABLE		(1 << 0)
4278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_ACTIVE_HIGH	(1 << 1)
4288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI1_STATUS		(1 << 2)
4298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ENABLE		(1 << 3)
4308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_ACTIVE_HIGH	(1 << 4)
4318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_LINTI2_STATUS		(1 << 5)
4328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_PCI_INTERRUPT_ENABLE	(1 << 6)
4338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#define PLX9050_SOFTWARE_INTERRUPT	(1 << 7)
4348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic void plx9050_interrupt_control(unsigned long io_base,
4360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_enable,
4370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi1_active_high,
4380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_enable,
4390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool LINTi2_active_high,
4400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      bool interrupt_enable)
4418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags = 0;
4438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_enable)
4458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ENABLE;
4468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi1_active_high)
4478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI1_ACTIVE_HIGH;
4488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_enable)
4498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ENABLE;
4508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (LINTi2_active_high)
4518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_LINTI2_ACTIVE_HIGH;
4528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (interrupt_enable)
4548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PLX9050_PCI_INTERRUPT_ENABLE;
4558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	outb(flags, io_base + PLX9050_REGISTER_INTERRUPT_CONTROL);
4578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
45952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
46052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  MISCELLANEOUS SECTION */
46152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
4628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
46352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  8254 timer */
4648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
465da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_timer_set(struct comedi_device *dev)
4668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_0 |
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_0 |
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_1 |
4730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_control_set(PCI9111_8254_COUNTER_2 |
4780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_READ_LOAD_LSB_MSB |
4790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_MODE_2 |
4800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 PCI9111_8254_BINARY_COUNTER);
4818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4825f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
4838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_2_set(dev_private->timer_divisor_2);
4858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_8254_counter_1_set(dev_private->timer_divisor_1);
4868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
4878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
488655f78f6aaa059ad262bc55e1c3575724c14867bBill Pembertonenum pci9111_trigger_sources {
4898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	software,
4908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	timer_pacer,
4918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	external
492655f78f6aaa059ad262bc55e1c3575724c14867bBill Pemberton};
4938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
494da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_trigger_source_set(struct comedi_device *dev,
4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       enum pci9111_trigger_sources source)
4968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
4978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
4988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
4998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x09;
5008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (source) {
5028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case software:
5038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_SOFTWARE_TRIGGER;
5048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case timer_pacer:
5078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_INTERNAL | PCI9111_TPST_TIMER_PACER;
5088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case external:
5118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_EITS_EXTERNAL;
5128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
5138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
5148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
518da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_pretrigger_set(struct comedi_device *dev, bool pretrigger)
5198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x07;
5238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pretrigger)
5258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_PTRG_ON;
5268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
530da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_autoscan_set(struct comedi_device *dev, bool autoscan)
5318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_trigger_and_autoscan_get() & 0x0e;
5358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (autoscan)
5378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ASCAN_ON;
5388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_and_autoscan_set(flags);
5408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5423ba97b3c6258cb67450e0873584489f97d0debc5Bill Pembertonenum pci9111_ISC0_sources {
5438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_eoc,
5448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_fifo_half_full
5453ba97b3c6258cb67450e0873584489f97d0debc5Bill Pemberton};
5468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
54752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pembertonenum pci9111_ISC1_sources {
5488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_timer_tick,
5498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	irq_on_external_trigger
55052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton};
5518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
552da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void pci9111_interrupt_source_set(struct comedi_device *dev,
5530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC0_sources irq_0_source,
5540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					 enum pci9111_ISC1_sources irq_1_source)
5558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
5568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int flags;
5578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	flags = pci9111_interrupt_and_fifo_get() & 0x04;
5598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_0_source == irq_on_fifo_half_full)
5618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC0_SET_IRQ_ON_FIFO_HALF_FULL;
5628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (irq_1_source == irq_on_external_trigger)
5648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		flags |= PCI9111_ISC1_SET_IRQ_ON_EXT_TRG;
5658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_and_fifo_set(flags);
5678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
56952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
57052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  HARDWARE TRIGGERED ANALOG INPUT SECTION */
57152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
5728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
57352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Cancel analog input autoscan */
5748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_DO_CMD_DEBUG
5768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_cancel(struct comedi_device *dev,
5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
5798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
58052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Disable interrupts */
5818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
5830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
5848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
5868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
5888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
5908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
5928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_cancel\n");
5938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
5948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
5958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
5968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
5978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
59852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Test analog input command */
5998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
600f7cbd7aad063b2a4b7aff6a743b2b00015ce3c3eBill Pemberton#define pci9111_check_trigger_src(src, flags) \
6018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  tmp = src; \
6028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  src &= flags; \
6038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud  if (!src || tmp != src) error++
6048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
606da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ai_do_cmd_test(struct comedi_device *dev,
6070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       struct comedi_subdevice *s, struct comedi_cmd *cmd)
6088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
6098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int tmp;
6108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error = 0;
6118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int range, reference;
6128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
6130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct pci9111_board *board = (struct pci9111_board *)dev->board_ptr;
6148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
61552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 1 : check if trigger are trivialy valid */
6168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->start_src, TRIG_NOW);
6188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_begin_src,
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT);
6208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->convert_src, TRIG_TIMER | TRIG_EXT);
6218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->scan_end_src, TRIG_COUNT);
6228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_check_trigger_src(cmd->stop_src, TRIG_COUNT | TRIG_NONE);
6238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 1;
6268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
62752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  step 2 : make sure trigger sources are unique and mutually compatible */
6288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->start_src != TRIG_NOW)
6308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src != TRIG_TIMER) &&
6330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_FOLLOW) &&
6340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_src != TRIG_EXT))
6358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6372306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((cmd->convert_src != TRIG_TIMER) && (cmd->convert_src != TRIG_EXT))
6388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_TIMER) ||
6412306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) &&
6440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    !((cmd->scan_begin_src == TRIG_EXT) ||
6452306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	      (cmd->scan_begin_src == TRIG_FOLLOW)))
6468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6472306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom
6488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_end_src != TRIG_COUNT)
6508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src != TRIG_COUNT) && (cmd->stop_src != TRIG_NONE))
6528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
6558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 2;
6568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
65752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 3 : make sure arguments are trivialy compatible */
6588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len < 1) {
6608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = 1;
6618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist_len > board->ai_channel_nbr) {
6658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->chanlist_len = board->ai_channel_nbr;
6668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->start_src == TRIG_NOW) && (cmd->start_arg != 0)) {
6708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->start_arg = 0;
6718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_TIMER) &&
6750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_arg < board->ai_acquisition_period_min_ns)) {
6768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = board->ai_acquisition_period_min_ns;
6778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->convert_src == TRIG_EXT) && (cmd->convert_arg != 0)) {
6808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->convert_arg = 0;
6818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_TIMER) &&
6850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_begin_arg < board->ai_acquisition_period_min_ns)) {
6868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = board->ai_acquisition_period_min_ns;
6878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_FOLLOW) && (cmd->scan_begin_arg != 0)) {
6908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_begin_src == TRIG_EXT) && (cmd->scan_begin_arg != 0)) {
6948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_begin_arg = 0;
6958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
6968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
6978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
6988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->scan_end_src == TRIG_COUNT) &&
6990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->scan_end_arg != cmd->chanlist_len)) {
7008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->scan_end_arg = cmd->chanlist_len;
7018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_COUNT) && (cmd->stop_arg < 1)) {
7058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 1;
7068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((cmd->stop_src == TRIG_NONE) && (cmd->stop_arg != 0)) {
7098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		cmd->stop_arg = 0;
7108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		error++;
7118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 3;
7158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
71652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 4 : fix up any arguments */
7178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->convert_src == TRIG_TIMER) {
7198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		tmp = cmd->convert_arg;
7208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
7210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
7220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
7230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
7240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
7258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (tmp != cmd->convert_arg)
7268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			error++;
7278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
72852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  There's only one timer on this card, so the scan_begin timer must */
72952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  be a multiple of chanlist_len*convert_arg */
7308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->scan_begin_src == TRIG_TIMER) {
7328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_min;
7348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_begin_arg;
7358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		unsigned int scan_factor;
7368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		scan_begin_min = cmd->chanlist_len * cmd->convert_arg;
7388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->scan_begin_arg != scan_begin_min) {
7408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (scan_begin_min < cmd->scan_begin_arg) {
7418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_factor =
7420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg / scan_begin_min;
7438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				scan_begin_arg = scan_factor * scan_begin_min;
7448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (cmd->scan_begin_arg != scan_begin_arg) {
7458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					cmd->scan_begin_arg = scan_begin_arg;
7468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
7498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				cmd->scan_begin_arg = scan_begin_min;
7508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 4;
7578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
75852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Step 5 : check channel list */
7598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (cmd->chanlist) {
7618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		range = CR_RANGE(cmd->chanlist[0]);
7638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		reference = CR_AREF(cmd->chanlist[0]);
7648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (cmd->chanlist_len > 1) {
7668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < cmd->chanlist_len; i++) {
7678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_CHAN(cmd->chanlist[i]) != i) {
7688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must be consecutive "
7700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "channels,counting upwards from 0\n");
7718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_RANGE(cmd->chanlist[i]) != range) {
7748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same gain\n");
7768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (CR_AREF(cmd->chanlist[i]) != reference) {
7798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					comedi_error(dev,
7800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     "entries in chanlist must all have the same reference\n");
7818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					error++;
7828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
7838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		} else {
7858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if ((CR_CHAN(cmd->chanlist[0]) >
7860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     (board->ai_channel_nbr - 1))
7870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    || (CR_CHAN(cmd->chanlist[0]) < 0)) {
7888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				comedi_error(dev,
7890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "channel number is out of limits\n");
7908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				error++;
7918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
7928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
7938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
7948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (error)
7968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return 5;
7978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
7988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
7998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
8018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
80252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog input command */
8038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_ai_do_cmd(struct comedi_device *dev,
8050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *subdevice)
8068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
807ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *async_cmd = &subdevice->async->cmd;
8088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->irq) {
8108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev,
8110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for PCI9111, cannot do hardware conversion");
8128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
81452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set channel scan limit */
81552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  PCI9111 allows only scanning from channel 0 to channel n */
81652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: handle the case of an external multiplexer */
8178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (async_cmd->chanlist_len > 1) {
8198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set((async_cmd->chanlist_len) - 1);
8208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, true);
8218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	} else {
8228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_channel_set(CR_CHAN(async_cmd->chanlist[0]));
8238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_autoscan_set(dev, false);
8248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
82652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set gain */
82752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  This is the same gain on every channel */
8288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_range_set(CR_RANGE(async_cmd->chanlist[0]));
8308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Set counter */
8328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->stop_src) {
8348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_COUNT:
8358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter =
8360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    async_cmd->stop_arg * async_cmd->chanlist_len;
8378cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 0;
8388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_NONE:
8418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_counter = 0;
8428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->stop_is_none = 1;
8438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid stop trigger");
8478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
85052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set timer pacer */
8518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->scan_delay = 0;
8538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	switch (async_cmd->convert_src) {
8548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_TIMER:
8558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		i8253_cascade_ns_to_timer_2div(PCI9111_8254_CLOCK_PERIOD_NS,
8560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_1),
8570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(dev_private->timer_divisor_2),
8580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(async_cmd->convert_arg),
8590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       async_cmd->
8600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       flags & TRIG_ROUND_MASK);
8618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
8628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		printk(PCI9111_DRIVER_NAME ": divisors = %d, %d\n",
8630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_1,
8640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       dev_private->timer_divisor_2);
8658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
8668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, software);
8688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_timer_set(dev);
8698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, timer_pacer);
8738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->scan_delay =
8770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (async_cmd->scan_begin_arg / (async_cmd->convert_arg *
8780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						  async_cmd->chanlist_len)) - 1;
8798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	case TRIG_EXT:
8838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_trigger_source_set(dev, external);
8858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
8868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_interrupt_source_set(dev, irq_on_fifo_half_full,
8870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     irq_on_timer_tick);
8888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		plx9050_interrupt_control(dev_private->lcr_io_base, true, true,
8890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  false, true, true);
8908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		break;
8928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	default:
8948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "Invalid convert trigger");
8958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -1;
8968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
8978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
8988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->stop_counter *= (1 + dev_private->scan_delay);
8998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chanlist_len = async_cmd->chanlist_len;
9008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_counter = 0;
9018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->chunk_num_samples =
9020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    dev_private->chanlist_len * (1 + dev_private->scan_delay);
9038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_DO_CMD_DEBUG
9058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": start interruptions!\n");
9068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": trigger source = %2x\n",
9070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_trigger_and_autoscan_get());
9088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": irq source     = %2x\n",
9090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_interrupt_and_fifo_get());
9108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_do_cmd\n");
9118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": stop counter   = %d\n",
9120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->stop_counter);
9138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": scan delay     = %d\n",
9140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->scan_delay);
9158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chanlist_len   = %d\n",
9160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chanlist_len);
9178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": chunk num samples = %d\n",
9180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev_private->chunk_num_samples);
9198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
9208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
9228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void pci9111_ai_munge(struct comedi_device *dev,
9250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s, void *data,
9260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int num_bytes,
9270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     unsigned int start_chan_index)
9288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
929790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int i, num_samples = num_bytes / sizeof(short);
930790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short *array = data;
9318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
9338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < num_samples; i++) {
9358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (resolution == PCI9111_HR_AI_RESOLUTION)
9368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (array[i] & PCI9111_HR_AI_RESOLUTION_MASK) ^
9380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_HR_AI_RESOLUTION_2_CMP_BIT;
9398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		else
9408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			array[i] =
9410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    ((array[i] >> 4) & PCI9111_AI_RESOLUTION_MASK) ^
9420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_AI_RESOLUTION_2_CMP_BIT;
9438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
9458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
94652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
94752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INTERRUPT SECTION */
94852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
9498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef INTERRUPT_DEBUG
9518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
95270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t pci9111_interrupt(int irq, void *p_device)
9538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
95471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = p_device;
95534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice = dev->read_subdev;
956d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
9578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long irq_flags;
9588cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned char intcsr;
9598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!dev->attached) {
96152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Ignore interrupt before device fully attached. */
96252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Might not even have allocated subdevices yet! */
9638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	async = subdevice->async;
9678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9685f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
9698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
97052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Check if we are source of interrupt */
9718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	intcsr = inb(dev_private->lcr_io_base +
9720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     PLX9050_REGISTER_INTERRUPT_CONTROL);
9738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (!(((intcsr & PLX9050_PCI_INTERRUPT_ENABLE) != 0)
9740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	      && (((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   == (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS))
9760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		  || ((intcsr & (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))
9770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      == (PLX9050_LINTI2_ENABLE | PLX9050_LINTI2_STATUS))))) {
97852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Not the source of the interrupt. */
97952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  (N.B. not using PLX9050_SOFTWARE_INTERRUPT) */
9805f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return IRQ_NONE;
9828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
9838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((intcsr & (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) ==
9850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (PLX9050_LINTI1_ENABLE | PLX9050_LINTI1_STATUS)) {
98652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton		/*  Interrupt comes from fifo_half-full signal */
9878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_full()) {
9890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			spin_unlock_irqrestore(&dev->spinlock, irq_flags);
9908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_error(dev, PCI9111_DRIVER_NAME " fifo overflow");
9918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_interrupt_clear();
9928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_ai_cancel(dev, subdevice);
9938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
9948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_event(dev, subdevice);
9958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return IRQ_HANDLED;
9978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
9988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
9998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci9111_is_fifo_half_full()) {
10008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int num_samples;
10018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			unsigned int bytes_written = 0;
10028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef INTERRUPT_DEBUG
10048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk(PCI9111_DRIVER_NAME ": fifo is half full\n");
10058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
10068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			num_samples =
10080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE >
10090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    dev_private->stop_counter
10100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    && !dev_private->
10110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    stop_is_none ? dev_private->stop_counter :
10120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    PCI9111_FIFO_HALF_SIZE;
10138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			insw(PCI9111_IO_BASE + PCI9111_REGISTER_AD_FIFO_VALUE,
10140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     dev_private->ai_bounce_buffer, num_samples);
10158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (dev_private->scan_delay < 1) {
10178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				bytes_written =
10180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cfc_write_array_to_buffer(subdevice,
10190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      dev_private->
10200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      ai_bounce_buffer,
10210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      num_samples *
10220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							      sizeof(short));
10238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			} else {
10248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int position = 0;
10258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				int to_read;
10268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				while (position < num_samples) {
10288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter <
10290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chanlist_len) {
10308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chanlist_len -
10320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    cfc_write_array_to_buffer
10420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    (subdevice,
10430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     dev_private->ai_bounce_buffer
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     + position,
10450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						     to_read * sizeof(short));
10468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					} else {
10478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						to_read =
10480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_num_samples
10490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    -
10500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    dev_private->chunk_counter;
10518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (to_read >
10520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    num_samples - position)
10538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							to_read =
10540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    num_samples -
10550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							    position;
10568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						bytes_written +=
10580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    sizeof(short) * to_read;
10598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
10608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					position += to_read;
10628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->chunk_counter += to_read;
10638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if (dev_private->chunk_counter >=
10650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev_private->chunk_num_samples)
10668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						dev_private->chunk_counter = 0;
10678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
10688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
10698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			dev_private->stop_counter -=
10710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    bytes_written / sizeof(short);
10728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
10738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if ((dev_private->stop_counter == 0) && (!dev_private->stop_is_none)) {
10768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		async->events |= COMEDI_CB_EOA;
10778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_cancel(dev, subdevice);
10788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
10798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	/* Very important, otherwise another interrupt request will be inserted
10818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	 * and will cause driver hangs on processing interrupt event. */
10828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_interrupt_clear();
10848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10855f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
10868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	comedi_event(dev, subdevice);
10888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return IRQ_HANDLED;
10908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
10918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
109252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
109352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INSTANT ANALOG INPUT OUTPUT SECTION */
109452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
10958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
109652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  analog instant input */
10978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
10988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#undef AI_INSN_DEBUG
10998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1100da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ai_insn_read(struct comedi_device *dev,
11010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int resolution =
11050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ((struct pci9111_board *)dev->board_ptr)->ai_resolution;
11068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int timeout, i;
11088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn set c/r/n = %2x/%2x/%2x\n",
11110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_CHAN((&insn->chanspec)[0]),
11120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       CR_RANGE((&insn->chanspec)[0]), insn->n);
11138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_ai_channel_set(CR_CHAN((&insn->chanspec)[0]));
11168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11172306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if ((pci9111_ai_range_get()) != CR_RANGE((&insn->chanspec)[0]))
11188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ai_range_set(CR_RANGE((&insn->chanspec)[0]));
11198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_fifo_reset();
11218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_software_trigger();
11248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		timeout = PCI9111_AI_INSTANT_READ_TIMEOUT;
11268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		while (timeout--) {
11288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			if (!pci9111_is_fifo_empty())
11298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				goto conversion_done;
11308cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
11318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		comedi_error(dev, "A/D read timeout");
11338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = 0;
11348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_fifo_reset();
11358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ETIME;
11368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralconversion_done:
11388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11392306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (resolution == PCI9111_HR_AI_RESOLUTION)
11408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_hr_ai_get_data();
11412306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		else
11428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			data[i] = pci9111_ai_get_data();
11438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#ifdef AI_INSN_DEBUG
11468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk(PCI9111_DRIVER_NAME ": ai_insn get c/r/t = %2x/%2x/%2x\n",
11470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_channel_get(),
11480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_ai_range_get(), pci9111_trigger_and_autoscan_get());
11498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud#endif
11508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
115452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog instant output */
11558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaudstatic int
1157da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonpci9111_ao_insn_write(struct comedi_device *dev,
11580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      struct comedi_subdevice *s, struct comedi_insn *insn,
11590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      unsigned int *data)
11608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11618cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (i = 0; i < insn->n; i++) {
11648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci9111_ao_set_data(data[i]);
11658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		dev_private->ao_readback = data[i];
11668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
11678cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11698cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
117152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Analog output readback */
11728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1173da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_ao_insn_read(struct comedi_device *dev,
11740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
11750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
11778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int i;
11788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11792306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	for (i = 0; i < insn->n; i++)
11808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		data[i] = dev_private->ao_readback & PCI9111_AO_RESOLUTION_MASK;
11818cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return i;
11838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
11848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
118652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  DIGITAL INPUT OUTPUT SECTION */
118752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
11888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
118952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital inputs */
11908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1191da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_di_insn_bits(struct comedi_device *dev,
11920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
11930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
11948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1195790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
11968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
11978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = pci9111_di_get_bits();
11988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
11998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
120352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Digital outputs */
12048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1205da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_do_insn_bits(struct comedi_device *dev,
12060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *subdevice,
12070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_insn *insn, unsigned int *data)
12088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
1209790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int bits;
12108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
121152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Only set bits that have been masked */
121252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[0] = mask */
121352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  data[1] = bit state */
12148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[0] &= PCI9111_DO_MASK;
12168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits = subdevice->state;
12188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits &= ~data[0];
12198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	bits |= data[0] & data[1];
12208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->state = bits;
12218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_do_set_bits(bits);
12238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	data[1] = bits;
12258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12268cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 2;
12278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12288cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
122952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
123052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  INITIALISATION SECTION */
123152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  ------------------------------------------------------------------ */
12328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
123352f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Reset device */
12348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1235da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_reset(struct comedi_device *dev)
12368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
123752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Set trigger source to software */
12388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	plx9050_interrupt_control(dev_private->lcr_io_base, true, true, true,
12400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  true, false);
12418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_trigger_source_set(dev, software);
12438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_pretrigger_set(dev, false);
12448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_autoscan_set(dev, false);
12458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
124652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset 8254 chip */
12478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_1 = 0;
12498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->timer_divisor_2 = 0;
12508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_timer_set(dev);
12528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
12548cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
12558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
125652f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Attach */
125752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Register PCI device */
125852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*       - Declare device driver capability */
12598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int pci9111_attach(struct comedi_device *dev,
12610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
12628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
126334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *subdevice;
12648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	unsigned long io_base, io_range, lcr_io_base, lcr_io_range;
12658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	struct pci_dev *pci_device;
12668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	int error, i;
1267940579fbae1a3a8967fe619562c8e78080dd873dBill Pemberton	const struct pci9111_board *board;
12688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12692306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (alloc_private(dev, sizeof(struct pci9111_private_data)) < 0)
12708cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -ENOMEM;
127152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Probe the device to determine what device in the series it is. */
12728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: " PCI9111_DRIVER_NAME " driver\n", dev->minor);
12748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	for (pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
12760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_device != NULL;
12770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     pci_device = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_device)) {
12788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (pci_device->vendor == PCI_VENDOR_ID_ADLINK) {
12798cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			for (i = 0; i < pci9111_board_nbr; i++) {
12808cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				if (pci9111_boards[i].device_id ==
12810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    pci_device->device) {
128252f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton					/*  was a particular bus/slot requested? */
12838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					if ((it->options[0] != 0)
12840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    || (it->options[1] != 0)) {
128552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton						/*  are we on the wrong bus/slot? */
12868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						if (pci_device->bus->number !=
12870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    it->options[0]
12880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    ||
12890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    PCI_SLOT(pci_device->devfn)
12900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						    != it->options[1]) {
12918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud							continue;
12928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud						}
12938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					}
12948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
12958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev->board_ptr = pci9111_boards + i;
12960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					board =
12970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    (struct pci9111_board *)
12980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    dev->board_ptr;
12998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					dev_private->pci_device = pci_device;
13008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud					goto found;
13018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				}
13028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			}
13038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
13070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, it->options[0], it->options[1]);
13088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return -EIO;
13098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
13118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: found %s (b:s:f=%d:%d:%d) , irq=%d\n",
13130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor,
13140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci9111_boards[i].name,
13150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pci_device->bus->number,
13160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_SLOT(pci_device->devfn),
13170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       PCI_FUNC(pci_device->devfn), pci_device->irq);
13188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
131952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Warn about non-tested boards. */
13208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
132152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read local configuration register base address [PCI_BASE_ADDRESS #1]. */
13228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_base = pci_resource_start(pci_device, 1);
13248cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	lcr_io_range = pci_resource_len(pci_device, 1);
13258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk
13270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ("comedi%d: local configuration registers at address 0x%4lx [0x%4lx]\n",
13280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     dev->minor, lcr_io_base, lcr_io_range);
13298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
133052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Enable PCI device and request regions */
13318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (comedi_pci_enable(pci_device, PCI9111_DRIVER_NAME) < 0) {
13320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
13330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    ("comedi%d: Failed to enable PCI device and request regions\n",
13340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->minor);
13358cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return -EIO;
13368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
133752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Read PCI6308 register base address [PCI_BASE_ADDRESS #2]. */
13388cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_base = pci_resource_start(pci_device, 2);
13408cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	io_range = pci_resource_len(pci_device, 2);
13418cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	printk("comedi%d: 6503 registers at address 0x%4lx [0x%4lx]\n",
13430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       dev->minor, io_base, io_range);
13448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->iobase = io_base;
13468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->board_name = board->name;
13478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->io_range = io_range;
13488cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 0;
13498cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_base = lcr_io_base;
13508cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->lcr_io_range = lcr_io_range;
13518cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13528cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	pci9111_reset(dev);
13538cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
135452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Irq setup */
13558cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13568cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = 0;
13578cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	if (pci_device->irq > 0) {
13585f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(pci_device->irq, pci9111_interrupt,
13598cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud				IRQF_SHARED, PCI9111_DRIVER_NAME, dev) != 0) {
13608cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			printk("comedi%d: unable to allocate irq  %u\n",
13610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       dev->minor, pci_device->irq);
13628cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			return -EINVAL;
13638cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		}
13648cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
13658cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->irq = pci_device->irq;
13668cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
136752f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer setup (according to option[2]). */
13688cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1369c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	error = alloc_subdevices(dev, 4);
1370c3744138715045adb316284ee7a1e608f0278f6cBill Pemberton	if (error < 0)
13718cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		return error;
13728cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13738cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 0;
13748cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev->read_subdev = subdevice;
13758cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13768cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AI;
13778cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_CMD_READ;
13788cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
137952f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  TODO: Add external multiplexer data */
138052f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     if (devpriv->usemux) { subdevice->n_chan = devpriv->usemux; } */
138152f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*     else { subdevice->n_chan = this_board->n_aichan; } */
13828cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13838cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ai_channel_nbr;
13848cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ai_resolution_mask;
13858cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ai_channel_nbr;
13868cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ai_range_list;
13878cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->cancel = pci9111_ai_cancel;
13888cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ai_insn_read;
13898cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmdtest = pci9111_ai_do_cmd_test;
13908cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->do_cmd = pci9111_ai_do_cmd;
13918cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->munge = pci9111_ai_munge;
13928cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
13938cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 1;
13948cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_AO;
13958cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_WRITABLE | SDF_COMMON;
13968cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = board->ao_channel_nbr;
13978cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = board->ao_resolution_mask;
13988cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->len_chanlist = board->ao_channel_nbr;
13998cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = board->ao_range_list;
14008cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_write = pci9111_ao_insn_write;
14018cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_read = pci9111_ao_insn_read;
14028cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14038cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 2;
14048cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DI;
14058cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE;
14068cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DI_CHANNEL_NBR;
14078cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14088cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14098cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_di_insn_bits;
14108cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14118cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice = dev->subdevices + 3;
14128cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->type = COMEDI_SUBD_DO;
14138cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->subdev_flags = SDF_READABLE | SDF_WRITABLE;
14148cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->n_chan = PCI9111_DO_CHANNEL_NBR;
14158cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->maxdata = 1;
14168cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->range_table = &range_digital;
14178cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	subdevice->insn_bits = pci9111_do_insn_bits;
14188cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14198cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	dev_private->is_valid = 1;
14208cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14218cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14228cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
14238cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
142452f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton/*  Detach */
14258cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1426da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int pci9111_detach(struct comedi_device *dev)
14278cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud{
142852f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Reset device */
14298cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1430525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev->private != NULL) {
14318cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		if (dev_private->is_valid)
14328cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			pci9111_reset(dev);
14338cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14348cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
143552f8ac983079ad6bba3c055152a39ccc5e76350aBill Pemberton	/*  Release previously allocated irq */
14368cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14372306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom	if (dev->irq != 0)
14385f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
14398cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
1440525d1b1395858606103d4663a570cc8725ff2cedGreg Kroah-Hartman	if (dev_private != NULL && dev_private->pci_device != NULL) {
14412306d9b1ee065d0dfb56af4cd05195ec61d69256Rich Folsom		if (dev->iobase)
14428cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud			comedi_pci_disable(dev_private->pci_device);
14438cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud		pci_dev_put(dev_private->pci_device);
14448cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	}
14458cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud
14468cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud	return 0;
14478cb9b9fb975476b6b3128f2d192d4e2ddf94c5a0Emmanuel Pacaud}
144890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
144990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
145090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
145190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1452