cb_pcidas.c revision cf530aa4385c97f668d76c8268d509ef9edebb70
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>
6659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8253.h"
6859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8255.h"
6959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "amcc_s5933.h"
7059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_pci.h"
7159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_fc.h"
7259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
73cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#undef CB_PCIDAS_DEBUG		/*  disable debugging code */
74cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* #define CB_PCIDAS_DEBUG         enable debugging code */
7559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
76cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* PCI vendor number of ComputerBoards/MeasurementComputing */
7759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PCI_VENDOR_ID_CB	0x1307
78cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TIMER_BASE 100		/*  10MHz master clock */
79cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AI_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
80cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AO_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
8159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8800 8
8259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_7376 1
8359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8402 2
8459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_DAC08 1
8559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
8659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* PCI-DAS base addresses */
8759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
88cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* indices of base address regions */
8959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define S5933_BADRINDEX 0
9059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_BADRINDEX 1
9159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_BADRINDEX 2
9259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_BADRINDEX 3
9359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_BADRINDEX 4
94cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* sizes of io regions */
9559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_SIZE 10
9659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_SIZE 4
9759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_SIZE 12
9859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_SIZE 4
9959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* Control/Status registers */
101cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define INT_ADCFIFO	0	/*  INTERRUPT / ADC FIFO register */
102cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_EOS 0x1		/*  interrupt end of scan */
103cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FHF 0x2		/*  interrupt fifo half full */
104cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FNE 0x3		/*  interrupt fifo not empty */
105cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_MASK 0x3		/*  mask of interrupt select bits */
106cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INTE 0x4		/*  interrupt enable */
107cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFIE 0x8		/*  dac half full interrupt enable */
108cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAIE	0x10		/*  end of aquisition interrupt enable */
109cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFI	0x20		/*  dac half full read status / write interrupt clear */
110cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAI 0x40		/*  read end of acq. interrupt status / write clear */
111cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT 0x80		/*  read interrupt status / write clear */
112cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOBI 0x200		/*  read end of burst interrupt status */
113cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADHFI 0x400		/*  read half-full interrupt status */
114cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNEI 0x800		/*  read fifo not empty interrupt latch status */
115cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNE 0x1000		/*  read, fifo not empty (realtime, not latched) status */
116cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMIE	0x1000	/*  write, dac empty interrupt enable */
117cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   LADFUL 0x2000		/*  read fifo overflow / write clear */
118cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMI 0x4000		/*  dac fifo empty interrupt status / write clear */
119cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
120cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCMUX_CONT	2	/*  ADC CHANNEL MUX AND CONTROL register */
12159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   BEGIN_SCAN(x)	((x) & 0xf)
12259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   END_SCAN(x)	(((x) & 0xf) << 4)
12359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   GAIN_BITS(x)	(((x) & 0x3) << 8)
124cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   UNIP	0x800		/*  Analog front-end unipolar for range */
125cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SE	0x400		/*  Inputs in single-ended mode */
126cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_MASK	0x3000	/*  pacer source bits */
127cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_INT 0x1000	/*  internal pacer */
128cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_FALL	0x2000	/*  external falling edge */
129cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_RISE	0x3000	/*  external rising edge */
130cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOC	0x4000		/*  adc not busy */
131cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
132cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TRIG_CONTSTAT 4		/*  TRIGGER CONTROL/STATUS register */
133cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SW_TRIGGER 0x1	/*  software start trigger */
134cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EXT_TRIGGER 0x2	/*  external start trigger */
135cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ANALOG_TRIGGER 0x3	/*  external analog trigger */
136cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TRIGGER_MASK	0x3	/*  mask of bits that determine start trigger */
137cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TGEN	0x10		/*  enable external start trigger */
138cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   BURSTE 0x20		/*  burst mode enable */
139cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   XTRCL	0x80		/*  clear external trigger */
140cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
141cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define CALIBRATION_REG	6	/*  CALIBRATION register */
142cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_8800_BIT	0x100	/*  select 8800 caldac */
143cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_TRIMPOT_BIT	0x200	/*  select ad7376 trim pot */
144cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_DAC08_BIT	0x400	/*  select dac08 caldac */
14559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)
146cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   CAL_EN_BIT	0x4000	/*  read calibration source instead of analog input channel 0 */
147cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SERIAL_DATA_IN_BIT	0x8000	/*  serial data stream going to 8800 and 7376 */
14859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DAC_CSR	0x8		/*  dac control and status register */
15059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits {
151cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DACEN = 0x2,		/*  dac enable */
152cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_MODE_UPDATE_BOTH = 0x80,	/*  update both dacs when dac0 is written */
15359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
15459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
15559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
15659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return (range & 0x3) << (8 + 2 * (channel & 0x1));
15759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
15859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE_MASK(unsigned int channel)
15959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
16059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0x3 << (8 + 2 * (channel & 0x1));
16159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
16259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
163cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bits for 1602 series only */
16459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits_1602 {
165cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_EMPTY = 0x1,	/*  dac fifo empty, read, write clear */
166cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_START = 0x4,	/*  start/arm dac fifo operations */
167cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_MASK = 0x18,	/*  bits that set dac pacer source */
168cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_INT = 0x8,	/*  dac internal pacing */
169cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_FALL = 0x10,	/*  dac external pacing, falling edge */
170cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_RISE = 0x18,	/*  dac external pacing, rising edge */
17159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_CHAN_EN(unsigned int channel)
17359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
174cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
17559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog input fifo */
178cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCDATA	0		/*  ADC DATA register */
179cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCFIFOCLR	2	/*  ADC FIFO CLEAR */
18059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pacer, counter, dio registers */
18259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC8254 0
18359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DIO_8255 4
18459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC8254 8
18559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output registers for 100x, 1200 series */
18759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_DATA_REG(unsigned int channel)
18859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
18959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2 * (channel & 0x1);
19059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
19159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
19259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog output registers for 1602 series*/
193cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACDATA	0		/*  DAC DATA register */
194cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACFIFOCLR	2	/*  DAC FIFO CLEAR */
19559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
196cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bit in hexadecimal representation of range index that indicates unipolar input range */
19759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define IS_UNIPOLAR 0x4
198cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog input ranges for most boards */
1999ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ranges = {
20059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
20159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
20259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
20359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(5),
20459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(2.5),
20559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(1.25),
20659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
20759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(5),
20859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(2.5),
20959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(1.25)
21059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
21159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
21259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
213cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pci-das1001 input ranges */
2149ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_alt_ranges = {
21559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
21659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
21759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
21859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(1),
21959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(0.1),
22059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(0.01),
22159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
22259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(1),
22359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(0.1),
22459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(0.01)
22559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
22659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
22759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
228cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output ranges */
2299ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ao_ranges = {
23059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	4,
23159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
23259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(5),
23359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			BIP_RANGE(10),
23459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(5),
23559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			UNI_RANGE(10),
23659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
23759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
23859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
23959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum trimpot_model {
24059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD7376,
24159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD8402,
24259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
24359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2445c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstruct cb_pcidas_board {
24559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const char *name;
24659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned short device_id;
247cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_se_chans;	/*  Inputs in single-ended mode */
248cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_diff_chans;	/*  Inputs in differential mode */
249cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_bits;		/*  analog input resolution */
250cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_speed;		/*  fastest conversion period in ns */
251cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_nchan;		/*  number of analog out channels */
252cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int has_ao_fifo;	/*  analog output has fifo */
253cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
254cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int fifo_size;		/*  number of samples fifo can hold */
2559ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
25659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	enum trimpot_model trimpot;
25759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned has_dac08:1;
2585c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton};
25959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2605c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstatic const struct cb_pcidas_board cb_pcidas_boards[] = {
26159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
26259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1602/16",
26359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x1,
26459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
26559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
26659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	16,
26759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:5000,
26859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:2,
26959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:1,
27059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_scan_speed:10000,
27159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:512,
27259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
27359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD8402,
27459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:1,
27559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
27659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
27759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1200",
27859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0xF,
27959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
28059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
28159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
28259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:3200,
28359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:2,
28459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
28559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
28659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
28759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
28859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
28959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
29059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
29159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1602/12",
29259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x10,
29359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
29459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
29559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
29659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:3200,
29759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:2,
29859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:1,
29959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_scan_speed:4000,
30059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
30159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
30259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
30359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
30459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
30559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
30659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1200/jr",
30759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x19,
30859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
30959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
31059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
31159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:3200,
31259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:0,
31359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
31459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
31559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
31659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
31759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
31859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
31959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
32059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1602/16/jr",
32159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x1C,
32259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
32359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
32459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	16,
32559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:5000,
32659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:0,
32759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
32859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:512,
32959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
33059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD8402,
33159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:1,
33259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
33359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
33459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1000",
33559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x4C,
33659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
33759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
33859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
33959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:4000,
34059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:0,
34159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
34259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
34359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
34459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
34559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
34659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
34759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
34859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1001",
34959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x1a,
35059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
35159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
35259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
35359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:6800,
35459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:2,
35559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
35659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
35759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_alt_ranges,
35859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
35959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
36059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
36159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
36259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      name:	"pci-das1002",
36359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      device_id:0x1b,
36459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_se_chans:16,
36559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_diff_chans:8,
36659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_bits:	12,
36759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ai_speed:6800,
36859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ao_nchan:2,
36959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_ao_fifo:0,
37059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      fifo_size:1024,
37159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      ranges:	&cb_pcidas_ranges,
37259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      trimpot:	AD7376,
37359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	      has_dac08:0,
37459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		},
37559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
37659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
377cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* Number of boards in cb_pcidas_boards */
3785c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define N_BOARDS	(sizeof(cb_pcidas_boards) / sizeof(struct cb_pcidas_board))
37959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
38059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
38159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0001, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x000f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0010, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x0019, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x004c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001a, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{PCI_VENDOR_ID_CB, 0x001b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
38959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{0}
39059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
39159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
39359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
39559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Useful for shorthand access to the particular board structure
39659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
3975c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr)
39859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
39959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* this structure is for data unique to this hardware driver.  If
40059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez   several hardware drivers keep similar information in this structure,
40171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
402c77e25898523395b56e1d120195e1ad2e3efa14dBill Pembertonstruct cb_pcidas_private {
40359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* would be useful for a PCI device */
40459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pci_dev;
405cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  base addresses */
40659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long s5933_config;
40759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long control_status;
40859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long adc_fifo;
40959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long pacer_counter_dio;
41059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long ao_registers;
411cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog input pacing */
41259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor1;
41359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor2;
414cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int count;	/*  number of analog input samples remaining */
415cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int adc_fifo_bits;	/*  bits to write to interupt/adcfifo register */
416cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int s5933_intcsr_bits;	/*  bits to write to amcc s5933 interrupt control/status register */
417cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_control_bits;	/*  bits to write to ao control and status register */
418790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_buffer[AI_BUFFER_SIZE];
419790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ao_buffer[AO_BUFFER_SIZE];
420cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog output pacing */
42159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor1;
42259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor2;
423cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_count;	/*  number of analog output samples remaining */
424cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
425cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int caldac_value[NUM_CHANNELS_8800];	/*  for readback of caldac */
426cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int trimpot_value[NUM_CHANNELS_8402];	/*  for readback of trimpot */
42759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int dac08_value;
42859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int calibration_source;
429c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton};
43059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
43259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * most drivers define the following macro to make it easy to
43359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * access the private structure.
43459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
435c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton#define devpriv ((struct cb_pcidas_private *)dev->private)
43659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
43759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
438139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
43959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * which functions to call to configure/deconfigure (attach/detach)
44059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the board, and also about the kernel module that contains
44159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the device code.
44259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
4430707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it);
44471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_detach(struct comedi_device * dev);
445139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_cb_pcidas = {
44659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      driver_name:"cb_pcidas",
44759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      module:THIS_MODULE,
44859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      attach:cb_pcidas_attach,
44959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      detach:cb_pcidas_detach,
45059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
45159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
452d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice * s,
45390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
45590035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
45790035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
45834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
45990035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
46034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
46190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
46234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
46334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
464ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
46534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
466d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
467d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *subdev,
468d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num);
46934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
470ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
47159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG);
47271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void handle_ao_interrupt(struct comedi_device * dev, unsigned int status);
47334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
47434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
47571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
47659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int round_flags);
47734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
47890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
47934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device * dev, unsigned int channel,
486790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int value);
48734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
48890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
48934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
49090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
49171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dac08_write(struct comedi_device * dev, unsigned int value);
49234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
49390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
49471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int caldac_8800_write(struct comedi_device * dev, unsigned int address,
49559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value);
49671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_7376_write(struct comedi_device * dev, uint8_t value);
49771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
49859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value);
49971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int nvram_read(struct comedi_device * dev, unsigned int address,
50059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t * data);
50159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
50271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic inline unsigned int cal_enable_bits(struct comedi_device * dev)
50359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
50459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
50559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
50659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
50759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
50859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Attach is called by the Comedi core to configure the driver
50959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * for a particular board.
51059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
5110707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int cb_pcidas_attach(struct comedi_device * dev, struct comedi_devconfig * it)
51259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
51334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
51459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pcidev;
51559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int index;
51659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i;
51759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
51859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: ", dev->minor);
51959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
52059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
52159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the private structure area.
52259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
523c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
52459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
52559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
52659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
52759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Probe the device to determine what device in the series it is.
52859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
52959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("\n");
53059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
53159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
53259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev != NULL;
53359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pcidev)) {
534cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  is it not a computer boards card? */
53559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (pcidev->vendor != PCI_VENDOR_ID_CB)
53659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			continue;
537cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  loop through cards supported by this driver */
53859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (index = 0; index < N_BOARDS; index++) {
53959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cb_pcidas_boards[index].device_id != pcidev->device)
54059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				continue;
541cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  was a particular bus/slot requested? */
54259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (it->options[0] || it->options[1]) {
543cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton				/*  are we on the wrong bus/slot? */
54459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				if (pcidev->bus->number != it->options[0] ||
54559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					PCI_SLOT(pcidev->devfn) !=
54659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					it->options[1]) {
54759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					continue;
54859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				}
54959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
55059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->pci_dev = pcidev;
55159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->board_ptr = cb_pcidas_boards + index;
55259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			goto found;
55359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
55459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
55559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
55659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("No supported ComputerBoards/MeasurementComputing card found on "
55759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		"requested position\n");
55859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EIO;
55959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez      found:
56159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
56359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pcidev->bus->number, PCI_SLOT(pcidev->devfn));
56459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
56659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Enable PCI device and reserve I/O ports.
56759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
56859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_pci_enable(pcidev, "cb_pcidas")) {
56959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" Failed to enable PCI device and request regions\n");
57059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EIO;
57159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
57259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
57359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Initialize devpriv->control_status and devpriv->adc_fifo to point to
57459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * their base address.
57559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
57659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_config =
57759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
57859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->control_status =
57959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
58059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo =
58159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
58259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->pacer_counter_dio =
58359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
58459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
58559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_registers =
58659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
58759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
588cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable and clear interrupts on amcc s5933 */
58959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(INTCSR_INBOX_INTR_STATUS,
59059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
59159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
592cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  get irq */
59359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
59459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			IRQF_SHARED, "cb_pcidas", dev)) {
59559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
59659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
59759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
59859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->irq = devpriv->pci_dev->irq;
59959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
600cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* Initialize dev->board_name */
60159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->board_name = thisboard->name;
60259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
60359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
60459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the subdevice structures.
60559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
60659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (alloc_subdevices(dev, 7) < 0)
60759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
60859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
60959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 0;
61059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog input subdevice */
61159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->read_subdev = s;
61259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_AI;
61359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
61459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* WARNING: Number of inputs in differential mode is ignored */
61559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = thisboard->ai_se_chans;
61659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->len_chanlist = thisboard->ai_se_chans;
61759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = (1 << thisboard->ai_bits) - 1;
61859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->range_table = thisboard->ranges;
61959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = cb_pcidas_ai_rinsn;
62059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_config = ai_config_insn;
62159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmd = cb_pcidas_ai_cmd;
62259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmdtest = cb_pcidas_ai_cmdtest;
62359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->cancel = cb_pcidas_cancel;
62459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
62559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog output subdevice */
62659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 1;
62759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
62859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_AO;
62959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
63059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = thisboard->ao_nchan;
631cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  analog out resolution is the same as analog input resolution, so use ai_bits */
63259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = (1 << thisboard->ai_bits) - 1;
63359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->range_table = &cb_pcidas_ao_ranges;
63459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = cb_pcidas_ao_readback_insn;
63559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (thisboard->has_ao_fifo) {
63659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->write_subdev = s;
63759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->subdev_flags |= SDF_CMD_WRITE;
63859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_fifo_winsn;
63959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmdtest = cb_pcidas_ao_cmdtest;
64059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmd = cb_pcidas_ao_cmd;
64159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->cancel = cb_pcidas_ao_cancel;
64259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		} else {
64359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_nofifo_winsn;
64459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
64559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
64659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
64759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
64859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
64959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* 8255 */
65059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 2;
65159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
65259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
653cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  serial EEPROM, */
65459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 3;
65559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_MEMORY;
65659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
65759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = 256;
65859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
65959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = eeprom_read_insn;
66059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
661cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  8800 caldac */
66259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 4;
66359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
66459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
66559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = NUM_CHANNELS_8800;
66659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
66759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = caldac_read_insn;
66859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = caldac_write_insn;
66959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
67059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		caldac_8800_write(dev, i, s->maxdata / 2);
67159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
672cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  trim potentiometer */
67359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 5;
67459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
67559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
67659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->trimpot == AD7376) {
67759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_7376;
67859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0x7f;
67959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
68059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_8402;
68159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
68259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
68359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = trimpot_read_insn;
68459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = trimpot_write_insn;
68559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
68659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
68759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
688cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  dac08 caldac */
68959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 6;
69059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->has_dac08) {
69159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_CALIB;
69259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
69359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_DAC08;
69459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = dac08_read_insn;
69559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_write = dac08_write_insn;
69659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
69759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		dac08_write(dev, s->maxdata / 2);
69859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else
69959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
70059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
701cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
70259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
70359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
70459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_intcsr_bits =
70559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
70659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		INTCSR_INBOX_FULL_INT;
707cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear and enable interrupt on amcc s5933 */
70859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
70959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
71059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
71159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
71259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
71359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
71459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
71559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cb_pcidas_detach is called to deconfigure a device.  It should deallocate
71659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * resources.
71759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * This function is also called when _attach() fails, so it should be
71859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * careful not to release resources that were not necessarily
71959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * allocated by _attach().  dev->private and dev->subdevices are
72059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * deallocated automatically by the core.
72159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
72271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_detach(struct comedi_device * dev)
72359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
72459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
72559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
72659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv) {
72759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
728cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  disable and clear interrupts on amcc s5933 */
72959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			outl(INTCSR_INBOX_INTR_STATUS,
73059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				devpriv->s5933_config + AMCC_OP_REG_INTCSR);
73159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
73259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			rt_printk("detaching, incsr is 0x%x\n",
73359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				inl(devpriv->s5933_config +
73459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					AMCC_OP_REG_INTCSR));
73559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
73659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
73759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
73859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->irq)
73959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_free_irq(dev->irq, dev);
74059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->subdevices)
74159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
74259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv && devpriv->pci_dev) {
74359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
74459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_pci_disable(devpriv->pci_dev);
74559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
74659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_dev_put(devpriv->pci_dev);
74759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
74859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
74959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
75059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
75159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
75259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
75359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * "instructions" read/write data in "one-shot" or "software-triggered"
75459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * mode.
75559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
75634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
75790035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
75859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
75959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int n, i;
76059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
76159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
76259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
763cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable calibration input if appropriate */
76459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (insn->chanspec & CR_ALT_SOURCE) {
76559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(cal_enable_bits(dev),
76659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + CALIBRATION_REG);
76759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = 0;
76859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
76959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->control_status + CALIBRATION_REG);
77059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = CR_CHAN(insn->chanspec);
77159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
772cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits and gain */
77359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(channel) |
77459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
775cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
77659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
77759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
778cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
77959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(insn->chanspec) != AREF_DIFF)
78059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
78159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
78259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
78359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* clear fifo */
78459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
78559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
78659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* convert n samples */
78759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (n = 0; n < insn->n; n++) {
78859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* trigger conversion */
78959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->adc_fifo + ADCDATA);
79059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
79159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* wait for conversion to end */
79259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* return -ETIMEDOUT if there is a timeout */
79359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
79459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
79559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
79659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
79759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (i == timeout)
79859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return -ETIMEDOUT;
79959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* read data */
80159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		data[n] = inw(devpriv->adc_fifo + ADCDATA);
80259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
80359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* return the number of samples read/written */
80559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return n;
80659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
80759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
80871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int ai_config_calibration_source(struct comedi_device * dev, unsigned int * data)
80959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
81059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_calibration_sources = 8;
811790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int source = data[1];
81259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
81359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (source >= num_calibration_sources) {
81459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk("invalid calibration source: %i\n", source);
81559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
81659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
81759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
81859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->calibration_source = source;
81959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2;
82159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
82259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int ai_config_insn(struct comedi_device * dev, struct comedi_subdevice * s,
82490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
82559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
82659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int id = data[0];
82759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (id) {
82959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case INSN_CONFIG_ALT_SOURCE:
83059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return ai_config_calibration_source(dev, data);
83159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
83259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
83359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
83459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
83559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
83659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EINVAL;
83759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
83859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
839cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1000 and 1200 series */
84034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
84190035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
84259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
84359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
84459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
84559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
846cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
84759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
84859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
84959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
85059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
85159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
85259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
85359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
85459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
85559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
856cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
85759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
858cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
85959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
86059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
86259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
86359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
864cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1602 series */
86534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
86690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
86759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
86859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
86959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
87059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
871cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear dac fifo */
87259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
87359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
874cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
87559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
87659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
87759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
87859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
87959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		~DAC_PACER_MASK;
88059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
88159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		DACEN | DAC_RANGE(channel,
88259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		CR_RANGE(insn->chanspec)) | DAC_CHAN_EN(channel) | DAC_START;
88359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
88459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
88559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
886cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
88759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
888cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
88959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DACDATA);
89059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
89159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
89259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
89359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
894cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output readback insn */
895cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* XXX loses track of analog output value back after an analog ouput command is executed */
89634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_readback_insn(struct comedi_device * dev, struct comedi_subdevice * s,
89790035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
89859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
89959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
90059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
90159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
90259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
90359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
90434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int eeprom_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
90590035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
90659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
90759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t nvram_data;
90859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int retval;
90959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
91159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (retval < 0)
91259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return retval;
91359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = nvram_data;
91559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
91759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
91859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
92090035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
92159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
92259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const unsigned int channel = CR_CHAN(insn->chanspec);
92359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
92459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return caldac_8800_write(dev, channel, data[0]);
92559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
92659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
92734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int caldac_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
92890035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
92959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
93059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
93159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
93259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
93359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
93459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
93559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 1602/16 pregain offset */
93671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int dac08_write(struct comedi_device * dev, unsigned int value)
93759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
93859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->dac08_value == value)
93959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
94059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->dac08_value = value;
94259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
94459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
94559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
94659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
94759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
94859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
94959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
95059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
95159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(1);
95259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
95359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
95459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
95559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
95634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
95790035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
95859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
95959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return dac08_write(dev, data[0]);
96059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
96159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int dac08_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
96390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
96459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
96559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->dac08_value;
96659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
96859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
96959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device * dev,
971790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int channel, unsigned int value)
97259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
97359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->trimpot_value[channel] == value)
97459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
97559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->trimpot_value[channel] = value;
97759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (thisboard->trimpot) {
97859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD7376:
97959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_7376_write(dev, value);
98059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD8402:
98259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_8402_write(dev, channel, value);
98359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
98559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "driver bug?");
98659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
98759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
98859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
98959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
99159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
99259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_write_insn(struct comedi_device * dev, struct comedi_subdevice * s,
99490035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
99559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
99659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
99759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return cb_pcidas_trimpot_write(dev, channel, data[0]);
99959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
100059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int trimpot_read_insn(struct comedi_device * dev, struct comedi_subdevice * s,
100290035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
100359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
100459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
100559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->trimpot_value[channel];
100759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
100959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
101059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
101134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1012ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd)
101359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
101459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
101559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
101659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i, gain, start_chan;
101759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
101859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
101959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
102059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
102159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
102259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
102359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
102459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
102659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
102859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_NOW | TRIG_EXT;
102959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
103059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
103159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
103359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
103459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
103559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
103659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
103859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
103959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
104059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
104159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
104359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
104459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
104559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
104659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
104859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
104959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
105059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
105159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
105359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
105459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
105659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
105859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
105959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW &&
106059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_TIMER &&
106159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_EXT)
106259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src != TRIG_TIMER &&
106459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
106559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
106759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
106859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1069cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure trigger sources are compatible with each other */
107059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
107159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
107359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_EXT &&
107559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		(cmd->convert_src == TRIG_EXT
107659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			|| cmd->scan_begin_src == TRIG_EXT))
107759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
107859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
107959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
108059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
108159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
108359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
108559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
108659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
108759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
108859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
109059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg <
109159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			thisboard->ai_speed * cmd->chanlist_len) {
109259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg =
109359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				thisboard->ai_speed * cmd->chanlist_len;
109459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
109559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
109659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
109759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
109859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_arg < thisboard->ai_speed) {
109959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->convert_arg = thisboard->ai_speed;
110059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
110159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
110259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
110359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
110459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
110559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
110659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
110859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
110959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
111059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
111159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
111259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
111359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
111459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
111559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
111759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
111859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
112059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
112159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
112259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
112359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
112459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->divisor1), &(devpriv->divisor2),
112559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
112659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
112759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
112859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
112959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
113059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->convert_arg;
113159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
113259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->divisor1), &(devpriv->divisor2),
113359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
113459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->convert_arg)
113559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
113659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
113759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
113859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
113959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
114059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1141cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
114259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist) {
114359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		gain = CR_RANGE(cmd->chanlist[0]);
114459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		start_chan = CR_CHAN(cmd->chanlist[0]);
114559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 1; i < cmd->chanlist_len; i++) {
114659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_CHAN(cmd->chanlist[i]) !=
114759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				(start_chan + i) % s->n_chan) {
114859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
114959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					"entries in chanlist must be consecutive channels, counting upwards\n");
115059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
115159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
115259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_RANGE(cmd->chanlist[i]) != gain) {
115359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
115459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					"entries in chanlist must all have the same gain\n");
115559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
115659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
115759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
115859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
115959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
116159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
116259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
116459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
116559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
116759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1168d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1169ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
117059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
117159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
117259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1173cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure CAL_EN_BIT is disabled */
117459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + CALIBRATION_REG);
1175cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  initialize before settings pacer source and count values */
117659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1177cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
117859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
117959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1180cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits, gain and pacer source */
118159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
118259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
118359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1184cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
118559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
118659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
1187cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
118859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
118959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
1190cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
119159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
119259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_EXT_RISE;
119359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else
119459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_INT;
119559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
119659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
119759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
119859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to adcmux control\n", bits);
119959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
120059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1201cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
120259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER)
120359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->convert_arg,
120459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->flags & TRIG_ROUND_MASK);
120559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->scan_begin_src == TRIG_TIMER)
120659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
120759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->flags & TRIG_ROUND_MASK);
120859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1209cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
121059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
121159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
121259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1213cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable interrupts */
121459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
121559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= INTE;
121659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INT_MASK;
121759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->flags & TRIG_WAKE_EOS) {
121859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1219cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_EOS;	/*  interrupt end of burst */
122059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
1221cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_FNE;	/*  interrupt fifo not empty */
122259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
1223cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		devpriv->adc_fifo_bits |= INT_FHF;	/* interrupt fifo half full */
122459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
122559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
122659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
122759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1228cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable (and clear) interrupts */
122959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
123059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + INT_ADCFIFO);
123159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
123259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1233cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set start trigger and burst mode */
123459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = 0;
123559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_NOW)
123659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SW_TRIGGER;
123759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->start_src == TRIG_EXT)
123859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= EXT_TRIGGER | TGEN | XTRCL;
123959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else {
124059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "bug!");
124159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
124259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
124359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
124459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= BURSTE;
124559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + TRIG_CONTSTAT);
124659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
124759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to trig control\n", bits);
124859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
124959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
125059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
125159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
125259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
125334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1254ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd)
125559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
125659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
125759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
125859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
125959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
126059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
126159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
126259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
126359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
126459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
126559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
126659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
126759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
126859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
126959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_INT;
127059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
127159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
127259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
127359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
127459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
127559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
127659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
127759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
127859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
127959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_NOW;
128059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
128159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
128259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
128459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
128559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
128659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
128759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
128959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
129059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
129159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
129259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
129459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
129559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
129759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
129859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_TIMER &&
129959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_begin_src != TRIG_EXT)
130059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
130159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
130259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
130359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
130559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
130659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
130859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
130959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
131059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
131159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
131259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
131359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
131459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
131559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
131659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg = thisboard->ao_scan_speed;
131759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
131859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
131959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
132059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
132159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
132259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
132359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
132459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
132559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
132659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
132759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
132859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
132959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
133059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
133159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
133259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
133459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
133559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
133759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
133959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
134059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
134159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->ao_divisor1), &(devpriv->ao_divisor2),
134259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
134359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
134459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
134559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
134659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
134859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
134959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1350cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
135159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist && cmd->chanlist_len > 1) {
135259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
135359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			CR_CHAN(cmd->chanlist[1]) != 1) {
135459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_error(dev,
135559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				"channels must be ordered channel 0, channel 1 in chanlist\n");
135659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
135759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
135859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
135959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
136159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
136259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
136459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
136559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_ao_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
136759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1368d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1369ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
137059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
137159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
137259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1373cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel limits, gain */
137459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
137559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < cmd->chanlist_len; i++) {
1376cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  enable channel */
137759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |=
137859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1379cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  set range */
138059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
138159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			CR_RANGE(cmd->chanlist[i]));
138259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
138359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1384cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable analog out before settings pacer source and count values */
138559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
138659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
138759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1388cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
138959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
139059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1391cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
139259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
139359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
139459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(devpriv->ao_divisor1), &(devpriv->ao_divisor2),
139559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			&(cmd->scan_begin_arg), cmd->flags);
139659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
139759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
139859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
139959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_divisor1, 2);
140059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
140159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_divisor2, 2);
140259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1403cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
140459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
140559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
140659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1407cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
140859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
140959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (cmd->scan_begin_src) {
141059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_TIMER:
141159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_INT;
141259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
141359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_EXT:
141459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
141559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
141659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
141759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
141859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "error setting dac pacer source");
141959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
142059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
142159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
142259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
142359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = cb_pcidas_ao_inttrig;
142559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
142759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
142859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1429d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1430d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *s,
1431d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num)
143259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
143359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_bytes, num_points = thisboard->fifo_size;
1434d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1435ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
143659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
143759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
143859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (trig_num != 0)
143959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
144059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1441cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load up fifo */
144259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
144359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = devpriv->ao_count;
144459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
144559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1446790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points * sizeof(short));
1447790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_points = num_bytes / sizeof(short);
144859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
144959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT) {
145059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count -= num_points;
145159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1452cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  write data to board's fifo */
145359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
145459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1455cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable dac half-full and empty interrupts */
145659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
145759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
145859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
145959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
146059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1461cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable and clear interrupts */
146259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
146359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + INT_ADCFIFO);
146459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1465cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  start dac */
146659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
146759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
146859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
146959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("comedi: sent 0x%x to dac control\n",
147059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits);
147159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
147259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
147359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
147459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = NULL;
147559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
147659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
147759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
147859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
147959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic irqreturn_t cb_pcidas_interrupt(int irq, void *d PT_REGS_ARG)
148059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
148171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = (struct comedi_device *) d;
148234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->read_subdev;
1483d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
148459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int status, s5933_status;
148559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int half_fifo = thisboard->fifo_size / 2;
148659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_samples, i;
148759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
148859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
148959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->attached == 0) {
149159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
149259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
149359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async = s->async;
149559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
149659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
149859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
149959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("intcsr 0x%x\n", s5933_status);
150059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	rt_printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
150159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
150259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
150359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
150459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
150559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1506cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
150759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1508cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear interrupt on amcc s5933 */
150959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
151059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->s5933_config + AMCC_OP_REG_INTCSR);
151159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
151259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	status = inw(devpriv->control_status + INT_ADCFIFO);
151359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
151459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0) {
151559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "spurious interrupt");
151659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
151759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
151859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1519cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog output interrupt */
152059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & (DAHFI | DAEMI)) {
152159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		handle_ao_interrupt(dev, status);
152259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1523cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog input interrupts */
1524cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  if fifo half-full */
152559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & ADHFI) {
1526cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  read data */
152759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_samples = half_fifo;
152859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT &&
152959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples > devpriv->count) {
153059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples = devpriv->count;
153159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
153259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
153359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples);
153459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
1535790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton			num_samples * sizeof(short));
153659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count -= num_samples;
153759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
153859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
153959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cb_pcidas_cancel(dev, s);
154059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1541cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
154259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
154359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
154459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
154559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
1546cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  else if fifo not empty */
154759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & (ADNEI | EOBI)) {
154859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
1549cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  break if fifo is empty */
155059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if ((ADNE & inw(devpriv->control_status +
155159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez						INT_ADCFIFO)) == 0)
155259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
155359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
155459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) {	/* end of acquisition */
155559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_cancel(dev, s);
155659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_EOA;
155759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
155859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
155959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1560cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear not-empty interrupt latch */
156159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
156259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
156359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
156459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
156559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & EOAI) {
156659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev,
156759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			"bug! encountered end of aquisition interrupt?");
1568cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear EOA interrupt latch */
156959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
157059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | EOAI,
157159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
157259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
157359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1574cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* check for fifo overflow */
157559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & LADFUL) {
157659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "fifo overflow");
1577cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear overflow interrupt latch */
157859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
157959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | LADFUL,
158059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
158159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
158259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_cancel(dev, s);
158359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
158459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
158559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
158759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return IRQ_HANDLED;
158959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
159059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
159171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void handle_ao_interrupt(struct comedi_device * dev, unsigned int status)
159259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
159334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->write_subdev;
1594d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1595ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
159659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int half_fifo = thisboard->fifo_size / 2;
159759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_points;
159859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int flags;
159959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
160059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
160159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
160259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & DAEMI) {
1603cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear dac empty interrupt latch */
160459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
160559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAEMI,
160659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
160759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
160859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
160959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cmd->stop_src == TRIG_NONE ||
161059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				(cmd->stop_src == TRIG_COUNT
161159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					&& devpriv->ao_count)) {
161259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev, "dac fifo underflow");
161359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_ao_cancel(dev, s);
161459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_ERROR;
161559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
161659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
161759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
161859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & DAHFI) {
161959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		unsigned int num_bytes;
162059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1621cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  figure out how many points we are writing to fifo */
162259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = half_fifo;
162359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_src == TRIG_COUNT &&
162459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count < num_points)
162559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points = devpriv->ao_count;
162659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_bytes =
162759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1628790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton			num_points * sizeof(short));
1629790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points = num_bytes / sizeof(short);
163059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
163159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT) {
163259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count -= num_points;
163359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1634cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  write data to board's fifo */
163559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
163659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points);
1637cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
163859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_lock_irqsave(&dev->spinlock, flags);
163959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAHFI,
164059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->control_status + INT_ADCFIFO);
164159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
164259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
164359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
164459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
164559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
164659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1647d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog input command */
164834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int cb_pcidas_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
164959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
165059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
165159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
165259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
1653cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
165459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
165559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
165659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
165759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1658cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable start trigger source and burst mode */
165959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1660cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  software pacer source */
166159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + ADCMUX_CONT);
166259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
166359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
166459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
166559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1666d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog output command */
1667d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
1668d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton			       struct comedi_subdevice *s)
166959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
167059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
167159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
167259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_lock_irqsave(&dev->spinlock, flags);
1673cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
167459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
167559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
167659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1677cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable output */
167859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
167959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
168059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
168159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
168259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
168359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
168459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
168571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device * dev, unsigned int *ns,
168659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int rounding_flags)
168759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
168859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
168959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		&(devpriv->divisor2), ns, rounding_flags & TRIG_ROUND_MASK);
169059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
169159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
169259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
169359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->divisor1, 2);
169459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
169559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->divisor2, 2);
169659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
169759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
169871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void write_calibration_bitstream(struct comedi_device * dev,
169959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits, unsigned int bitstream,
170059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream_length)
170159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
170259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int write_delay = 1;
170359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bit;
170459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
170559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
170659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (bitstream & bit)
170759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits |= SERIAL_DATA_IN_BIT;
170859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
170959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits &= ~SERIAL_DATA_IN_BIT;
171059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_udelay(write_delay);
171159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(register_bits, devpriv->control_status + CALIBRATION_REG);
171259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
171359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
171459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
171571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int caldac_8800_write(struct comedi_device * dev, unsigned int address,
171659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value)
171759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
171859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_caldac_channels = 8;
171959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 11;
172059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((address & 0x7) << 8) | value;
172159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int caldac_8800_comedi_udelay = 1;
172259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
172359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (address >= num_caldac_channels) {
172459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "illegal caldac channel");
172559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
172659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
172759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
172859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (value == devpriv->caldac_value[address])
172959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
173059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->caldac_value[address] = value;
173259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
173459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
173559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(caldac_8800_comedi_udelay);
173759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_8800_BIT,
173859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->control_status + CALIBRATION_REG);
173959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(caldac_8800_comedi_udelay);
174059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
174159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
174259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
174359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
174459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
174571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_7376_write(struct comedi_device * dev, uint8_t value)
174659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
174759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 7;
174859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = value & 0x7f;
174959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
175059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int ad7376_comedi_udelay = 1;
175159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
175359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad7376_comedi_udelay);
175459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
175559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
175759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
175859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad7376_comedi_udelay);
176059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
176159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
176359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
176459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* For 1602/16 only
176659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 0 : adc gain
176759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 1 : adc postgain offset */
176871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int trimpot_8402_write(struct comedi_device * dev, unsigned int channel,
176959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t value)
177059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
177159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 10;
177259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
177359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
177459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int ad8402_comedi_udelay = 1;
177559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
177659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
177759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad8402_comedi_udelay);
177859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
177959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
178159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bitstream_length);
178259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_udelay(ad8402_comedi_udelay);
178459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
178559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
178759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
178859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic int wait_for_nvram_ready(unsigned long s5933_base_addr)
179059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
179159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 1000;
179259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
179359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < timeout; i++) {
179559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if ((inb(s5933_base_addr +
179659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
179759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			== 0)
179859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return 0;
179959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_udelay(1);
180059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
180159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -1;
180259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
180359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
180471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int nvram_read(struct comedi_device * dev, unsigned int address, uint8_t * data)
180559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
180659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long iobase = devpriv->s5933_config;
180759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
180859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
180959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
181059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
181259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		iobase + AMCC_OP_REG_MCSR_NVCMD);
181359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
181459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
181559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		iobase + AMCC_OP_REG_MCSR_NVCMD);
181659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
181759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
181859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
182059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
182159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	*data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
182359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
182559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
182659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
182859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * A convenient macro that defines init_module() and cleanup_module(),
182959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * as necessary.
183059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
183159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezCOMEDI_PCI_INITCLEANUP(driver_cb_pcidas, cb_pcidas_pci_table);
1832