cb_pcidas.c revision 20fb2280815510533cbd7785b53821ca7209345b
159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    comedi/drivers/cb_pcidas.c
359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    David Schleef and the rest of the Comedi developers comunity.
659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    COMEDI - Linux Control and Measurement Device Interface
1159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
1259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    This program is free software; you can redistribute it and/or modify
1459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    it under the terms of the GNU General Public License as published by
1559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    the Free Software Foundation; either version 2 of the License, or
1659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    (at your option) any later version.
1759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    This program is distributed in the hope that it will be useful,
1959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    but WITHOUT ANY WARRANTY; without even the implied warranty of
2059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
2159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    GNU General Public License for more details.
2259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    You should have received a copy of the GNU General Public License
2459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    along with this program; if not, write to the Free Software
2559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
2659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez************************************************************************
2859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/
2959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
3059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDriver: cb_pcidas
3159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDescription: MeasurementComputing PCI-DAS series with the AMCC S5933 PCI controller
3259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezAuthor: Ivan Martinez <imr@oersted.dtu.dk>,
3359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  Frank Mori Hess <fmhess@users.sourceforge.net>
3459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezUpdated: 2003-3-11
3559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezDevices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
3659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
3759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
3859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
3959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezStatus:
4059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  There are many reports of the driver being used with most of the
4159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  supported cards. Despite no detailed log is maintained, it can
4259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  be said that the driver is quite tested and stable.
4359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
4459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  The boards may be autocalibrated using the comedi_calibrate
4559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  utility.
4659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
4759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezConfiguration options:
4859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  [0] - PCI bus of device (optional)
4959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  [1] - PCI slot of device (optional)
5059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  If bus/slot is not specified, the first supported
5159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez  PCI device found will be used.
5259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
5359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezFor commands, the scanned channels must be consecutive
5459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
5559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezrange and aref.
5659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/
5759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
5859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
5959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezTODO:
6059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezanalog triggering on 1602 series
6259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/
6359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "../comedidev.h"
6559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include <linux/delay.h>
6670265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
6759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8253.h"
6959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8255.h"
7059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "amcc_s5933.h"
7159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_pci.h"
7259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_fc.h"
7359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
74cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#undef CB_PCIDAS_DEBUG		/*  disable debugging code */
75cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* #define CB_PCIDAS_DEBUG         enable debugging code */
7659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
77cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* PCI vendor number of ComputerBoards/MeasurementComputing */
7859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PCI_VENDOR_ID_CB	0x1307
79cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TIMER_BASE 100		/*  10MHz master clock */
80cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AI_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
81cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AO_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
8259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8800 8
8359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_7376 1
8459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8402 2
8559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_DAC08 1
8659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
8759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* PCI-DAS base addresses */
8859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
89cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* indices of base address regions */
9059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define S5933_BADRINDEX 0
9159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_BADRINDEX 1
9259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_BADRINDEX 2
9359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_BADRINDEX 3
9459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_BADRINDEX 4
95cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* sizes of io regions */
9659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_SIZE 10
9759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_SIZE 4
9859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_SIZE 12
9959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_SIZE 4
10059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* Control/Status registers */
102cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define INT_ADCFIFO	0	/*  INTERRUPT / ADC FIFO register */
103cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_EOS 0x1		/*  interrupt end of scan */
104cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FHF 0x2		/*  interrupt fifo half full */
105cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FNE 0x3		/*  interrupt fifo not empty */
106cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_MASK 0x3		/*  mask of interrupt select bits */
107cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INTE 0x4		/*  interrupt enable */
108cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFIE 0x8		/*  dac half full interrupt enable */
109cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAIE	0x10		/*  end of aquisition interrupt enable */
110cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFI	0x20		/*  dac half full read status / write interrupt clear */
111cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAI 0x40		/*  read end of acq. interrupt status / write clear */
112cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT 0x80		/*  read interrupt status / write clear */
113cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOBI 0x200		/*  read end of burst interrupt status */
114cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADHFI 0x400		/*  read half-full interrupt status */
115cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNEI 0x800		/*  read fifo not empty interrupt latch status */
116cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNE 0x1000		/*  read, fifo not empty (realtime, not latched) status */
117cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMIE	0x1000	/*  write, dac empty interrupt enable */
118cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   LADFUL 0x2000		/*  read fifo overflow / write clear */
119cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMI 0x4000		/*  dac fifo empty interrupt status / write clear */
120cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
121cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCMUX_CONT	2	/*  ADC CHANNEL MUX AND CONTROL register */
12259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   BEGIN_SCAN(x)	((x) & 0xf)
12359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   END_SCAN(x)	(((x) & 0xf) << 4)
12459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   GAIN_BITS(x)	(((x) & 0x3) << 8)
125cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   UNIP	0x800		/*  Analog front-end unipolar for range */
126cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SE	0x400		/*  Inputs in single-ended mode */
127cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_MASK	0x3000	/*  pacer source bits */
128cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_INT 0x1000	/*  internal pacer */
129cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_FALL	0x2000	/*  external falling edge */
130cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_RISE	0x3000	/*  external rising edge */
131cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOC	0x4000		/*  adc not busy */
132cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
133cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TRIG_CONTSTAT 4		/*  TRIGGER CONTROL/STATUS register */
134cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SW_TRIGGER 0x1	/*  software start trigger */
135cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EXT_TRIGGER 0x2	/*  external start trigger */
136cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ANALOG_TRIGGER 0x3	/*  external analog trigger */
137cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TRIGGER_MASK	0x3	/*  mask of bits that determine start trigger */
138cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TGEN	0x10		/*  enable external start trigger */
139cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   BURSTE 0x20		/*  burst mode enable */
140cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   XTRCL	0x80		/*  clear external trigger */
141cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
142cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define CALIBRATION_REG	6	/*  CALIBRATION register */
143cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_8800_BIT	0x100	/*  select 8800 caldac */
144cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_TRIMPOT_BIT	0x200	/*  select ad7376 trim pot */
145cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_DAC08_BIT	0x400	/*  select dac08 caldac */
14659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)
147cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   CAL_EN_BIT	0x4000	/*  read calibration source instead of analog input channel 0 */
148cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SERIAL_DATA_IN_BIT	0x8000	/*  serial data stream going to 8800 and 7376 */
14959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
150cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DAC_CSR	0x8		/*  dac control and status register */
15159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits {
152cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DACEN = 0x2,		/*  dac enable */
153cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_MODE_UPDATE_BOTH = 0x80,	/*  update both dacs when dac0 is written */
15459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
15559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
15659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
15759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return (range & 0x3) << (8 + 2 * (channel & 0x1));
15859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
1590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
16059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE_MASK(unsigned int channel)
16159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
16259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0x3 << (8 + 2 * (channel & 0x1));
16359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
16459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
165cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bits for 1602 series only */
16659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits_1602 {
167cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_EMPTY = 0x1,	/*  dac fifo empty, read, write clear */
168cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_START = 0x4,	/*  start/arm dac fifo operations */
169cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_MASK = 0x18,	/*  bits that set dac pacer source */
170cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_INT = 0x8,	/*  dac internal pacing */
171cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_FALL = 0x10,	/*  dac external pacing, falling edge */
172cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_RISE = 0x18,	/*  dac external pacing, rising edge */
17359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_CHAN_EN(unsigned int channel)
17559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
176cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
17759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog input fifo */
180cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCDATA	0		/*  ADC DATA register */
181cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCFIFOCLR	2	/*  ADC FIFO CLEAR */
18259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
183cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pacer, counter, dio registers */
18459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC8254 0
18559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DIO_8255 4
18659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC8254 8
18759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
188cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output registers for 100x, 1200 series */
18959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_DATA_REG(unsigned int channel)
19059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
19159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2 * (channel & 0x1);
19259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
19359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
19459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog output registers for 1602 series*/
195cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACDATA	0		/*  DAC DATA register */
196cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACFIFOCLR	2	/*  DAC FIFO CLEAR */
19759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
198cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bit in hexadecimal representation of range index that indicates unipolar input range */
19959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define IS_UNIPOLAR 0x4
200cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog input ranges for most boards */
2019ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ranges = {
20259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
20359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
2070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
2080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(5),
2100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(2.5),
2110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(1.25)
2120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
21359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
21459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
215cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pci-das1001 input ranges */
2169ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_alt_ranges = {
21759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
21859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1),
2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.1),
2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.01),
2230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(1),
2250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(0.1),
2260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(0.01)
2270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
22859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
22959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
230cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output ranges */
2319ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ao_ranges = {
23259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	4,
23359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(5),
2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
23959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
24059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
24159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum trimpot_model {
24259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD7376,
24359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD8402,
24459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
24559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2465c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstruct cb_pcidas_board {
24759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const char *name;
24859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned short device_id;
249cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_se_chans;	/*  Inputs in single-ended mode */
250cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_diff_chans;	/*  Inputs in differential mode */
251cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_bits;		/*  analog input resolution */
252cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_speed;		/*  fastest conversion period in ns */
253cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_nchan;		/*  number of analog out channels */
254cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int has_ao_fifo;	/*  analog output has fifo */
255cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
256cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int fifo_size;		/*  number of samples fifo can hold */
2579ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
25859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	enum trimpot_model trimpot;
25959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned has_dac08:1;
2605c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton};
26159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2625c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstatic const struct cb_pcidas_board cb_pcidas_boards[] = {
26359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/16",
2650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1,
2660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
2670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
2680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 16,
2690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 5000,
2700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
2710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 1,
2720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_scan_speed = 10000,
2730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 512,
2740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
2750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD8402,
2760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 1,
2770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
27859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1200",
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0xF,
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
2850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
2860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
2880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
2890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
2900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
2910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
29259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/12",
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x10,
2950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
2970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 1,
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_scan_speed = 4000,
3020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
30759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1200/jr",
3090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x19,
3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
32159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/16/jr",
3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1C,
3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 16,
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 5000,
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 512,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD8402,
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 1,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
33559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1000",
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x4C,
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 4000,
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
34959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1001",
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1a,
3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6800,
3560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_alt_ranges,
3600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
3620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
36359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1002",
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1b,
3660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6800,
3700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
37759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
37859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
37959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	{
3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	0}
39059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
39159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
39359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
39559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Useful for shorthand access to the particular board structure
39659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
3975c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr)
39859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* this structure is for data unique to this hardware driver.  If
40059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez   several hardware drivers keep similar information in this structure,
40171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
402c77e25898523395b56e1d120195e1ad2e3efa14dBill Pembertonstruct cb_pcidas_private {
40359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* would be useful for a PCI device */
40459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pci_dev;
405cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  base addresses */
40659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long s5933_config;
40759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long control_status;
40859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long adc_fifo;
40959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long pacer_counter_dio;
41059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long ao_registers;
411cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog input pacing */
41259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor1;
41359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor2;
414cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int count;	/*  number of analog input samples remaining */
415cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int adc_fifo_bits;	/*  bits to write to interupt/adcfifo register */
416cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int s5933_intcsr_bits;	/*  bits to write to amcc s5933 interrupt control/status register */
417cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_control_bits;	/*  bits to write to ao control and status register */
418790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_buffer[AI_BUFFER_SIZE];
419790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ao_buffer[AO_BUFFER_SIZE];
420cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog output pacing */
42159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor1;
42259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor2;
423cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_count;	/*  number of analog output samples remaining */
424cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
425cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int caldac_value[NUM_CHANNELS_8800];	/*  for readback of caldac */
426cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int trimpot_value[NUM_CHANNELS_8402];	/*  for readback of trimpot */
42759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int dac08_value;
42859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int calibration_source;
429c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton};
43059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
43259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * most drivers define the following macro to make it easy to
43359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * access the private structure.
43459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
435c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton#define devpriv ((struct cb_pcidas_private *)dev->private)
43659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
438139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
43959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * which functions to call to configure/deconfigure (attach/detach)
44059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the board, and also about the kernel module that contains
44159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the device code.
44259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_attach(struct comedi_device *dev,
4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it);
445da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_detach(struct comedi_device *dev);
446139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_cb_pcidas = {
44768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_pcidas",
44868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
44968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = cb_pcidas_attach,
45068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = cb_pcidas_detach,
45159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
45259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev,
4540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
4550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data);
456814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
4570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_insn *insn, unsigned int *data);
4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
4600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
4610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data);
4620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
4630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
4640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
4650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
4660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
4670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_insn *insn,
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int *data);
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmd(struct comedi_device *dev,
4710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
4720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
4730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
4740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd);
4750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmd(struct comedi_device *dev,
4760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
477d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
478d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *subdev,
479d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num);
4800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd);
48370265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d);
484814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void handle_ao_interrupt(struct comedi_device *dev, unsigned int status);
4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_cancel(struct comedi_device *dev,
4860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
4870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s);
489814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    int round_flags);
4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int eeprom_read_insn(struct comedi_device *dev,
4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
4940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_read_insn(struct comedi_device *dev,
4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
4960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_write_insn(struct comedi_device *dev,
4980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
4990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data);
5000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_read_insn(struct comedi_device *dev,
5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
5020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data);
5030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_trimpot_write(struct comedi_device *dev,
5040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int channel, unsigned int value);
5050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_write_insn(struct comedi_device *dev,
5060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
5070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data);
5080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_read_insn(struct comedi_device *dev,
5090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
5100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
511814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int dac08_write(struct comedi_device *dev, unsigned int value);
5120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_write_insn(struct comedi_device *dev,
5130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
515814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int caldac_8800_write(struct comedi_device *dev, unsigned int address,
5160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     uint8_t value);
517814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int trimpot_7376_write(struct comedi_device *dev, uint8_t value);
518814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
5190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      uint8_t value);
520814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int nvram_read(struct comedi_device *dev, unsigned int address,
5212d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		      uint8_t *data);
52259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
523814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic inline unsigned int cal_enable_bits(struct comedi_device *dev)
52459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
52559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
52659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
52759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
52859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
52959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Attach is called by the Comedi core to configure the driver
53059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * for a particular board.
53159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
5320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_attach(struct comedi_device *dev,
5330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it)
53459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
53534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
53620fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pcidev = NULL;
53759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int index;
53859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i;
53959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
54059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: ", dev->minor);
54159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
54259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
54359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the private structure area.
54459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
545c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
54659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
54759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
54859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
54959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Probe the device to determine what device in the series it is.
55059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
55159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("\n");
55259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
55320fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pcidev) {
554cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  is it not a computer boards card? */
55559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (pcidev->vendor != PCI_VENDOR_ID_CB)
55659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			continue;
557cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  loop through cards supported by this driver */
5588629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton		for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) {
55959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cb_pcidas_boards[index].device_id != pcidev->device)
56059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				continue;
561cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  was a particular bus/slot requested? */
56259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (it->options[0] || it->options[1]) {
563cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton				/*  are we on the wrong bus/slot? */
56459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				if (pcidev->bus->number != it->options[0] ||
5650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    PCI_SLOT(pcidev->devfn) != it->options[1]) {
56659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					continue;
56759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				}
56859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
56959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->pci_dev = pcidev;
57059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->board_ptr = cb_pcidas_boards + index;
57159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			goto found;
57259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
57359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
57459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
57559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("No supported ComputerBoards/MeasurementComputing card found on "
5760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       "requested position\n");
57759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EIO;
57859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
5790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
58059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
58159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
5820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pcidev->bus->number, PCI_SLOT(pcidev->devfn));
58359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
58459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
58559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Enable PCI device and reserve I/O ports.
58659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
58759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_pci_enable(pcidev, "cb_pcidas")) {
58859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" Failed to enable PCI device and request regions\n");
58959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EIO;
59059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
59159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
59259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Initialize devpriv->control_status and devpriv->adc_fifo to point to
59359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * their base address.
59459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
59559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_config =
5960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
59759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->control_status =
5980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
59959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo =
6000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
60159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->pacer_counter_dio =
6020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
60359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
60459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_registers =
6050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
60659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
607cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable and clear interrupts on amcc s5933 */
60859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(INTCSR_INBOX_INTR_STATUS,
6090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
61059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
611cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  get irq */
6125f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
61359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			IRQF_SHARED, "cb_pcidas", dev)) {
61459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
61559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
61659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
61759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->irq = devpriv->pci_dev->irq;
61859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
619cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* Initialize dev->board_name */
62059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->board_name = thisboard->name;
62159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
62259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
62359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the subdevice structures.
62459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
62559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (alloc_subdevices(dev, 7) < 0)
62659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
62759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
62859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 0;
62959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog input subdevice */
63059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->read_subdev = s;
63159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_AI;
63259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
63359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* WARNING: Number of inputs in differential mode is ignored */
63459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = thisboard->ai_se_chans;
63559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->len_chanlist = thisboard->ai_se_chans;
63659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = (1 << thisboard->ai_bits) - 1;
63759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->range_table = thisboard->ranges;
63859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = cb_pcidas_ai_rinsn;
63959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_config = ai_config_insn;
64059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmd = cb_pcidas_ai_cmd;
64159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmdtest = cb_pcidas_ai_cmdtest;
64259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->cancel = cb_pcidas_cancel;
64359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
64459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog output subdevice */
64559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 1;
64659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
64759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_AO;
64859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
64959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = thisboard->ao_nchan;
650cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  analog out resolution is the same as analog input resolution, so use ai_bits */
65159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = (1 << thisboard->ai_bits) - 1;
65259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->range_table = &cb_pcidas_ao_ranges;
65359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = cb_pcidas_ao_readback_insn;
65459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (thisboard->has_ao_fifo) {
65559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->write_subdev = s;
65659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->subdev_flags |= SDF_CMD_WRITE;
65759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_fifo_winsn;
65859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmdtest = cb_pcidas_ao_cmdtest;
65959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmd = cb_pcidas_ao_cmd;
66059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->cancel = cb_pcidas_ao_cancel;
66159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		} else {
66259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_nofifo_winsn;
66359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
66459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
66559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
66659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
66759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
66859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* 8255 */
66959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 2;
67059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
67159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
672cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  serial EEPROM, */
67359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 3;
67459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_MEMORY;
67559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
67659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = 256;
67759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
67859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = eeprom_read_insn;
67959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
680cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  8800 caldac */
68159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 4;
68259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
68359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
68459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = NUM_CHANNELS_8800;
68559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
68659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = caldac_read_insn;
68759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = caldac_write_insn;
68859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
68959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		caldac_8800_write(dev, i, s->maxdata / 2);
69059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
691cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  trim potentiometer */
69259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 5;
69359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
69459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
69559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->trimpot == AD7376) {
69659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_7376;
69759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0x7f;
69859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
69959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_8402;
70059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
70159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
70259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = trimpot_read_insn;
70359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = trimpot_write_insn;
70459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
70559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
70659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
707cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  dac08 caldac */
70859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 6;
70959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->has_dac08) {
71059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_CALIB;
71159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
71259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_DAC08;
71359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = dac08_read_insn;
71459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_write = dac08_write_insn;
71559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
71659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		dac08_write(dev, s->maxdata / 2);
71759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else
71859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
71959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
720cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
72159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
72259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
72359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_intcsr_bits =
7240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
7250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    INTCSR_INBOX_FULL_INT;
726cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear and enable interrupt on amcc s5933 */
72759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
7280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
72959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
73059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
73159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
73259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
73359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
73459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cb_pcidas_detach is called to deconfigure a device.  It should deallocate
73559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * resources.
73659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * This function is also called when _attach() fails, so it should be
73759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * careful not to release resources that were not necessarily
73859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * allocated by _attach().  dev->private and dev->subdevices are
73959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * deallocated automatically by the core.
74059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
741da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_detach(struct comedi_device *dev)
74259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
74359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
74459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
74559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv) {
74659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
747cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  disable and clear interrupts on amcc s5933 */
74859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			outl(INTCSR_INBOX_INTR_STATUS,
7490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
75059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
7515f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			printk("detaching, incsr is 0x%x\n",
7520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
75359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
75459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
75559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
75659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->irq)
7575f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
75859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->subdevices)
75959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
76059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv && devpriv->pci_dev) {
7612d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		if (devpriv->s5933_config)
76259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_pci_disable(devpriv->pci_dev);
76359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_dev_put(devpriv->pci_dev);
76459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
76559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
76659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
76759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
76859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
76959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
77059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * "instructions" read/write data in "one-shot" or "software-triggered"
77159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * mode.
77259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
7730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev,
7740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
7750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data)
77659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
77759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int n, i;
77859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
77959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
78059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
781cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable calibration input if appropriate */
78259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (insn->chanspec & CR_ALT_SOURCE) {
78359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(cal_enable_bits(dev),
7840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + CALIBRATION_REG);
78559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = 0;
78659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
78759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->control_status + CALIBRATION_REG);
78859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = CR_CHAN(insn->chanspec);
78959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
790cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits and gain */
79159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(channel) |
7920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
793cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
79459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
79559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
796cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
79759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(insn->chanspec) != AREF_DIFF)
79859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
79959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
80059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* clear fifo */
80259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
80359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* convert n samples */
80559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (n = 0; n < insn->n; n++) {
80659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* trigger conversion */
80759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->adc_fifo + ADCDATA);
80859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* wait for conversion to end */
81059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* return -ETIMEDOUT if there is a timeout */
81159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
81259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
81359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
81459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
81559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (i == timeout)
81659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return -ETIMEDOUT;
81759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
81859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* read data */
81959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		data[n] = inw(devpriv->adc_fifo + ADCDATA);
82059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
82159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* return the number of samples read/written */
82359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return n;
82459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
82559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
8260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ai_config_calibration_source(struct comedi_device *dev,
8270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int *data)
82859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
82959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_calibration_sources = 8;
830790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int source = data[1];
83159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (source >= num_calibration_sources) {
83359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk("invalid calibration source: %i\n", source);
83459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
83559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
83659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->calibration_source = source;
83859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2;
84059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
84159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
842da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
8430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_insn *insn, unsigned int *data)
84459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
84559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int id = data[0];
84659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
84759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (id) {
84859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case INSN_CONFIG_ALT_SOURCE:
84959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return ai_config_calibration_source(dev, data);
85059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
85159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
85259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
85359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
85459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
85559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EINVAL;
85659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
85759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
858cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1000 and 1200 series */
8590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
8600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
8610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
8620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data)
86359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
86459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
86559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
86659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
867cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
86859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
8695f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
87059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
87259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
8730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
87459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
8755f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
87659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
877cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
87859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
879cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
88059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
88159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
88259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
88359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
88459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
885cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1602 series */
8860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
8870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
8880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
88959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
89059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
89159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
89259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
893cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear dac fifo */
89459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
89559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
896cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
89759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
8985f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
89959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
9000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
9010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_PACER_MASK;
90259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
9030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DACEN | DAC_RANGE(channel,
9040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      CR_RANGE(insn->
9050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       chanspec)) | DAC_CHAN_EN(channel) |
9060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DAC_START;
90759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
9085f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
90959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
910cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
91159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
912cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
91359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DACDATA);
91459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
91659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
91759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
918cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output readback insn */
919cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* XXX loses track of analog output value back after an analog ouput command is executed */
9200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
9210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
9220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_insn *insn,
9230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int *data)
92459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
92559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
92659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
92759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
92859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
92959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int eeprom_read_insn(struct comedi_device *dev,
9310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
93359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
93459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t nvram_data;
93559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int retval;
93659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
93759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
93859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (retval < 0)
93959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return retval;
94059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = nvram_data;
94259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
94459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
94559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_write_insn(struct comedi_device *dev,
9470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
9480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data)
94959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
95059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const unsigned int channel = CR_CHAN(insn->chanspec);
95159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
95259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return caldac_8800_write(dev, channel, data[0]);
95359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
95459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_read_insn(struct comedi_device *dev,
9560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
9570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
95859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
95959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
96059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
96259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
96359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 1602/16 pregain offset */
965da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dac08_write(struct comedi_device *dev, unsigned int value)
96659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
96759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->dac08_value == value)
96859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
96959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->dac08_value = value;
97159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
9730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
9745f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
97559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
9760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
9775f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
97859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
9790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
9805f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
98159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
98259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
98359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
98459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_write_insn(struct comedi_device *dev,
9860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
9870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
98859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
98959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return dac08_write(dev, data[0]);
99059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
99159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_read_insn(struct comedi_device *dev,
9930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
9940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
99559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
99659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->dac08_value;
99759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
99959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
100059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1001da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device *dev,
10020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int channel, unsigned int value)
100359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
100459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->trimpot_value[channel] == value)
100559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
100659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->trimpot_value[channel] = value;
100859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (thisboard->trimpot) {
100959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD7376:
101059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_7376_write(dev, value);
101159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
101259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD8402:
101359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_8402_write(dev, channel, value);
101459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
101559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
101659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "driver bug?");
101759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
101859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
101959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
102059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
102259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
102359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_write_insn(struct comedi_device *dev,
10250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
10260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data)
102759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
102859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
102959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return cb_pcidas_trimpot_write(dev, channel, data[0]);
103159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
103259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_read_insn(struct comedi_device *dev,
10340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
10350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data)
103659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
103759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
103859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->trimpot_value[channel];
104059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
104259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
104359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
10450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
10460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
104759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
104859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
104959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
105059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i, gain, start_chan;
105159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
105359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
105459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
105559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
105659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
105759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
105859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
106059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
106159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
106259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_NOW | TRIG_EXT;
106359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
106459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
106659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
106759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
106859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
106959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
107159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
107259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
107359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
107459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
107659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
107759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
107859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
107959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
108059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
108259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
108359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
108459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
108559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
108759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
108859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
109059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
109159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
109259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
109359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW &&
10940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_TIMER &&
10950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
109659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
109759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src != TRIG_TIMER &&
10980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
109959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
110159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1103cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure trigger sources are compatible with each other */
110459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
110559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
110759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_EXT &&
11090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
111059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
111159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
111359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
111459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
111659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
111859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
111959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
112059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
112159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
112259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
112359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg <
11240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    thisboard->ai_speed * cmd->chanlist_len) {
112559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg =
11260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    thisboard->ai_speed * cmd->chanlist_len;
112759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
112859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
112959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
113059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
113159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_arg < thisboard->ai_speed) {
113259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->convert_arg = thisboard->ai_speed;
113359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
113459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
113559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
113659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
113759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
113859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
113959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
114059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
114159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
114259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
114359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
114459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
114559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
114659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
114759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
114859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
114959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
115059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
115159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
115259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
115359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
115459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
115559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
115659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
11570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor1),
11580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
11590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
11600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
116159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
116259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
116359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
116459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
116559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->convert_arg;
116659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
11670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor1),
11680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
11690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
11700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
117159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->convert_arg)
117259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
117359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
117459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
117559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
117659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
117759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1178cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
117959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist) {
118059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		gain = CR_RANGE(cmd->chanlist[0]);
118159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		start_chan = CR_CHAN(cmd->chanlist[0]);
118259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 1; i < cmd->chanlist_len; i++) {
118359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_CHAN(cmd->chanlist[i]) !=
11840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (start_chan + i) % s->n_chan) {
118559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
11860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must be consecutive channels, counting upwards\n");
118759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
118859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
118959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_RANGE(cmd->chanlist[i]) != gain) {
119059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
11910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must all have the same gain\n");
119259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
119359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
119459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
119559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
119659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
119759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
119859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
119959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
120059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
120159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
120259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
12030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmd(struct comedi_device *dev,
12040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
120559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1206d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1207ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
120859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
120959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
121059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1211cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure CAL_EN_BIT is disabled */
121259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + CALIBRATION_REG);
1213cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  initialize before settings pacer source and count values */
121459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1215cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
121659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
121759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1218cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits, gain and pacer source */
121959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
12200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
12210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1222cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
122359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
122459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
1225cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
122659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
122759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
1228cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
122959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
123059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_EXT_RISE;
123159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else
123259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_INT;
123359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
123459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
123559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
12365f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: sent 0x%x to adcmux control\n", bits);
123759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
123859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1239cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
124059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER)
124159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->convert_arg,
12420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					cmd->flags & TRIG_ROUND_MASK);
124359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->scan_begin_src == TRIG_TIMER)
124459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
12450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					cmd->flags & TRIG_ROUND_MASK);
124659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1247cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
12482d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
124959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
1250cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable interrupts */
12515f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
125259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= INTE;
125359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INT_MASK;
125459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->flags & TRIG_WAKE_EOS) {
125559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1256cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_EOS;	/*  interrupt end of burst */
125759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
1258cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_FNE;	/*  interrupt fifo not empty */
125959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
1260cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		devpriv->adc_fifo_bits |= INT_FHF;	/* interrupt fifo half full */
126159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
126259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
12635f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
126459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1265cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable (and clear) interrupts */
126659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
12670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + INT_ADCFIFO);
12685f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
126959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1270cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set start trigger and burst mode */
127159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = 0;
127259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_NOW)
127359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SW_TRIGGER;
127459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->start_src == TRIG_EXT)
127559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= EXT_TRIGGER | TGEN | XTRCL;
127659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else {
127759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "bug!");
127859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
127959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
128059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
128159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= BURSTE;
128259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + TRIG_CONTSTAT);
128359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
12845f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: sent 0x%x to trig control\n", bits);
128559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
128659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
128859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
128959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
12900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
12910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
12920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
129359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
129459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
129559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
129659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
129859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
129959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
130059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
130159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
130259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
130359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
130559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
130759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_INT;
130859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
130959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
131059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
131159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
131259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
131359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
131459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
131559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
131659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
131759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_NOW;
131859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
131959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
132059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
132159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
132259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
132359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
132459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
132559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
132659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
132759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
132859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
132959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
133059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
133259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
133359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
133559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_TIMER &&
13370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
133859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
133959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
134059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
134159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
134359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
134459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
134659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
134859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
134959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
135059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
135159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
135259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
135359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
135459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg = thisboard->ao_scan_speed;
135559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
135659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
135759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
135859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
135959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
136059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
136159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
136259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
136359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
136459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
136559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
136659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
136759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
136859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
136959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
137059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
137159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
137259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
137359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
137459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
137559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
137659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
137759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
137859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
13790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor1),
13800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor2),
13810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
13820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
138359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
138459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
138559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
138659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
138759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
138859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
138959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1390cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
139159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist && cmd->chanlist_len > 1) {
139259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
13930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    CR_CHAN(cmd->chanlist[1]) != 1) {
139459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_error(dev,
13950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     "channels must be ordered channel 0, channel 1 in chanlist\n");
139659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
139759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
139859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
139959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
140059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
140159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
140259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
140359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
140459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
140559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
14060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmd(struct comedi_device *dev,
14070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
140859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1409d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1410ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
141159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
141259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
141359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1414cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel limits, gain */
14155f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
141659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < cmd->chanlist_len; i++) {
1417cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  enable channel */
141859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |=
14190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1420cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  set range */
142159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
14220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						      CR_RANGE(cmd->
14230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       chanlist[i]));
142459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
142559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1426cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable analog out before settings pacer source and count values */
142759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
14285f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
142959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1430cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
143159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
143259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1433cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
143459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
143559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
14360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor1),
14370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor2),
14380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
14390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags);
144059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
144159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
144259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
14430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   devpriv->ao_divisor1, 2);
144459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
14450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   devpriv->ao_divisor2, 2);
144659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1447cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
14482d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
144959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
1450cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
14515f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
145259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (cmd->scan_begin_src) {
145359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_TIMER:
145459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_INT;
145559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
145659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_EXT:
145759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
145859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
145959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
14605f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
146159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "error setting dac pacer source");
146259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
146359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
146459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
14655f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
146659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
146759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = cb_pcidas_ao_inttrig;
146859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
146959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
147059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
147159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1472d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1473d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *s,
1474d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num)
147559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
147659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_bytes, num_points = thisboard->fifo_size;
1477d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1478ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
147959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
148059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
148159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (trig_num != 0)
148259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
148359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1484cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load up fifo */
148559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
148659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = devpriv->ao_count;
148759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
148859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
14890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       num_points * sizeof(short));
1490790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_points = num_bytes / sizeof(short);
149159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
14922d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
149359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count -= num_points;
1494cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  write data to board's fifo */
149559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
149659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1497cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable dac half-full and empty interrupts */
14985f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
149959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
150059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
150259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1503cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable and clear interrupts */
150459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
15050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + INT_ADCFIFO);
150659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1507cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  start dac */
150859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
150959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
151059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk("comedi: sent 0x%x to dac control\n", devpriv->ao_control_bits);
151259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
15135f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
151459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
151559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = NULL;
151659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
151759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
151859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
151959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
152070265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d)
152159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
15220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct comedi_device *dev = (struct comedi_device *)d;
152334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->read_subdev;
1524d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
152559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int status, s5933_status;
152659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int half_fifo = thisboard->fifo_size / 2;
152759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_samples, i;
152859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
152959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
153059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
15312d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (dev->attached == 0)
153259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
153359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
153459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async = s->async;
153559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
153659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
153759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
153859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15395f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("intcsr 0x%x\n", s5933_status);
15405f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
154159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
154259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
154359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
154459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
154559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1546cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
154759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1548cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear interrupt on amcc s5933 */
154959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
15500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
155159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
155259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	status = inw(devpriv->control_status + INT_ADCFIFO);
155359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15542d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
155559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "spurious interrupt");
155659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
155759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1558cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog output interrupt */
15592d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (status & (DAHFI | DAEMI))
156059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		handle_ao_interrupt(dev, status);
1561cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog input interrupts */
1562cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  if fifo half-full */
156359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & ADHFI) {
1564cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  read data */
156559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_samples = half_fifo;
156659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT &&
15670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    num_samples > devpriv->count) {
156859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples = devpriv->count;
156959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
157059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
15710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     num_samples);
157259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
15730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  num_samples * sizeof(short));
157459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count -= num_samples;
157559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
157659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
157759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cb_pcidas_cancel(dev, s);
157859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1579cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
15805f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
158159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
15820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
15835f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
1584cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  else if fifo not empty */
158559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & (ADNEI | EOBI)) {
158659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
1587cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  break if fifo is empty */
158859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if ((ADNE & inw(devpriv->control_status +
15890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					INT_ADCFIFO)) == 0)
159059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
159159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
159259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) {	/* end of acquisition */
159359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_cancel(dev, s);
159459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_EOA;
159559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
159659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
159759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1598cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear not-empty interrupt latch */
15995f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
160059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
16010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16025f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
160359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & EOAI) {
160459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev,
16050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "bug! encountered end of aquisition interrupt?");
1606cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear EOA interrupt latch */
16075f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
160859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | EOAI,
16090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16105f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
161159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1612cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* check for fifo overflow */
161359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & LADFUL) {
161459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "fifo overflow");
1615cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear overflow interrupt latch */
16165f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
161759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | LADFUL,
16180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16195f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
162059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_cancel(dev, s);
162159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
162259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
162359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
162459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
162559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
162659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return IRQ_HANDLED;
162759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
162859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1629da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
163059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
163134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->write_subdev;
1632d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1633ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
163459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int half_fifo = thisboard->fifo_size / 2;
163559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_points;
16363a5e32ddcb04d7a2bed86323ca22da51d3a810bdGerard Lledo	unsigned long flags;
163759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
163859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
163959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
164059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & DAEMI) {
1641cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear dac empty interrupt latch */
16425f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
164359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAEMI,
16440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16455f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
164659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
164759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cmd->stop_src == TRIG_NONE ||
16480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (cmd->stop_src == TRIG_COUNT
16490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     && devpriv->ao_count)) {
165059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev, "dac fifo underflow");
165159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_ao_cancel(dev, s);
165259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_ERROR;
165359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
165459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
165559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
165659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & DAHFI) {
165759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		unsigned int num_bytes;
165859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1659cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  figure out how many points we are writing to fifo */
166059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = half_fifo;
166159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_src == TRIG_COUNT &&
16620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    devpriv->ao_count < num_points)
166359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points = devpriv->ao_count;
166459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_bytes =
16650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cfc_read_array_from_buffer(s, devpriv->ao_buffer,
16660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       num_points * sizeof(short));
1667790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points = num_bytes / sizeof(short);
166859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
16692d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		if (async->cmd.stop_src == TRIG_COUNT)
167059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count -= num_points;
1671cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  write data to board's fifo */
167259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
16730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      num_points);
1674cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
16755f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
167659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAHFI,
16770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16785f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
167959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
168059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
168159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
168259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
168359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1684d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog input command */
16850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_cancel(struct comedi_device *dev,
16860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
168759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
168859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
168959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
16905f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
1691cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
169259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
169359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
16945f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
169559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1696cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable start trigger source and burst mode */
169759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1698cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  software pacer source */
169959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + ADCMUX_CONT);
170059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
170159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
170259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
170359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1704d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog output command */
1705d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
1706d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton			       struct comedi_subdevice *s)
170759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
170859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
170959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17105f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
1711cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
171259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
171359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
171459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1715cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable output */
171659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
171759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
17185f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
171959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
172059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
172159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
172259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1723da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
17240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    int rounding_flags)
172559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
172659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
17270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       &(devpriv->divisor2), ns,
17280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       rounding_flags & TRIG_ROUND_MASK);
172959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
173159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
17320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   devpriv->divisor1, 2);
173359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
17340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   devpriv->divisor2, 2);
173559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
173659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1737da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void write_calibration_bitstream(struct comedi_device *dev,
17380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int register_bits,
17390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int bitstream,
17400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int bitstream_length)
174159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
174259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int write_delay = 1;
174359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bit;
174459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
174559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
174659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (bitstream & bit)
174759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits |= SERIAL_DATA_IN_BIT;
174859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
174959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits &= ~SERIAL_DATA_IN_BIT;
17505f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(write_delay);
175159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(register_bits, devpriv->control_status + CALIBRATION_REG);
175259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
175359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
175459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1755da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int caldac_8800_write(struct comedi_device *dev, unsigned int address,
17560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     uint8_t value)
175759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
175859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_caldac_channels = 8;
175959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 11;
176059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((address & 0x7) << 8) | value;
17615f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int caldac_8800_udelay = 1;
176259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (address >= num_caldac_channels) {
176459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "illegal caldac channel");
176559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
176659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
176759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (value == devpriv->caldac_value[address])
176959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
177059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
177159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->caldac_value[address] = value;
177259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
177359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
17740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
177559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17765f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(caldac_8800_udelay);
177759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_8800_BIT,
17780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
17795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(caldac_8800_udelay);
178059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
178159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
178359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
178459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1785da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
178659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
178759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 7;
178859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = value & 0x7f;
178959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
17905f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int ad7376_udelay = 1;
179159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
17935f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad7376_udelay);
179459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
179559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
17970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
179859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17995f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad7376_udelay);
180059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
180159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
180259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
180359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
180459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
180559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* For 1602/16 only
180659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 0 : adc gain
180759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 1 : adc postgain offset */
1808da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
18090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      uint8_t value)
181059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
181159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 10;
181259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
181359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
18145f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int ad8402_udelay = 1;
181559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
18175f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad8402_udelay);
181859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
181959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
18210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
182259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad8402_udelay);
182459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
182559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
182759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
182859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic int wait_for_nvram_ready(unsigned long s5933_base_addr)
183059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
183159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 1000;
183259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
183359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
183459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < timeout; i++) {
183559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if ((inb(s5933_base_addr +
18360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
18370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    == 0)
183859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return 0;
18395f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
184059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
184159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -1;
184259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
184359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nvram_read(struct comedi_device *dev, unsigned int address,
18452d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini			uint8_t *data)
184659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
184759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long iobase = devpriv->s5933_config;
184859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
184959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
185059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
185159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
185259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
18530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     iobase + AMCC_OP_REG_MCSR_NVCMD);
185459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
185559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
18560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     iobase + AMCC_OP_REG_MCSR_NVCMD);
185759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
185859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
185959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
186159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
186259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	*data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
186459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
186659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
186759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
186959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * A convenient macro that defines init_module() and cleanup_module(),
187059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * as necessary.
187159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
1872727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
1873727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas						const struct pci_device_id *ent)
1874727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1875727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
1876727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1877727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1878727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
1879727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1880727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
1881727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1882727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1883727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_cb_pcidas_pci_driver = {
1884727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = cb_pcidas_pci_table,
1885727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_cb_pcidas_pci_probe,
1886727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
1887727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
1888727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1889727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_cb_pcidas_init_module(void)
1890727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1891727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
1892727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1893727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_cb_pcidas);
1894727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
1895727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
1896727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1897727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
1898727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_cb_pcidas_pci_driver);
1899727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1900727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1901727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_cb_pcidas_cleanup_module(void)
1902727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1903727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_cb_pcidas_pci_driver);
1904727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_cb_pcidas);
1905727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1906727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1907727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_cb_pcidas_init_module);
1908727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_cb_pcidas_cleanup_module);
190990f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
191090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
191190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
191290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1913