cb_pcidas.c revision 68c3dbff9fc9f25872408d0e95980d41733d48d0
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}
15959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE_MASK(unsigned int channel)
16059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
16159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0x3 << (8 + 2 * (channel & 0x1));
16259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
16359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
164cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bits for 1602 series only */
16559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits_1602 {
166cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_EMPTY = 0x1,	/*  dac fifo empty, read, write clear */
167cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_START = 0x4,	/*  start/arm dac fifo operations */
168cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_MASK = 0x18,	/*  bits that set dac pacer source */
169cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_INT = 0x8,	/*  dac internal pacing */
170cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_FALL = 0x10,	/*  dac external pacing, falling edge */
171cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_RISE = 0x18,	/*  dac external pacing, rising edge */
17259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_CHAN_EN(unsigned int channel)
17459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
175cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
17659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog input fifo */
179cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCDATA	0		/*  ADC DATA register */
180cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCFIFOCLR	2	/*  ADC FIFO CLEAR */
18159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pacer, counter, dio registers */
18359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC8254 0
18459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DIO_8255 4
18559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC8254 8
18659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
187cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output registers for 100x, 1200 series */
18859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_DATA_REG(unsigned int channel)
18959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
19059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2 * (channel & 0x1);
19159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
19259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
19359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog output registers for 1602 series*/
194cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACDATA	0		/*  DAC DATA register */
195cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACFIFOCLR	2	/*  DAC FIFO CLEAR */
19659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
197cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bit in hexadecimal representation of range index that indicates unipolar input range */
19859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define IS_UNIPOLAR 0x4
199cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog input ranges for most boards */
2009ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ranges = {
20159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
20259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
20359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
20459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(5),
20559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(2.5),
20659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(1.25),
20759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
20859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(5),
20959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(2.5),
21059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(1.25)
21159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
21259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
21359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
214cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pci-das1001 input ranges */
2159ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_alt_ranges = {
21659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
21759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
21859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
21959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(1),
22059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(0.1),
22159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(0.01),
22259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
22359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(1),
22459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(0.1),
22559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(0.01)
22659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
22759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
22859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
229cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output ranges */
2309ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ao_ranges = {
23159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	4,
23259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
23359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(5),
23459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
23559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(5),
23659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
23759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
23859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
23959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
24059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum trimpot_model {
24159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD7376,
24259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD8402,
24359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
24459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2455c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstruct cb_pcidas_board {
24659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const char *name;
24759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned short device_id;
248cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_se_chans;	/*  Inputs in single-ended mode */
249cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_diff_chans;	/*  Inputs in differential mode */
250cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_bits;		/*  analog input resolution */
251cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_speed;		/*  fastest conversion period in ns */
252cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_nchan;		/*  number of analog out channels */
253cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int has_ao_fifo;	/*  analog output has fifo */
254cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
255cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int fifo_size;		/*  number of samples fifo can hold */
2569ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
25759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	enum trimpot_model trimpot;
25859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned has_dac08:1;
2595c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton};
26059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2615c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstatic const struct cb_pcidas_board cb_pcidas_boards[] = {
26259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
26368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1602/16",
26468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x1,
26568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
26668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
26768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 16,
26868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 5000,
26968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 2,
27068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 1,
27168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_scan_speed = 10000,
27268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 512,
27368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
27468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD8402,
27568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 1,
27659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
27759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
27868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1200",
27968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0xF,
28068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
28168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
28268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
28368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3200,
28468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 2,
28568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
28668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
28768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
28868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
28968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
29059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
29159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
29268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1602/12",
29368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x10,
29468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
29568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
29668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
29768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3200,
29868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 2,
29968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 1,
30068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_scan_speed = 4000,
30168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
30268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
30368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
30468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
30559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
30659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
30768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1200/jr",
30868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x19,
30968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
31068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
31168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
31268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3200,
31368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 0,
31468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
31568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
31668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
31768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
31868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
31959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
32059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
32168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1602/16/jr",
32268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x1C,
32368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
32468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
32568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 16,
32668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 5000,
32768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 0,
32868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
32968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 512,
33068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
33168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD8402,
33268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 1,
33359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
33459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
33568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1000",
33668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x4C,
33768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
33868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
33968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
34068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 4000,
34168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 0,
34268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
34368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
34468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
34568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
34668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
34759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
34859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
34968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1001",
35068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x1a,
35168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
35268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
35368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
35468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6800,
35568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 2,
35668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
35768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
35868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_alt_ranges,
35968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
36068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
36159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
36259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
36368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "pci-das1002",
36468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.device_id = 0x1b,
36568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_se_chans = 16,
36668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_diff_chans = 8,
36768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_bits = 12,
36868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6800,
36968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_nchan = 2,
37068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_ao_fifo = 0,
37168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.fifo_size = 1024,
37268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ranges = &cb_pcidas_ranges,
37368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.trimpot = AD7376,
37468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.has_dac08 = 0,
37559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
37659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
37759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
378cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* Number of boards in cb_pcidas_boards */
3795c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board))
38059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
38159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
38259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
39059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{0}
39159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
39259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
39459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
39659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Useful for shorthand access to the particular board structure
39759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
3985c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr)
39959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
40059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* this structure is for data unique to this hardware driver.  If
40159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez   several hardware drivers keep similar information in this structure,
40271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
403c77e25898523395b56e1d120195e1ad2e3efa14dBill Pembertonstruct cb_pcidas_private {
40459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* would be useful for a PCI device */
40559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pci_dev;
406cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  base addresses */
40759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long s5933_config;
40859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long control_status;
40959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long adc_fifo;
41059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long pacer_counter_dio;
41159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long ao_registers;
412cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog input pacing */
41359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor1;
41459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor2;
415cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int count;	/*  number of analog input samples remaining */
416cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int adc_fifo_bits;	/*  bits to write to interupt/adcfifo register */
417cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int s5933_intcsr_bits;	/*  bits to write to amcc s5933 interrupt control/status register */
418cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_control_bits;	/*  bits to write to ao control and status register */
419790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_buffer[AI_BUFFER_SIZE];
420790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ao_buffer[AO_BUFFER_SIZE];
421cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog output pacing */
42259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor1;
42359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor2;
424cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_count;	/*  number of analog output samples remaining */
425cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
426cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int caldac_value[NUM_CHANNELS_8800];	/*  for readback of caldac */
427cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int trimpot_value[NUM_CHANNELS_8402];	/*  for readback of trimpot */
42859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int dac08_value;
42959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int calibration_source;
430c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton};
43159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
43359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * most drivers define the following macro to make it easy to
43459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * access the private structure.
43559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
436c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton#define devpriv ((struct cb_pcidas_private *)dev->private)
43759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
439139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
44059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * which functions to call to configure/deconfigure (attach/detach)
44159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the board, and also about the kernel module that contains
44259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the device code.
44359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
444da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_attach(struct comedi_device *dev, 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
453d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
45490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
45690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
45890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
46090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
46134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
46290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
46334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
46434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
465ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
46634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
467d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
468d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *subdev,
469d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num);
47034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
471ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
47270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d);
47371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
47434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
47534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
47671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
47759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int round_flags);
47834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
47990035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48590035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
487790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int value);
48834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48990035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
49034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
49190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
49271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dac08_write(struct comedi_device * dev, unsigned int value);
49334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
49490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
49571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int caldac_8800_write(struct comedi_device * dev, unsigned int address,
49659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value);
49771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_7376_write(struct comedi_device * dev, uint8_t value);
49871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
49959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value);
50071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int nvram_read(struct comedi_device * dev, unsigned int address,
50159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t * data);
50259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
50371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic inline unsigned int cal_enable_bits(struct comedi_device * dev)
50459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
50559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
50659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
50759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
50859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
50959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Attach is called by the Comedi core to configure the driver
51059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * for a particular board.
51159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
512da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_attach(struct comedi_device *dev, struct comedi_devconfig *it)
51359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
51434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
51559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pcidev;
51659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int index;
51759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i;
51859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
51959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: ", dev->minor);
52059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
52159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
52259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the private structure area.
52359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
524c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
52559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
52659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
52759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
52859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Probe the device to determine what device in the series it is.
52959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
53059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("\n");
53159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
53259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
53359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev != NULL;
53459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
535cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  is it not a computer boards card? */
53659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (pcidev->vendor != PCI_VENDOR_ID_CB)
53759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			continue;
538cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  loop through cards supported by this driver */
53959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (index = 0; index < N_BOARDS; index++) {
54059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cb_pcidas_boards[index].device_id != pcidev->device)
54159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				continue;
542cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  was a particular bus/slot requested? */
54359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (it->options[0] || it->options[1]) {
544cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton				/*  are we on the wrong bus/slot? */
54559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				if (pcidev->bus->number != it->options[0] ||
54659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					PCI_SLOT(pcidev->devfn) !=
54759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					it->options[1]) {
54859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					continue;
54959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				}
55059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
55159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->pci_dev = pcidev;
55259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->board_ptr = cb_pcidas_boards + index;
55359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			goto found;
55459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
55559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
55659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
55759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("No supported ComputerBoards/MeasurementComputing card found on "
55859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		"requested position\n");
55959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EIO;
56059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      found:
56259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
56459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev->bus->number, PCI_SLOT(pcidev->devfn));
56559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
56759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Enable PCI device and reserve I/O ports.
56859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
56959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_pci_enable(pcidev, "cb_pcidas")) {
57059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" Failed to enable PCI device and request regions\n");
57159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EIO;
57259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
57359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
57459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Initialize devpriv->control_status and devpriv->adc_fifo to point to
57559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * their base address.
57659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
57759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_config =
57859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
57959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->control_status =
58059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
58159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo =
58259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
58359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->pacer_counter_dio =
58459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
58559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
58659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_registers =
58759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
58859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
589cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable and clear interrupts on amcc s5933 */
59059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(INTCSR_INBOX_INTR_STATUS,
59159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
59259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
593cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  get irq */
59459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
59559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			IRQF_SHARED, "cb_pcidas", dev)) {
59659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
59759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
59859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
59959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->irq = devpriv->pci_dev->irq;
60059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
601cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* Initialize dev->board_name */
60259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->board_name = thisboard->name;
60359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
60459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
60559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the subdevice structures.
60659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
60759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (alloc_subdevices(dev, 7) < 0)
60859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
60959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
61059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 0;
61159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog input subdevice */
61259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->read_subdev = s;
61359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_AI;
61459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
61559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* WARNING: Number of inputs in differential mode is ignored */
61659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = thisboard->ai_se_chans;
61759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->len_chanlist = thisboard->ai_se_chans;
61859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = (1 << thisboard->ai_bits) - 1;
61959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->range_table = thisboard->ranges;
62059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = cb_pcidas_ai_rinsn;
62159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_config = ai_config_insn;
62259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmd = cb_pcidas_ai_cmd;
62359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmdtest = cb_pcidas_ai_cmdtest;
62459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->cancel = cb_pcidas_cancel;
62559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
62659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog output subdevice */
62759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 1;
62859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
62959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_AO;
63059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
63159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = thisboard->ao_nchan;
632cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  analog out resolution is the same as analog input resolution, so use ai_bits */
63359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = (1 << thisboard->ai_bits) - 1;
63459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->range_table = &cb_pcidas_ao_ranges;
63559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = cb_pcidas_ao_readback_insn;
63659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (thisboard->has_ao_fifo) {
63759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->write_subdev = s;
63859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->subdev_flags |= SDF_CMD_WRITE;
63959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_fifo_winsn;
64059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmdtest = cb_pcidas_ao_cmdtest;
64159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmd = cb_pcidas_ao_cmd;
64259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->cancel = cb_pcidas_ao_cancel;
64359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		} else {
64459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_nofifo_winsn;
64559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
64659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
64759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
64859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
64959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
65059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* 8255 */
65159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 2;
65259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
65359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
654cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  serial EEPROM, */
65559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 3;
65659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_MEMORY;
65759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
65859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = 256;
65959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
66059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = eeprom_read_insn;
66159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
662cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  8800 caldac */
66359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 4;
66459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
66559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
66659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = NUM_CHANNELS_8800;
66759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
66859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = caldac_read_insn;
66959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = caldac_write_insn;
67059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
67159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		caldac_8800_write(dev, i, s->maxdata / 2);
67259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
673cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  trim potentiometer */
67459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 5;
67559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
67659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
67759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->trimpot == AD7376) {
67859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_7376;
67959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0x7f;
68059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
68159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_8402;
68259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
68359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
68459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = trimpot_read_insn;
68559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = trimpot_write_insn;
68659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
68759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
68859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
689cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  dac08 caldac */
69059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 6;
69159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->has_dac08) {
69259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_CALIB;
69359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
69459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_DAC08;
69559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = dac08_read_insn;
69659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_write = dac08_write_insn;
69759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
69859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		dac08_write(dev, s->maxdata / 2);
69959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else
70059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
70159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
702cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
70359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
70459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
70559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_intcsr_bits =
70659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
70759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		INTCSR_INBOX_FULL_INT;
708cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear and enable interrupt on amcc s5933 */
70959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
71059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
71159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
71259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
71359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
71459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
71559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
71659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cb_pcidas_detach is called to deconfigure a device.  It should deallocate
71759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * resources.
71859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * This function is also called when _attach() fails, so it should be
71959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * careful not to release resources that were not necessarily
72059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * allocated by _attach().  dev->private and dev->subdevices are
72159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * deallocated automatically by the core.
72259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
723da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_detach(struct comedi_device *dev)
72459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
72559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
72659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
72759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv) {
72859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
729cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  disable and clear interrupts on amcc s5933 */
73059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			outl(INTCSR_INBOX_INTR_STATUS,
73159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				devpriv->s5933_config + AMCC_OP_REG_INTCSR);
73259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
73359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			rt_printk("detaching, incsr is 0x%x\n",
73459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				inl(devpriv->s5933_config +
73559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					AMCC_OP_REG_INTCSR));
73659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
73759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
73859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
73959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->irq)
74059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_free_irq(dev->irq, dev);
74159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->subdevices)
74259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
74359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv && devpriv->pci_dev) {
74459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
74559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_pci_disable(devpriv->pci_dev);
74659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
74759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_dev_put(devpriv->pci_dev);
74859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
74959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
75059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
75159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
75259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
75359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
75459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * "instructions" read/write data in "one-shot" or "software-triggered"
75559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * mode.
75659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
757da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
758da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
75959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
76059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int n, i;
76159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
76259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
76359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
764cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable calibration input if appropriate */
76559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (insn->chanspec & CR_ALT_SOURCE) {
76659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(cal_enable_bits(dev),
76759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + CALIBRATION_REG);
76859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = 0;
76959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
77059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->control_status + CALIBRATION_REG);
77159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = CR_CHAN(insn->chanspec);
77259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
773cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits and gain */
77459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(channel) |
77559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
776cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
77759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
77859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
779cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
78059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(insn->chanspec) != AREF_DIFF)
78159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
78259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
78359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
78459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* clear fifo */
78559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
78659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
78759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* convert n samples */
78859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (n = 0; n < insn->n; n++) {
78959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* trigger conversion */
79059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->adc_fifo + ADCDATA);
79159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
79259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* wait for conversion to end */
79359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* return -ETIMEDOUT if there is a timeout */
79459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
79559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
79659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
79759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
79859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (i == timeout)
79959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return -ETIMEDOUT;
80059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* read data */
80259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		data[n] = inw(devpriv->adc_fifo + ADCDATA);
80359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
80459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* return the number of samples read/written */
80659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return n;
80759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
80859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
809da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ai_config_calibration_source(struct comedi_device *dev, unsigned int *data)
81059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
81159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_calibration_sources = 8;
812790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int source = data[1];
81359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
81459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (source >= num_calibration_sources) {
81559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk("invalid calibration source: %i\n", source);
81659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
81759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
81859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
81959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->calibration_source = source;
82059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2;
82259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
82359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
824da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
825da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
82659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
82759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int id = data[0];
82859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (id) {
83059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case INSN_CONFIG_ALT_SOURCE:
83159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return ai_config_calibration_source(dev, data);
83259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
83359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
83459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
83559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
83659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
83759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EINVAL;
83859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
83959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
840cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1000 and 1200 series */
841da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
842da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
84359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
84459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
84559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
84659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
847cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
84859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
84959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
85059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
85159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
85259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
85359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
85459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
85559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
85659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
857cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
85859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
859cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
86059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
86159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
86359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
86459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
865cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1602 series */
866da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
867da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
86859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
86959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
87059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
87159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
872cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear dac fifo */
87359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
87459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
875cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
87659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
87759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
87859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
87959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
88059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_PACER_MASK;
88159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
88259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		DACEN | DAC_RANGE(channel,
88359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		CR_RANGE(insn->chanspec)) | DAC_CHAN_EN(channel) | DAC_START;
88459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
88559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
88659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
887cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
88859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
889cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
89059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DACDATA);
89159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
89259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
89359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
89459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
895cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output readback insn */
896cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* XXX loses track of analog output value back after an analog ouput command is executed */
897da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
898da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
89959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
90059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
90159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
90259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
90359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
90459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
905da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int eeprom_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
906da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
90759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
90859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t nvram_data;
90959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int retval;
91059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
91259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (retval < 0)
91359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return retval;
91459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = nvram_data;
91659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
91859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
91959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
920da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int caldac_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
921da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
92259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
92359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const unsigned int channel = CR_CHAN(insn->chanspec);
92459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
92559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return caldac_8800_write(dev, channel, data[0]);
92659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
92759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
928da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int caldac_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
929da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
93059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
93159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
93259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
93359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
93459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
93559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
93659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 1602/16 pregain offset */
937da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dac08_write(struct comedi_device *dev, unsigned int value)
93859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
93959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->dac08_value == value)
94059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
94159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->dac08_value = value;
94359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
94559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
94659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
94759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
94859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
94959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
95059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
95159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
95259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
95359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
95459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
95559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
95659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
957da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dac08_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
958da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
95959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
96059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return dac08_write(dev, data[0]);
96159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
96259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
963da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dac08_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
964da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
96559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
96659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->dac08_value;
96759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
96959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
97059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
971da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device *dev,
972790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int channel, unsigned int value)
97359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
97459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->trimpot_value[channel] == value)
97559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
97659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->trimpot_value[channel] = value;
97859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (thisboard->trimpot) {
97959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD7376:
98059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_7376_write(dev, value);
98159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD8402:
98359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_8402_write(dev, channel, value);
98459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
98659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "driver bug?");
98759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
98859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
99059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
99259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
99359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
994da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_write_insn(struct comedi_device *dev, struct comedi_subdevice *s,
995da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
99659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
99759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
99859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return cb_pcidas_trimpot_write(dev, channel, data[0]);
100059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
100159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1002da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_read_insn(struct comedi_device *dev, struct comedi_subdevice *s,
1003da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
100459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
100559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
100659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->trimpot_value[channel];
100859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
101059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
101159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1012da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1013da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_cmd *cmd)
101459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
101559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
101659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
101759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i, gain, start_chan;
101859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
101959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
102059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
102159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
102259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
102359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
102459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
102559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
102759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
102959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_NOW | TRIG_EXT;
103059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
103159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
103259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
103459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
103559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
103659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
103759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
103959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
104059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
104159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
104259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
104459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
104559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
104659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
104759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
104959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
105059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
105159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
105259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
105459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
105559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
105759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
105959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW &&
106159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_TIMER &&
106259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_EXT)
106359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src != TRIG_TIMER &&
106559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
106659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
106859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1070cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure trigger sources are compatible with each other */
107159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
107259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
107459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_EXT &&
107659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		(cmd->convert_src == TRIG_EXT
107759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			|| cmd->scan_begin_src == TRIG_EXT))
107859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
108159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
108259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
108459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
108659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
108759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
108859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
108959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
109059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
109159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg <
109259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			thisboard->ai_speed * cmd->chanlist_len) {
109359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg =
109459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				thisboard->ai_speed * cmd->chanlist_len;
109559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
109659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
109759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
109859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
109959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_arg < thisboard->ai_speed) {
110059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->convert_arg = thisboard->ai_speed;
110159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
110259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
110359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
110459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
110559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
110659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
110759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
110959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
111059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
111159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
111259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
111359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
111459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
111559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
111659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
111859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
111959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
112059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
112159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
112259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
112359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
112459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
112559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->divisor1), &(devpriv->divisor2),
112659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
112759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
112859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
112959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
113059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
113159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->convert_arg;
113259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
113359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->divisor1), &(devpriv->divisor2),
113459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
113559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->convert_arg)
113659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
113759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
113859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
113959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
114059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
114159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1142cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
114359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist) {
114459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		gain = CR_RANGE(cmd->chanlist[0]);
114559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		start_chan = CR_CHAN(cmd->chanlist[0]);
114659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 1; i < cmd->chanlist_len; i++) {
114759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_CHAN(cmd->chanlist[i]) !=
114859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				(start_chan + i) % s->n_chan) {
114959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
115059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					"entries in chanlist must be consecutive channels, counting upwards\n");
115159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
115259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
115359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_RANGE(cmd->chanlist[i]) != gain) {
115459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
115559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					"entries in chanlist must all have the same gain\n");
115659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
115759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
115859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
115959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
116059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
116259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
116359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
116559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
116659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1167da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
116859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1169d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1170ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
117159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
117259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
117359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1174cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure CAL_EN_BIT is disabled */
117559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + CALIBRATION_REG);
1176cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  initialize before settings pacer source and count values */
117759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1178cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
117959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
118059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1181cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits, gain and pacer source */
118259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
118359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
118459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1185cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
118659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
118759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
1188cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
118959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
119059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
1191cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
119259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
119359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_EXT_RISE;
119459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else
119559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_INT;
119659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
119759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
119859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
119959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to adcmux control\n", bits);
120059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
120159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1202cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
120359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER)
120459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->convert_arg,
120559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->flags & TRIG_ROUND_MASK);
120659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->scan_begin_src == TRIG_TIMER)
120759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
120859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->flags & TRIG_ROUND_MASK);
120959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1210cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
121159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
121259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
121359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1214cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable interrupts */
121559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
121659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= INTE;
121759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INT_MASK;
121859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->flags & TRIG_WAKE_EOS) {
121959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1220cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_EOS;	/*  interrupt end of burst */
122159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
1222cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_FNE;	/*  interrupt fifo not empty */
122359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
1224cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		devpriv->adc_fifo_bits |= INT_FHF;	/* interrupt fifo half full */
122559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
122659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
122759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
122859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1229cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable (and clear) interrupts */
123059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
123159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + INT_ADCFIFO);
123259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
123359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1234cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set start trigger and burst mode */
123559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = 0;
123659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_NOW)
123759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SW_TRIGGER;
123859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->start_src == TRIG_EXT)
123959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= EXT_TRIGGER | TGEN | XTRCL;
124059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else {
124159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "bug!");
124259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
124359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
124459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
124559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= BURSTE;
124659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + TRIG_CONTSTAT);
124759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
124859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to trig control\n", bits);
124959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
125059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
125159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
125259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
125359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1254da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1255da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_cmd *cmd)
125659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
125759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
125859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
125959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
126059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
126159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
126259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
126359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
126459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
126559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
126659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
126759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
126859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
126959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
127059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_INT;
127159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
127259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
127359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
127459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
127559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
127659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
127759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
127859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
127959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
128059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_NOW;
128159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
128259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
128359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
128559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
128659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
128759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
128859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
129059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
129159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
129259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
129359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
129559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
129659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
129859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_TIMER &&
130059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_EXT)
130159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
130259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
130359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
130459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
130659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
130759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
130959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
131059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
131159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
131259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
131359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
131459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
131559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
131659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
131759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg = thisboard->ao_scan_speed;
131859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
131959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
132059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
132159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
132259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
132359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
132459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
132559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
132659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
132759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
132859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
132959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
133059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
133159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
133259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
133359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
133559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
133659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
133859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
134059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
134159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
134259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->ao_divisor1), &(devpriv->ao_divisor2),
134359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
134459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
134559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
134659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
134759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
134959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
135059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1351cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
135259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist && cmd->chanlist_len > 1) {
135359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
135459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			CR_CHAN(cmd->chanlist[1]) != 1) {
135559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_error(dev,
135659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				"channels must be ordered channel 0, channel 1 in chanlist\n");
135759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
135859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
135959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
136059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
136259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
136359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
136559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
136659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1367da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
136859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1369d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1370ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
137159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
137259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
137359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1374cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel limits, gain */
137559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
137659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < cmd->chanlist_len; i++) {
1377cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  enable channel */
137859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |=
137959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1380cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  set range */
138159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
138259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			CR_RANGE(cmd->chanlist[i]));
138359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
138459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1385cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable analog out before settings pacer source and count values */
138659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
138759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
138859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1389cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
139059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
139159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1392cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
139359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
139459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
139559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->ao_divisor1), &(devpriv->ao_divisor2),
139659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags);
139759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
139859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
139959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
140059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_divisor1, 2);
140159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
140259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_divisor2, 2);
140359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1404cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
140559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
140659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
140759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1408cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
140959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
141059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (cmd->scan_begin_src) {
141159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_TIMER:
141259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_INT;
141359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
141459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_EXT:
141559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
141659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
141759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
141859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
141959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "error setting dac pacer source");
142059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
142159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
142259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
142359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
142459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = cb_pcidas_ao_inttrig;
142659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
142859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
142959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1430d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1431d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *s,
1432d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num)
143359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
143459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_bytes, num_points = thisboard->fifo_size;
1435d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1436ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
143759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
143859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
143959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (trig_num != 0)
144059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
144159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1442cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load up fifo */
144359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
144459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = devpriv->ao_count;
144559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
144659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1447790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points * sizeof(short));
1448790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_points = num_bytes / sizeof(short);
144959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
145059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
145159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count -= num_points;
145259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1453cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  write data to board's fifo */
145459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
145559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1456cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable dac half-full and empty interrupts */
145759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
145859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
145959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
146059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
146159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1462cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable and clear interrupts */
146359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
146459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + INT_ADCFIFO);
146559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1466cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  start dac */
146759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
146859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
146959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
147059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to dac control\n",
147159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits);
147259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
147359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
147459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
147559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = NULL;
147659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
147759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
147859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
147959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
148070265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d)
148159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
148271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = (struct comedi_device *) d;
148334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->read_subdev;
1484d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
148559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int status, s5933_status;
148659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int half_fifo = thisboard->fifo_size / 2;
148759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_samples, i;
148859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
148959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
149059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->attached == 0) {
149259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
149359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
149459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async = s->async;
149659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
149759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
149959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
150059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("intcsr 0x%x\n", s5933_status);
150159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
150259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
150359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
150459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
150559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
150659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1507cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
150859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1509cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear interrupt on amcc s5933 */
151059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
151159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
151259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
151359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	status = inw(devpriv->control_status + INT_ADCFIFO);
151459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
151559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) {
151659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "spurious interrupt");
151759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
151859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
151959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1520cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog output interrupt */
152159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & (DAHFI | DAEMI)) {
152259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		handle_ao_interrupt(dev, status);
152359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1524cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog input interrupts */
1525cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  if fifo half-full */
152659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & ADHFI) {
1527cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  read data */
152859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_samples = half_fifo;
152959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT &&
153059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples > devpriv->count) {
153159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples = devpriv->count;
153259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
153359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
153459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples);
153559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
1536790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton			num_samples * sizeof(short));
153759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count -= num_samples;
153859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
153959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
154059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cb_pcidas_cancel(dev, s);
154159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1542cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
154359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
154459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
154559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
154659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1547cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  else if fifo not empty */
154859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & (ADNEI | EOBI)) {
154959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
1550cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  break if fifo is empty */
155159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if ((ADNE & inw(devpriv->control_status +
155259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez						INT_ADCFIFO)) == 0)
155359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
155459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
155559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) {	/* end of acquisition */
155659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_cancel(dev, s);
155759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_EOA;
155859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
155959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
156059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1561cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear not-empty interrupt latch */
156259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
156359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
156459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
156559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
156659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & EOAI) {
156759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev,
156859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			"bug! encountered end of aquisition interrupt?");
1569cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear EOA interrupt latch */
157059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
157159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | EOAI,
157259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
157359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
157459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1575cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* check for fifo overflow */
157659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & LADFUL) {
157759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "fifo overflow");
1578cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear overflow interrupt latch */
157959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
158059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | LADFUL,
158159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
158259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
158359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_cancel(dev, s);
158459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
158559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
158659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
158859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return IRQ_HANDLED;
159059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
159159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1592da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
159359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
159434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->write_subdev;
1595d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1596ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
159759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int half_fifo = thisboard->fifo_size / 2;
159859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_points;
159959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int flags;
160059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
160159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
160259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
160359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & DAEMI) {
1604cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear dac empty interrupt latch */
160559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
160659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAEMI,
160759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
160859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
160959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
161059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cmd->stop_src == TRIG_NONE ||
161159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				(cmd->stop_src == TRIG_COUNT
161259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					&& devpriv->ao_count)) {
161359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev, "dac fifo underflow");
161459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_ao_cancel(dev, s);
161559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_ERROR;
161659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
161759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
161859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
161959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & DAHFI) {
162059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		unsigned int num_bytes;
162159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1622cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  figure out how many points we are writing to fifo */
162359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = half_fifo;
162459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_src == TRIG_COUNT &&
162559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count < num_points)
162659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points = devpriv->ao_count;
162759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_bytes =
162859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1629790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton			num_points * sizeof(short));
1630790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points = num_bytes / sizeof(short);
163159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
163259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT) {
163359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count -= num_points;
163459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1635cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  write data to board's fifo */
163659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
163759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points);
1638cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
163959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
164059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAHFI,
164159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
164259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
164359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
164459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
164559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
164659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
164759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1648d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog input command */
1649da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
165059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
165159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
165259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
165359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
1654cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
165559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
165659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
165759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
165859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1659cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable start trigger source and burst mode */
166059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1661cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  software pacer source */
166259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + ADCMUX_CONT);
166359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
166459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
166559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
166659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1667d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog output command */
1668d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
1669d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton			       struct comedi_subdevice *s)
167059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
167159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
167259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
167359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
1674cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
167559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
167659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
167759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1678cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable output */
167959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
168059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
168159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
168259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
168359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
168459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
168559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1686da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
168759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int rounding_flags)
168859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
168959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
169059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		&(devpriv->divisor2), ns, rounding_flags & TRIG_ROUND_MASK);
169159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
169259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
169359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
169459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->divisor1, 2);
169559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
169659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->divisor2, 2);
169759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
169859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1699da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void write_calibration_bitstream(struct comedi_device *dev,
170059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits, unsigned int bitstream,
170159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream_length)
170259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
170359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int write_delay = 1;
170459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bit;
170559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
170659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
170759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (bitstream & bit)
170859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits |= SERIAL_DATA_IN_BIT;
170959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
171059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits &= ~SERIAL_DATA_IN_BIT;
171159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_udelay(write_delay);
171259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(register_bits, devpriv->control_status + CALIBRATION_REG);
171359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
171459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
171559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1716da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int caldac_8800_write(struct comedi_device *dev, unsigned int address,
171759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value)
171859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
171959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_caldac_channels = 8;
172059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 11;
172159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((address & 0x7) << 8) | value;
172259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int caldac_8800_comedi_udelay = 1;
172359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
172459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (address >= num_caldac_channels) {
172559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "illegal caldac channel");
172659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
172759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
172859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
172959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (value == devpriv->caldac_value[address])
173059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
173159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->caldac_value[address] = value;
173359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
173559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
173659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(caldac_8800_comedi_udelay);
173859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_8800_BIT,
173959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
174059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(caldac_8800_comedi_udelay);
174159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
174259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
174359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
174459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
174559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1746da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
174759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
174859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 7;
174959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = value & 0x7f;
175059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
175159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int ad7376_comedi_udelay = 1;
175259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
175459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad7376_comedi_udelay);
175559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
175659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
175859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
175959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad7376_comedi_udelay);
176159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
176259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
176459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
176559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* For 1602/16 only
176759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 0 : adc gain
176859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 1 : adc postgain offset */
1769da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
177059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value)
177159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
177259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 10;
177359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
177459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
177559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int ad8402_comedi_udelay = 1;
177659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
177759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
177859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad8402_comedi_udelay);
177959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
178059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
178259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
178359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad8402_comedi_udelay);
178559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
178659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
178859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
178959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic int wait_for_nvram_ready(unsigned long s5933_base_addr)
179159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
179259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 1000;
179359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
179459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < timeout; i++) {
179659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if ((inb(s5933_base_addr +
179759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
179859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			== 0)
179959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return 0;
180059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_udelay(1);
180159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
180259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -1;
180359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
180459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1805da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int nvram_read(struct comedi_device *dev, unsigned int address, uint8_t *data)
180659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
180759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long iobase = devpriv->s5933_config;
180859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
180959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
181059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
181159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
181359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		iobase + AMCC_OP_REG_MCSR_NVCMD);
181459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
181559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
181659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		iobase + AMCC_OP_REG_MCSR_NVCMD);
181759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
181859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
181959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
182159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
182259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	*data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
182459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
182659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
182759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
182959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * A convenient macro that defines init_module() and cleanup_module(),
183059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * as necessary.
183159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
183259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezCOMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table);
1833