cb_pcidas.c revision f1bc434398e8cf400374911357e89a13de366ce7
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.
56f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost
57f1bc434398e8cf400374911357e89a13de366ce7Brice DubostAI Triggering:
58f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost   For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
59f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost   For 1602 series, the start_arg is interpreted as follows:
60f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost     start_arg == 0                   => gated triger (level high)
61f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost     start_arg == CR_INVERT           => gated triger (level low)
62f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost     start_arg == CR_EDGE             => Rising edge
63f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost     start_arg == CR_EDGE | CR_INVERT => Falling edge
64f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost   For the other boards the trigger will be done on rising edge
6559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/
6659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
6759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezTODO:
6959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
7059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezanalog triggering on 1602 series
7159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez*/
7259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
7359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "../comedidev.h"
7459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include <linux/delay.h>
7570265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slaby#include <linux/interrupt.h>
7659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
7759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8253.h"
7859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "8255.h"
7959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "amcc_s5933.h"
8059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_pci.h"
8159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#include "comedi_fc.h"
8259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#undef CB_PCIDAS_DEBUG		/*  disable debugging code */
84cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* #define CB_PCIDAS_DEBUG         enable debugging code */
8559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* PCI vendor number of ComputerBoards/MeasurementComputing */
8759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PCI_VENDOR_ID_CB	0x1307
88cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TIMER_BASE 100		/*  10MHz master clock */
89cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AI_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
90cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define AO_BUFFER_SIZE 1024	/*  maximum fifo size of any supported board */
9159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8800 8
9259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_7376 1
9359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_8402 2
9459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define NUM_CHANNELS_DAC08 1
9559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* PCI-DAS base addresses */
9759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
98cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* indices of base address regions */
9959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define S5933_BADRINDEX 0
10059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_BADRINDEX 1
10159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_BADRINDEX 2
10259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_BADRINDEX 3
10359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_BADRINDEX 4
104cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* sizes of io regions */
10559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define CONT_STAT_SIZE 10
10659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC_FIFO_SIZE 4
10759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define PACER_SIZE 12
10859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define AO_SIZE 4
10959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
11059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* Control/Status registers */
111cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define INT_ADCFIFO	0	/*  INTERRUPT / ADC FIFO register */
112cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_EOS 0x1		/*  interrupt end of scan */
113cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FHF 0x2		/*  interrupt fifo half full */
114cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_FNE 0x3		/*  interrupt fifo not empty */
115cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT_MASK 0x3		/*  mask of interrupt select bits */
116cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INTE 0x4		/*  interrupt enable */
117cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFIE 0x8		/*  dac half full interrupt enable */
118cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAIE	0x10		/*  end of aquisition interrupt enable */
119cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAHFI	0x20		/*  dac half full read status / write interrupt clear */
120cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOAI 0x40		/*  read end of acq. interrupt status / write clear */
121cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   INT 0x80		/*  read interrupt status / write clear */
122cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOBI 0x200		/*  read end of burst interrupt status */
123cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADHFI 0x400		/*  read half-full interrupt status */
124cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNEI 0x800		/*  read fifo not empty interrupt latch status */
125cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ADNE 0x1000		/*  read, fifo not empty (realtime, not latched) status */
126cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMIE	0x1000	/*  write, dac empty interrupt enable */
127cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   LADFUL 0x2000		/*  read fifo overflow / write clear */
128cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   DAEMI 0x4000		/*  dac fifo empty interrupt status / write clear */
129cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
130cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCMUX_CONT	2	/*  ADC CHANNEL MUX AND CONTROL register */
13159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   BEGIN_SCAN(x)	((x) & 0xf)
13259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   END_SCAN(x)	(((x) & 0xf) << 4)
13359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   GAIN_BITS(x)	(((x) & 0x3) << 8)
134cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   UNIP	0x800		/*  Analog front-end unipolar for range */
135cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SE	0x400		/*  Inputs in single-ended mode */
136cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_MASK	0x3000	/*  pacer source bits */
137cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_INT 0x1000	/*  internal pacer */
138cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_FALL	0x2000	/*  external falling edge */
139cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   PACER_EXT_RISE	0x3000	/*  external rising edge */
140cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EOC	0x4000		/*  adc not busy */
141cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
142cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define TRIG_CONTSTAT 4		/*  TRIGGER CONTROL/STATUS register */
143cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SW_TRIGGER 0x1	/*  software start trigger */
144cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   EXT_TRIGGER 0x2	/*  external start trigger */
145cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   ANALOG_TRIGGER 0x3	/*  external analog trigger */
146cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TRIGGER_MASK	0x3	/*  mask of bits that determine start trigger */
147f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost#define   TGPOL	0x04		/*  invert the edge/level of the external trigger (1602 only) */
148f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost#define   TGSEL	0x08		/*  if set edge triggered, otherwise level trigerred (1602 only) */
149cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   TGEN	0x10		/*  enable external start trigger */
150cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   BURSTE 0x20		/*  burst mode enable */
151cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   XTRCL	0x80		/*  clear external trigger */
152cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton
153cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define CALIBRATION_REG	6	/*  CALIBRATION register */
154cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_8800_BIT	0x100	/*  select 8800 caldac */
155cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_TRIMPOT_BIT	0x200	/*  select ad7376 trim pot */
156cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SELECT_DAC08_BIT	0x400	/*  select dac08 caldac */
15759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)
158cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   CAL_EN_BIT	0x4000	/*  read calibration source instead of analog input channel 0 */
159cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define   SERIAL_DATA_IN_BIT	0x8000	/*  serial data stream going to 8800 and 7376 */
16059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
161cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DAC_CSR	0x8		/*  dac control and status register */
16259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits {
163cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DACEN = 0x2,		/*  dac enable */
164cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_MODE_UPDATE_BOTH = 0x80,	/*  update both dacs when dac0 is written */
16559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
16659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
16759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
16859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return (range & 0x3) << (8 + 2 * (channel & 0x1));
16959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
1700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral
17159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_RANGE_MASK(unsigned int channel)
17259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
17359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0x3 << (8 + 2 * (channel & 0x1));
17459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
17559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
176cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bits for 1602 series only */
17759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum dac_csr_bits_1602 {
178cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_EMPTY = 0x1,	/*  dac fifo empty, read, write clear */
179cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_START = 0x4,	/*  start/arm dac fifo operations */
180cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_MASK = 0x18,	/*  bits that set dac pacer source */
181cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_INT = 0x8,	/*  dac internal pacing */
182cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_FALL = 0x10,	/*  dac external pacing, falling edge */
183cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	DAC_PACER_EXT_RISE = 0x18,	/*  dac external pacing, rising edge */
18459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
18559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_CHAN_EN(unsigned int channel)
18659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
187cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
18859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
18959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
19059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog input fifo */
191cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCDATA	0		/*  ADC DATA register */
192cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define ADCFIFOCLR	2	/*  ADC FIFO CLEAR */
19359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
194cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pacer, counter, dio registers */
19559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define ADC8254 0
19659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DIO_8255 4
19759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define DAC8254 8
19859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
199cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output registers for 100x, 1200 series */
20059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic inline unsigned int DAC_DATA_REG(unsigned int channel)
20159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
20259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2 * (channel & 0x1);
20359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
20459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
20559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* analog output registers for 1602 series*/
206cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACDATA	0		/*  DAC DATA register */
207cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton#define DACFIFOCLR	2	/*  DAC FIFO CLEAR */
20859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
209cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* bit in hexadecimal representation of range index that indicates unipolar input range */
21059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#define IS_UNIPOLAR 0x4
211cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog input ranges for most boards */
2129ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ranges = {
21359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
21459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(2.5),
2180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1.25),
2190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(5),
2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(2.5),
2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(1.25)
2230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
22459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
22559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
226cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* pci-das1001 input ranges */
2279ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_alt_ranges = {
22859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	8,
22959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(1),
2320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.1),
2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(0.01),
2340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(1),
2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(0.1),
2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(0.01)
2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
23959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
24059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
241cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output ranges */
2429ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange cb_pcidas_ao_ranges = {
24359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	4,
24459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(5),
2460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 BIP_RANGE(10),
2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(5),
2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 UNI_RANGE(10),
2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
25059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
25159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
25259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezenum trimpot_model {
25359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD7376,
25459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	AD8402,
25559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
25659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2575c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstruct cb_pcidas_board {
25859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const char *name;
25959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned short device_id;
260cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_se_chans;	/*  Inputs in single-ended mode */
261cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_diff_chans;	/*  Inputs in differential mode */
262cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_bits;		/*  analog input resolution */
263cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ai_speed;		/*  fastest conversion period in ns */
264cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_nchan;		/*  number of analog out channels */
265cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int has_ao_fifo;	/*  analog output has fifo */
266cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_scan_speed;	/*  analog output speed for 1602 series (for a scan, not conversion) */
267cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int fifo_size;		/*  number of samples fifo can hold */
2689ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *ranges;
26959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	enum trimpot_model trimpot;
27059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned has_dac08:1;
271f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	unsigned has_ai_trig_gated:1;	/* Tells if the AI trigger can be gated */
272f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	unsigned has_ai_trig_invert:1;	/* Tells if the AI trigger can be inverted */
2735c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton};
27459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
2755c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pembertonstatic const struct cb_pcidas_board cb_pcidas_boards[] = {
27659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/16",
2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1,
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 16,
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 5000,
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 1,
2850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_scan_speed = 10000,
2860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 512,
2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
2880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD8402,
2890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 1,
290f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 1,
291f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 1,
2920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
29359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1200",
2950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0xF,
2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
2970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
306f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 0,
307f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 0,
3080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
30959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/12",
3110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x10,
3120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 1,
3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_scan_speed = 4000,
3190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
323f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 1,
324f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 1,
3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
32659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1200/jr",
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x19,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3200,
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
339f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 0,
340f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 0,
3410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
34259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1602/16/jr",
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1C,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 16,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 5000,
3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 512,
3520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD8402,
3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 1,
355f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 1,
356f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 1,
3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
35859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1000",
3600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x4C,
3610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 4000,
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 0,
3660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
3690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
371f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 0,
372f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 0,
3730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
37459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1001",
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1a,
3770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6800,
3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
3840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_alt_ranges,
3850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
387f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 0,
388f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 0,
3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
39059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	{
3910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "pci-das1002",
3920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .device_id = 0x1b,
3930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_se_chans = 16,
3940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_diff_chans = 8,
3950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_bits = 12,
3960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6800,
3970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_nchan = 2,
3980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_ao_fifo = 0,
3990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .fifo_size = 1024,
4000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ranges = &cb_pcidas_ranges,
4010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .trimpot = AD7376,
4020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .has_dac08 = 0,
403f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_gated = 0,
404f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	 .has_ai_trig_invert = 0,
4050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
40659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
40759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
40859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
40916f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
41016f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
41116f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
41216f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
41316f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
41416f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
41516f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
41616f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
41716f08494f4523de348988763b74e5756d482978bJavier Martinez Canillas	{ 0 }
41859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
41959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
42059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan MartinezMODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
42159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
42259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
42359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Useful for shorthand access to the particular board structure
42459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
4255c2670cba2a5fd1a27f938ae11b3a24518d999dbBill Pemberton#define thisboard ((const struct cb_pcidas_board *)dev->board_ptr)
42659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
42759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* this structure is for data unique to this hardware driver.  If
42859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez   several hardware drivers keep similar information in this structure,
42971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton   feel free to suggest moving the variable to the struct comedi_device struct.  */
430c77e25898523395b56e1d120195e1ad2e3efa14dBill Pembertonstruct cb_pcidas_private {
43159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* would be useful for a PCI device */
43259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	struct pci_dev *pci_dev;
433cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  base addresses */
43459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long s5933_config;
43559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long control_status;
43659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long adc_fifo;
43759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long pacer_counter_dio;
43859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long ao_registers;
439cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog input pacing */
44059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor1;
44159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int divisor2;
442cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int count;	/*  number of analog input samples remaining */
443cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int adc_fifo_bits;	/*  bits to write to interupt/adcfifo register */
444cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int s5933_intcsr_bits;	/*  bits to write to amcc s5933 interrupt control/status register */
445cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_control_bits;	/*  bits to write to ao control and status register */
446790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ai_buffer[AI_BUFFER_SIZE];
447790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short ao_buffer[AO_BUFFER_SIZE];
448cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  divisors of master clock for analog output pacing */
44959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor1;
45059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int ao_divisor2;
451cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	volatile unsigned int ao_count;	/*  number of analog output samples remaining */
452cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	int ao_value[2];	/*  remember what the analog outputs are set to, to allow readback */
453cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int caldac_value[NUM_CHANNELS_8800];	/*  for readback of caldac */
454cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	unsigned int trimpot_value[NUM_CHANNELS_8402];	/*  for readback of trimpot */
45559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int dac08_value;
45659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int calibration_source;
457c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton};
45859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
45959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
46059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * most drivers define the following macro to make it easy to
46159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * access the private structure.
46259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
463c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton#define devpriv ((struct cb_pcidas_private *)dev->private)
46459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
46559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
466139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pemberton * The struct comedi_driver structure tells the Comedi core module
46759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * which functions to call to configure/deconfigure (attach/detach)
46859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the board, and also about the kernel module that contains
46959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * the device code.
47059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
4710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_attach(struct comedi_device *dev,
4720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it);
473da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_detach(struct comedi_device *dev);
474139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_cb_pcidas = {
47568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "cb_pcidas",
47668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
47768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = cb_pcidas_attach,
47868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = cb_pcidas_detach,
47959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez};
48059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
4810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev,
4820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
4830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data);
484814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
4850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_insn *insn, unsigned int *data);
4860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
4870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
4880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
4890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data);
4900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
4910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
4920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn,
4930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int *data);
4940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
4950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
4960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_insn *insn,
4970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int *data);
4980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmd(struct comedi_device *dev,
4990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
5000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
5010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
5020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd);
5030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmd(struct comedi_device *dev,
5040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
505d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
506d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *subdev,
507d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num);
5080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
5090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
5100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd);
51170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d);
512814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void handle_ao_interrupt(struct comedi_device *dev, unsigned int status);
5130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_cancel(struct comedi_device *dev,
5140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s);
5150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
5160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s);
517814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
5180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    int round_flags);
5190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int eeprom_read_insn(struct comedi_device *dev,
5200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
5220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_read_insn(struct comedi_device *dev,
5230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
5250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_write_insn(struct comedi_device *dev,
5260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
5270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data);
5280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_read_insn(struct comedi_device *dev,
5290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
5300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data);
5310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_trimpot_write(struct comedi_device *dev,
5320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int channel, unsigned int value);
5330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_write_insn(struct comedi_device *dev,
5340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
5350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data);
5360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_read_insn(struct comedi_device *dev,
5370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
5380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data);
539814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int dac08_write(struct comedi_device *dev, unsigned int value);
5400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_write_insn(struct comedi_device *dev,
5410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
5420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
543814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int caldac_8800_write(struct comedi_device *dev, unsigned int address,
5440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     uint8_t value);
545814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int trimpot_7376_write(struct comedi_device *dev, uint8_t value);
546814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
5470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      uint8_t value);
548814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int nvram_read(struct comedi_device *dev, unsigned int address,
5492d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		      uint8_t *data);
55059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
551814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic inline unsigned int cal_enable_bits(struct comedi_device *dev)
55259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
55359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
55459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
55559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
55659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
55759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Attach is called by the Comedi core to configure the driver
55859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * for a particular board.
55959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
5600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_attach(struct comedi_device *dev,
5610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_devconfig *it)
56259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
56334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
56420fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	struct pci_dev *pcidev = NULL;
56559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int index;
56659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i;
56759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
56859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: ", dev->minor);
56959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
57059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
57159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the private structure area.
57259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
573c77e25898523395b56e1d120195e1ad2e3efa14dBill Pemberton	if (alloc_private(dev, sizeof(struct cb_pcidas_private)) < 0)
57459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
57559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
57659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
57759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Probe the device to determine what device in the series it is.
57859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
57959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("\n");
58059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
58120fb2280815510533cbd7785b53821ca7209345bKulikov Vasiliy	for_each_pci_dev(pcidev) {
582cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  is it not a computer boards card? */
58359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (pcidev->vendor != PCI_VENDOR_ID_CB)
58459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			continue;
585cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  loop through cards supported by this driver */
5868629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton		for (index = 0; index < ARRAY_SIZE(cb_pcidas_boards); index++) {
58759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cb_pcidas_boards[index].device_id != pcidev->device)
58859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				continue;
589cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  was a particular bus/slot requested? */
59059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (it->options[0] || it->options[1]) {
591cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton				/*  are we on the wrong bus/slot? */
59259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				if (pcidev->bus->number != it->options[0] ||
5930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    PCI_SLOT(pcidev->devfn) != it->options[1]) {
59459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez					continue;
59559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				}
59659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
59759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->pci_dev = pcidev;
59859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->board_ptr = cb_pcidas_boards + index;
59959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			goto found;
60059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
60159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
60259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
60359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("No supported ComputerBoards/MeasurementComputing card found on "
6040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       "requested position\n");
60559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EIO;
60659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
6070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralfound:
60859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
60959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("Found %s on bus %i, slot %i\n", cb_pcidas_boards[index].name,
6100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       pcidev->bus->number, PCI_SLOT(pcidev->devfn));
61159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
61259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
61359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Enable PCI device and reserve I/O ports.
61459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
61559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (comedi_pci_enable(pcidev, "cb_pcidas")) {
61659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" Failed to enable PCI device and request regions\n");
61759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EIO;
61859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
61959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/*
62059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Initialize devpriv->control_status and devpriv->adc_fifo to point to
62159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * their base address.
62259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 */
62359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_config =
6240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, S5933_BADRINDEX);
62559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->control_status =
6260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, CONT_STAT_BADRINDEX);
62759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo =
6280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, ADC_FIFO_BADRINDEX);
62959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->pacer_counter_dio =
6300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    pci_resource_start(devpriv->pci_dev, PACER_BADRINDEX);
63159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
63259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_registers =
6330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    pci_resource_start(devpriv->pci_dev, AO_BADRINDEX);
63459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
635cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable and clear interrupts on amcc s5933 */
63659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(INTCSR_INBOX_INTR_STATUS,
6370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
63859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
639cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  get irq */
6405f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	if (request_irq(devpriv->pci_dev->irq, cb_pcidas_interrupt,
64159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			IRQF_SHARED, "cb_pcidas", dev)) {
64259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk(" unable to allocate irq %d\n", devpriv->pci_dev->irq);
64359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
64459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
64559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->irq = devpriv->pci_dev->irq;
64659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
647cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* Initialize dev->board_name */
64859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->board_name = thisboard->name;
64959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
65059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
65159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * Allocate the subdevice structures.
65259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
65359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (alloc_subdevices(dev, 7) < 0)
65459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ENOMEM;
65559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
65659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 0;
65759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog input subdevice */
65859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	dev->read_subdev = s;
65959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_AI;
66059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
66159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* WARNING: Number of inputs in differential mode is ignored */
66259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = thisboard->ai_se_chans;
66359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->len_chanlist = thisboard->ai_se_chans;
66459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = (1 << thisboard->ai_bits) - 1;
66559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->range_table = thisboard->ranges;
66659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = cb_pcidas_ai_rinsn;
66759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_config = ai_config_insn;
66859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmd = cb_pcidas_ai_cmd;
66959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->do_cmdtest = cb_pcidas_ai_cmdtest;
67059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->cancel = cb_pcidas_cancel;
67159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
67259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* analog output subdevice */
67359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 1;
67459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->ao_nchan) {
67559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_AO;
67659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
67759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = thisboard->ao_nchan;
678cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  analog out resolution is the same as analog input resolution, so use ai_bits */
67959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = (1 << thisboard->ai_bits) - 1;
68059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->range_table = &cb_pcidas_ao_ranges;
68159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = cb_pcidas_ao_readback_insn;
68259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (thisboard->has_ao_fifo) {
68359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			dev->write_subdev = s;
68459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->subdev_flags |= SDF_CMD_WRITE;
68559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_fifo_winsn;
68659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmdtest = cb_pcidas_ao_cmdtest;
68759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->do_cmd = cb_pcidas_ao_cmd;
68859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->cancel = cb_pcidas_ao_cancel;
68959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		} else {
69059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			s->insn_write = cb_pcidas_ao_nofifo_winsn;
69159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
69259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
69359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
69459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
69559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
69659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* 8255 */
69759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 2;
69859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	subdev_8255_init(dev, s, NULL, devpriv->pacer_counter_dio + DIO_8255);
69959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
700cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  serial EEPROM, */
70159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 3;
70259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_MEMORY;
70359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
70459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = 256;
70559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
70659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = eeprom_read_insn;
70759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
708cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  8800 caldac */
70959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 4;
71059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
71159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
71259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->n_chan = NUM_CHANNELS_8800;
71359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->maxdata = 0xff;
71459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = caldac_read_insn;
71559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = caldac_write_insn;
71659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
71759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		caldac_8800_write(dev, i, s->maxdata / 2);
71859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
719cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  trim potentiometer */
72059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 5;
72159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->type = COMEDI_SUBD_CALIB;
72259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
72359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->trimpot == AD7376) {
72459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_7376;
72559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0x7f;
72659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
72759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_8402;
72859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
72959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
73059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_read = trimpot_read_insn;
73159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s->insn_write = trimpot_write_insn;
73259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < s->n_chan; i++)
73359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
73459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
735cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  dac08 caldac */
73659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s = dev->subdevices + 6;
73759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (thisboard->has_dac08) {
73859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_CALIB;
73959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
74059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->n_chan = NUM_CHANNELS_DAC08;
74159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_read = dac08_read_insn;
74259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->insn_write = dac08_write_insn;
74359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->maxdata = 0xff;
74459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		dac08_write(dev, s->maxdata / 2);
74559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else
74659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		s->type = COMEDI_SUBD_UNUSED;
74759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
748cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
74959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
75059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
75159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->s5933_intcsr_bits =
7520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
7530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    INTCSR_INBOX_FULL_INT;
754cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear and enable interrupt on amcc s5933 */
75559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
7560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
75759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
75859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
75959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
76059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
76159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
76259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * cb_pcidas_detach is called to deconfigure a device.  It should deallocate
76359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * resources.
76459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * This function is also called when _attach() fails, so it should be
76559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * careful not to release resources that were not necessarily
76659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * allocated by _attach().  dev->private and dev->subdevices are
76759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * deallocated automatically by the core.
76859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
769da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_detach(struct comedi_device *dev)
77059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
77159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	printk("comedi%d: cb_pcidas: remove\n", dev->minor);
77259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
77359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv) {
77459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (devpriv->s5933_config) {
775cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  disable and clear interrupts on amcc s5933 */
77659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			outl(INTCSR_INBOX_INTR_STATUS,
7770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
77859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
7795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman			printk("detaching, incsr is 0x%x\n",
7800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR));
78159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
78259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
78359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
78459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->irq)
7855f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
78659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (dev->subdevices)
78759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		subdev_8255_cleanup(dev, dev->subdevices + 2);
78859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv && devpriv->pci_dev) {
7892d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		if (devpriv->s5933_config)
79059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_pci_disable(devpriv->pci_dev);
79159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		pci_dev_put(devpriv->pci_dev);
79259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
79359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
79459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
79559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
79659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
79759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
79859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * "instructions" read/write data in "one-shot" or "software-triggered"
79959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * mode.
80059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
8010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_rinsn(struct comedi_device *dev,
8020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
8030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data)
80459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
80559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int n, i;
80659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
80759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
80859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
809cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable calibration input if appropriate */
81059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (insn->chanspec & CR_ALT_SOURCE) {
81159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(cal_enable_bits(dev),
8120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + CALIBRATION_REG);
81359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = 0;
81459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
81559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->control_status + CALIBRATION_REG);
81659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		channel = CR_CHAN(insn->chanspec);
81759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
818cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits and gain */
81959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(channel) |
8200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    END_SCAN(channel) | GAIN_BITS(CR_RANGE(insn->chanspec));
821cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
82259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(insn->chanspec) & IS_UNIPOLAR)
82359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
824cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
82559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(insn->chanspec) != AREF_DIFF)
82659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
82759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
82859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
82959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* clear fifo */
83059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
83159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* convert n samples */
83359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (n = 0; n < insn->n; n++) {
83459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* trigger conversion */
83559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(0, devpriv->adc_fifo + ADCDATA);
83659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
83759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* wait for conversion to end */
83859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* return -ETIMEDOUT if there is a timeout */
83959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
84059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
84159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
84259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
84359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (i == timeout)
84459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return -ETIMEDOUT;
84559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
84659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* read data */
84759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		data[n] = inw(devpriv->adc_fifo + ADCDATA);
84859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
84959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
85059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* return the number of samples read/written */
85159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return n;
85259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
85359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
8540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int ai_config_calibration_source(struct comedi_device *dev,
8550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int *data)
85659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
85759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_calibration_sources = 8;
858790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int source = data[1];
85959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (source >= num_calibration_sources) {
86159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		printk("invalid calibration source: %i\n", source);
86259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
86359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
86459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->calibration_source = source;
86659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
86759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 2;
86859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
86959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
870da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
8710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_insn *insn, unsigned int *data)
87259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
87359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int id = data[0];
87459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
87559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (id) {
87659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case INSN_CONFIG_ALT_SOURCE:
87759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return ai_config_calibration_source(dev, data);
87859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
87959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
88059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
88159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
88259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
88359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -EINVAL;
88459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
88559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
886cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1000 and 1200 series */
8870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
8880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_subdevice *s,
8890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     struct comedi_insn *insn,
8900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     unsigned int *data)
89159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
89259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
89359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
89459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
895cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
89659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
8975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
89859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
8990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_MODE_UPDATE_BOTH & ~DAC_RANGE_MASK(channel);
90059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
9010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DACEN | DAC_RANGE(channel, CR_RANGE(insn->chanspec));
90259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
9035f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
90459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
905cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
90659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
907cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
90859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(channel));
90959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
91059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
91159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
91259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
913cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output insn for pcidas-1602 series */
9140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
9150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_subdevice *s,
9160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   struct comedi_insn *insn, unsigned int *data)
91759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
91859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int channel;
91959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
92059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
921cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear dac fifo */
92259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
92359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
924cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel and range */
92559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	channel = CR_CHAN(insn->chanspec);
9265f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
92759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &=
9280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) & ~DAC_RANGE_MASK(channel) &
9290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    ~DAC_PACER_MASK;
93059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |=
9310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DACEN | DAC_RANGE(channel,
9320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      CR_RANGE(insn->
9330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       chanspec)) | DAC_CHAN_EN(channel) |
9340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    DAC_START;
93559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
9365f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
93759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
938cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  remember value for readback */
93959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_value[channel] = data[0];
940cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  send data */
94159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(data[0], devpriv->ao_registers + DACDATA);
94259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
94359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
94459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
94559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
946cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* analog output readback insn */
947cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton/* XXX loses track of analog output value back after an analog ouput command is executed */
9480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
9490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
9500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_insn *insn,
9510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int *data)
95259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
95359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
95459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
95559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
95659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
95759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int eeprom_read_insn(struct comedi_device *dev,
9590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
9600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
96159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
96259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	uint8_t nvram_data;
96359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int retval;
96459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
96659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (retval < 0)
96759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return retval;
96859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
96959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = nvram_data;
97059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
97159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
97259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
97359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_write_insn(struct comedi_device *dev,
9750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
9760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data)
97759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
97859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	const unsigned int channel = CR_CHAN(insn->chanspec);
97959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
98059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return caldac_8800_write(dev, channel, data[0]);
98159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
98259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
9830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int caldac_read_insn(struct comedi_device *dev,
9840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
9850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
98659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
98759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
98859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
98959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
99059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
99159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* 1602/16 pregain offset */
993da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int dac08_write(struct comedi_device *dev, unsigned int value)
99459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
99559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->dac08_value == value)
99659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
99759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
99859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->dac08_value = value;
99959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
100059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
10010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
10025f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
100359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_DAC08_BIT | (value & 0xff),
10040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
10055f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
100659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | (value & 0xff),
10070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
10085f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(1);
100959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
101059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
101159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
101259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_write_insn(struct comedi_device *dev,
10140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
10150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
101659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
101759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return dac08_write(dev, data[0]);
101859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
101959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int dac08_read_insn(struct comedi_device *dev,
10210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s, struct comedi_insn *insn,
10220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   unsigned int *data)
102359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
102459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->dac08_value;
102559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
102659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
102759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
102859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1029da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int cb_pcidas_trimpot_write(struct comedi_device *dev,
10300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				   unsigned int channel, unsigned int value)
103159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
103259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (devpriv->trimpot_value[channel] == value)
103359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
103459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
103559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->trimpot_value[channel] = value;
103659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (thisboard->trimpot) {
103759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD7376:
103859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_7376_write(dev, value);
103959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
104059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case AD8402:
104159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		trimpot_8402_write(dev, channel, value);
104259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
104359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
104459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "driver bug?");
104559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
104659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
104759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
104859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
104959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
105059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
105159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_write_insn(struct comedi_device *dev,
10530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s,
10540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_insn *insn, unsigned int *data)
105559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
105659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
105759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
105859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return cb_pcidas_trimpot_write(dev, channel, data[0]);
105959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
106059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int trimpot_read_insn(struct comedi_device *dev,
10620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s,
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_insn *insn, unsigned int *data)
106459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
106559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int channel = CR_CHAN(insn->chanspec);
106659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
106759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	data[0] = devpriv->trimpot_value[channel];
106859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
106959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
107059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
107159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
10720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
10730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
10740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
107559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
107659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
107759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
107859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int i, gain, start_chan;
107959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
108159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
108259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
108359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
108459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
108559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
108659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
108859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
108959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
109059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_NOW | TRIG_EXT;
109159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
109259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
109359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
109459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
109559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
109659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
109759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
109859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
109959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
110059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_TIMER | TRIG_NOW | TRIG_EXT;
110159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
110259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
110459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
110559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
110659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
110759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
110859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
110959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
111059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
111159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
111259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
111359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
111559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
111659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
111859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
111959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
112059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
112159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW &&
11220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_TIMER &&
11230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
112459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
112559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src != TRIG_TIMER &&
11260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
112759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
112859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
112959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
113059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1131cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure trigger sources are compatible with each other */
113259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
113359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
113459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
113559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
113659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_EXT &&
11370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
113859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
113959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
114059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
114159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
114259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
114359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
114459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1145f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	switch (cmd->start_src) {
1146f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	case TRIG_EXT:
1147f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		/* External trigger, only CR_EDGE and CR_INVERT flags allowed */
1148f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		if ((cmd->start_arg
1149f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
1150f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			cmd->start_arg &=
1151f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			    ~(CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1152f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			err++;
1153f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		}
1154f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		if (!thisboard->has_ai_trig_invert &&
1155f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		    (cmd->start_arg & CR_INVERT)) {
1156f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
1157f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			err++;
1158f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		}
1159f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		break;
1160f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	default:
1161f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		if (cmd->start_arg != 0) {
1162f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			cmd->start_arg = 0;
1163f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			err++;
1164f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		}
1165f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		break;
116659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
116759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
116859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
116959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg <
11700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    thisboard->ai_speed * cmd->chanlist_len) {
117159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg =
11720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    thisboard->ai_speed * cmd->chanlist_len;
117359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
117459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
117559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
117659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
117759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_arg < thisboard->ai_speed) {
117859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->convert_arg = thisboard->ai_speed;
117959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
118059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
118159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
118259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
118359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
118459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
118559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
118659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
118759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
118859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
118959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
119059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
119159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
119259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
119359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
119459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
119559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
119659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
119759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
119859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
119959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
120059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
120159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
120259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
12030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor1),
12040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
12050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
12060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
120759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
120859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
120959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
121059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER) {
121159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->convert_arg;
121259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
12130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor1),
12140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
12150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->convert_arg),
12160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
121759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->convert_arg)
121859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
121959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
122059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
122159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
122259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
122359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1224cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
122559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist) {
122659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		gain = CR_RANGE(cmd->chanlist[0]);
122759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		start_chan = CR_CHAN(cmd->chanlist[0]);
122859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 1; i < cmd->chanlist_len; i++) {
122959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_CHAN(cmd->chanlist[i]) !=
12300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (start_chan + i) % s->n_chan) {
123159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
12320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must be consecutive channels, counting upwards\n");
123359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
123459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
123559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (CR_RANGE(cmd->chanlist[i]) != gain) {
123659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev,
12370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "entries in chanlist must all have the same gain\n");
123859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				err++;
123959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
124059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
124159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
124259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
124359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
124459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
124559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
124659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
124759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
124859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
12490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ai_cmd(struct comedi_device *dev,
12500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
125159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1252d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1253ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
125459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bits;
125559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
125659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1257cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure CAL_EN_BIT is disabled */
125859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + CALIBRATION_REG);
1259cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  initialize before settings pacer source and count values */
126059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1261cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
126259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
126359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1264cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set mux limits, gain and pacer source */
126559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
12660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
12670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
1268cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set unipolar/bipolar */
126959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
127059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= UNIP;
1271cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set singleended/differential */
127259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
127359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SE;
1274cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
127559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
127659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_EXT_RISE;
127759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else
127859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= PACER_INT;
127959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + ADCMUX_CONT);
128059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
128159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
12825f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: sent 0x%x to adcmux control\n", bits);
128359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
128459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1285cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
128659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_TIMER)
128759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->convert_arg,
12880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					cmd->flags & TRIG_ROUND_MASK);
128959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	else if (cmd->scan_begin_src == TRIG_TIMER)
129059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
12910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					cmd->flags & TRIG_ROUND_MASK);
129259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1293cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
12942d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
129559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
1296cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable interrupts */
12975f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
129859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= INTE;
129959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INT_MASK;
130059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->flags & TRIG_WAKE_EOS) {
130159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1302cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_EOS;	/*  interrupt end of burst */
130359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
1304cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			devpriv->adc_fifo_bits |= INT_FNE;	/*  interrupt fifo not empty */
130559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else {
1306cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		devpriv->adc_fifo_bits |= INT_FHF;	/* interrupt fifo half full */
130759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
130859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
13095f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
131059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1311cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable (and clear) interrupts */
131259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
13130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + INT_ADCFIFO);
13145f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
131559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1316cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set start trigger and burst mode */
131759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	bits = 0;
131859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_src == TRIG_NOW)
131959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= SW_TRIGGER;
1320f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	else if (cmd->start_src == TRIG_EXT) {
132159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= EXT_TRIGGER | TGEN | XTRCL;
1322f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		if (thisboard->has_ai_trig_invert
1323f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		    && (cmd->start_arg & CR_INVERT))
1324f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			bits |= TGPOL;
1325f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost		if (thisboard->has_ai_trig_gated && (cmd->start_arg & CR_EDGE))
1326f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost			bits |= TGSEL;
1327f1bc434398e8cf400374911357e89a13de366ce7Brice Dubost	} else {
132859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "bug!");
132959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
133059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
133159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
133259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		bits |= BURSTE;
133359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(bits, devpriv->control_status + TRIG_CONTSTAT);
133459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
13355f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: sent 0x%x to trig control\n", bits);
133659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
133759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
133859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
133959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
134059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
13410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
13420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_subdevice *s,
13430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				struct comedi_cmd *cmd)
134459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
134559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int err = 0;
134659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int tmp;
134759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
134859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* cmdtest tests a particular command to see if it is valid.
134959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * Using the cmdtest ioctl, a user can create a valid cmd
135059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * and then have it executes by the cmd ioctl.
135159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 *
135259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
135359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	 * the command passes. */
135459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
135559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 1: make sure trigger sources are trivially valid */
135659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
135759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->start_src;
135859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->start_src &= TRIG_INT;
135959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->start_src || tmp != cmd->start_src)
136059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
136159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_begin_src;
136359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT;
136459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
136559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
136659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
136759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->convert_src;
136859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->convert_src &= TRIG_NOW;
136959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->convert_src || tmp != cmd->convert_src)
137059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
137159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
137259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->scan_end_src;
137359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->scan_end_src &= TRIG_COUNT;
137459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
137559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
137659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
137759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	tmp = cmd->stop_src;
137859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
137959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (!cmd->stop_src || tmp != cmd->stop_src)
138059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
138159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
138259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
138359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
138459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
138559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 2: make sure trigger sources are unique and mutually compatible */
138659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
138759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src != TRIG_TIMER &&
13880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
138959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
139059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE)
139159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
139259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
139359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
139459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 2;
139559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
139659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 3: make sure arguments are trivially compatible */
139759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
139859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->start_arg != 0) {
139959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->start_arg = 0;
140059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
140159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
140259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
140359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
140459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->scan_begin_arg < thisboard->ao_scan_speed) {
140559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->scan_begin_arg = thisboard->ao_scan_speed;
140659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
140759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
140859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
140959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
141059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_end_arg != cmd->chanlist_len) {
141159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cmd->scan_end_arg = cmd->chanlist_len;
141259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		err++;
141359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
141459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_NONE) {
141559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* TRIG_NONE */
141659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_arg != 0) {
141759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cmd->stop_arg = 0;
141859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
141959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
142059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
142159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
142359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 3;
142459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* step 4: fix up any arguments */
142659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
142759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
142859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		tmp = cmd->scan_begin_arg;
142959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
14300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor1),
14310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor2),
14320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
14330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags & TRIG_ROUND_MASK);
143459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (tmp != cmd->scan_begin_arg)
143559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
143659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
143759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
143859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
143959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 4;
144059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1441cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check channel/gain list against card's limitations */
144259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->chanlist && cmd->chanlist_len > 1) {
144359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
14440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    CR_CHAN(cmd->chanlist[1]) != 1) {
144559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			comedi_error(dev,
14460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				     "channels must be ordered channel 0, channel 1 in chanlist\n");
144759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			err++;
144859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
144959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
145059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
145159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (err)
145259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 5;
145359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
145459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
145559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
145659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
14570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_ao_cmd(struct comedi_device *dev,
14580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
145959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
1460d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1461ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
146259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
146359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
146459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1465cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set channel limits, gain */
14665f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
146759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < cmd->chanlist_len; i++) {
1468cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  enable channel */
146959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |=
14700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1471cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  set range */
147259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
14730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						      CR_RANGE(cmd->
14740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       chanlist[i]));
147559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
147659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1477cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable analog out before settings pacer source and count values */
147859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
14795f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
148059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1481cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear fifo */
148259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->ao_registers + DACFIFOCLR);
148359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1484cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load counters */
148559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->scan_begin_src == TRIG_TIMER) {
148659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
14870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor1),
14880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->ao_divisor2),
14890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd->scan_begin_arg),
14900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd->flags);
149159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
149259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
149359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
14940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   devpriv->ao_divisor1, 2);
149559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
14960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   devpriv->ao_divisor2, 2);
149759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1498cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set number of conversions */
14992d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
150059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
1501cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  set pacer source */
15025f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
150359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	switch (cmd->scan_begin_src) {
150459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_TIMER:
150559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_INT;
150659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
150759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	case TRIG_EXT:
150859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
150959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
151059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	default:
15115f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
151259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "error setting dac pacer source");
151359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
151459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		break;
151559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
15165f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
151759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
151859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = cb_pcidas_ao_inttrig;
151959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
152059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
152159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
152259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1523d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1524d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				struct comedi_subdevice *s,
1525d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton				unsigned int trig_num)
152659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
152759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_bytes, num_points = thisboard->fifo_size;
1528d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1529ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
153059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
153159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
153259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (trig_num != 0)
153359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -EINVAL;
153459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1535cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  load up fifo */
153659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
153759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = devpriv->ao_count;
153859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
153959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
15400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       num_points * sizeof(short));
1541790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_points = num_bytes / sizeof(short);
154259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
15432d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (cmd->stop_src == TRIG_COUNT)
154459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->ao_count -= num_points;
1545cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  write data to board's fifo */
154659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
154759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1548cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable dac half-full and empty interrupts */
15495f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
155059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
155159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15525f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("comedi: adc_fifo_bits are 0x%x\n", devpriv->adc_fifo_bits);
155359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
1554cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  enable and clear interrupts */
155559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
15560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + INT_ADCFIFO);
155759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1558cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  start dac */
155959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
156059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
156159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	printk("comedi: sent 0x%x to dac control\n", devpriv->ao_control_bits);
156359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
15645f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
156559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
156659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->inttrig = NULL;
156759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
156859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
156959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
157059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
157170265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t cb_pcidas_interrupt(int irq, void *d)
157259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
15730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	struct comedi_device *dev = (struct comedi_device *)d;
157434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->read_subdev;
1575d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async;
157659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int status, s5933_status;
157759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	int half_fifo = thisboard->fifo_size / 2;
157859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_samples, i;
157959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 10000;
158059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
158159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
15822d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (dev->attached == 0)
158359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
158459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async = s->async;
158659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
158759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
158859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
158959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
15905f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("intcsr 0x%x\n", s5933_status);
15915f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	printk("mbef 0x%x\n", inl(devpriv->s5933_config + AMCC_OP_REG_MBEF));
159259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
159359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
159459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
159559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return IRQ_NONE;
159659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1597cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  make sure mailbox 4 is empty */
159859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1599cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  clear interrupt on amcc s5933 */
160059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
16010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
160259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
160359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	status = inw(devpriv->control_status + INT_ADCFIFO);
160459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#ifdef CB_PCIDAS_DEBUG
16052d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if ((status & (INT | EOAI | LADFUL | DAHFI | DAEMI)) == 0)
160659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "spurious interrupt");
160759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez#endif
160859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1609cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog output interrupt */
16102d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini	if (status & (DAHFI | DAEMI))
161159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		handle_ao_interrupt(dev, status);
1612cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  check for analog input interrupts */
1613cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  if fifo half-full */
161459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & ADHFI) {
1615cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  read data */
161659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_samples = half_fifo;
161759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT &&
16180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    num_samples > devpriv->count) {
161959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_samples = devpriv->count;
162059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
162159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
16220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     num_samples);
162359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
16240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  num_samples * sizeof(short));
162559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		devpriv->count -= num_samples;
162659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
162759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
162859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cb_pcidas_cancel(dev, s);
162959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1630cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
16315f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
163259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
16330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16345f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
1635cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  else if fifo not empty */
163659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & (ADNEI | EOBI)) {
163759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		for (i = 0; i < timeout; i++) {
1638cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton			/*  break if fifo is empty */
163959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if ((ADNE & inw(devpriv->control_status +
16400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					INT_ADCFIFO)) == 0)
164159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
164259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
164359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (async->cmd.stop_src == TRIG_COUNT && --devpriv->count == 0) {	/* end of acquisition */
164459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_cancel(dev, s);
164559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_EOA;
164659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				break;
164759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
164859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
1649cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear not-empty interrupt latch */
16505f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
165159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | INT,
16520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16535f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
165459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & EOAI) {
165559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev,
16560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "bug! encountered end of aquisition interrupt?");
1657cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear EOA interrupt latch */
16585f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
165959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | EOAI,
16600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16615f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
166259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
1663cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/* check for fifo overflow */
166459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & LADFUL) {
166559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "fifo overflow");
1666cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear overflow interrupt latch */
16675f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
166859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | LADFUL,
16690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16705f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
167159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		cb_pcidas_cancel(dev, s);
167259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
167359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
167459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
167559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
167659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
167759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return IRQ_HANDLED;
167859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
167959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1680da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
168159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
168234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->write_subdev;
1683d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1684ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
168559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int half_fifo = thisboard->fifo_size / 2;
168659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int num_points;
16873a5e32ddcb04d7a2bed86323ca22da51d3a810bdGerard Lledo	unsigned long flags;
168859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
168959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	async->events = 0;
169059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
169159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (status & DAEMI) {
1692cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear dac empty interrupt latch */
16935f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
169459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAEMI,
16950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
16965f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
169759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
169859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			if (cmd->stop_src == TRIG_NONE ||
16990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (cmd->stop_src == TRIG_COUNT
17000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     && devpriv->ao_count)) {
170159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				comedi_error(dev, "dac fifo underflow");
170259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				cb_pcidas_ao_cancel(dev, s);
170359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez				async->events |= COMEDI_CB_ERROR;
170459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			}
170559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			async->events |= COMEDI_CB_EOA;
170659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		}
170759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	} else if (status & DAHFI) {
170859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		unsigned int num_bytes;
170959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1710cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  figure out how many points we are writing to fifo */
171159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_points = half_fifo;
171259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (cmd->stop_src == TRIG_COUNT &&
17130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    devpriv->ao_count < num_points)
171459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			num_points = devpriv->ao_count;
171559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		num_bytes =
17160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    cfc_read_array_from_buffer(s, devpriv->ao_buffer,
17170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       num_points * sizeof(short));
1718790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton		num_points = num_bytes / sizeof(short);
171959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17202d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini		if (async->cmd.stop_src == TRIG_COUNT)
172159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			devpriv->ao_count -= num_points;
1722cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  write data to board's fifo */
172359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
17240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		      num_points);
1725cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton		/*  clear half-full interrupt latch */
17265f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_lock_irqsave(&dev->spinlock, flags);
172759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(devpriv->adc_fifo_bits | DAHFI,
17280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     devpriv->control_status + INT_ADCFIFO);
17295f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		spin_unlock_irqrestore(&dev->spinlock, flags);
173059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
173159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
173259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	comedi_event(dev, s);
173359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
173459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1735d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog input command */
17360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int cb_pcidas_cancel(struct comedi_device *dev,
17370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s)
173859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
173959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
174059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17415f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
1742cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
174359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
174459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
17455f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
174659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1747cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable start trigger source and burst mode */
174859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1749cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  software pacer source */
175059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(0, devpriv->control_status + ADCMUX_CONT);
175159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
175259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
175359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
175459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1755d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton/* cancel analog output command */
1756d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pembertonstatic int cb_pcidas_ao_cancel(struct comedi_device *dev,
1757d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton			       struct comedi_subdevice *s)
175859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
175959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long flags;
176059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
17615f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
1762cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable interrupts */
176359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
176459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
176559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1766cf530aa4385c97f668d76c8268d509ef9edebb70Bill Pemberton	/*  disable output */
176759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
176859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
17695f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
177059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
177159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
177259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
177359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1774da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
17750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    int rounding_flags)
177659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
177759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
17780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       &(devpriv->divisor2), ns,
17790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       rounding_flags & TRIG_ROUND_MASK);
178059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
178159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
178259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
17830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   devpriv->divisor1, 2);
178459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
17850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		   devpriv->divisor2, 2);
178659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
178759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1788da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void write_calibration_bitstream(struct comedi_device *dev,
17890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int register_bits,
17900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int bitstream,
17910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					unsigned int bitstream_length)
179259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
179359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int write_delay = 1;
179459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bit;
179559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
179659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
179759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if (bitstream & bit)
179859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits |= SERIAL_DATA_IN_BIT;
179959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		else
180059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			register_bits &= ~SERIAL_DATA_IN_BIT;
18015f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(write_delay);
180259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		outw(register_bits, devpriv->control_status + CALIBRATION_REG);
180359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
180459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
180559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1806da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int caldac_8800_write(struct comedi_device *dev, unsigned int address,
18070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     uint8_t value)
180859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
180959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int num_caldac_channels = 8;
181059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 11;
181159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((address & 0x7) << 8) | value;
18125f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int caldac_8800_udelay = 1;
181359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (address >= num_caldac_channels) {
181559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		comedi_error(dev, "illegal caldac channel");
181659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -1;
181759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
181859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
181959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (value == devpriv->caldac_value[address])
182059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return 1;
182159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	devpriv->caldac_value[address] = value;
182359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
182459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
18250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
182659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18275f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(caldac_8800_udelay);
182859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev) | SELECT_8800_BIT,
18290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     devpriv->control_status + CALIBRATION_REG);
18305f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(caldac_8800_udelay);
183159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
183259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
183359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 1;
183459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
183559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
1836da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
183759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
183859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 7;
183959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = value & 0x7f;
184059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
18415f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int ad7376_udelay = 1;
184259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
184359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
18445f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad7376_udelay);
184559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
184659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
184759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
18480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
184959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18505f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad7376_udelay);
185159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
185259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
185359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
185459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
185559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
185659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/* For 1602/16 only
185759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 0 : adc gain
185859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * ch 1 : adc postgain offset */
1859da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
18600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      uint8_t value)
186159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
186259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int bitstream_length = 10;
186359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
186459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int register_bits;
18655f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	static const int ad8402_udelay = 1;
186659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
186759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
18685f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad8402_udelay);
186959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
187059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
187159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	write_calibration_bitstream(dev, register_bits, bitstream,
18720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    bitstream_length);
187359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18745f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	udelay(ad8402_udelay);
187559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
187659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
187759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
187859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
187959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
188059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinezstatic int wait_for_nvram_ready(unsigned long s5933_base_addr)
188159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
188259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	static const int timeout = 1000;
188359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned int i;
188459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
188559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	for (i = 0; i < timeout; i++) {
188659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		if ((inb(s5933_base_addr +
18870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
18880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    == 0)
188959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez			return 0;
18905f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		udelay(1);
189159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	}
189259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return -1;
189359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
189459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
18950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int nvram_read(struct comedi_device *dev, unsigned int address,
18962d238b2972bf365153ae8d699177c7a19a5f3056Andrea Gelmini			uint8_t *data)
189759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez{
189859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	unsigned long iobase = devpriv->s5933_config;
189959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
190059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
190159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
190259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
190359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
19040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     iobase + AMCC_OP_REG_MCSR_NVCMD);
190559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
190659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
19070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	     iobase + AMCC_OP_REG_MCSR_NVCMD);
190859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
190959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
191059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
191159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	if (wait_for_nvram_ready(iobase) < 0)
191259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez		return -ETIMEDOUT;
191359c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
191459c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	*data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
191559c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
191659c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez	return 0;
191759c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez}
191859c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez
191959c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez/*
192059c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * A convenient macro that defines init_module() and cleanup_module(),
192159c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez * as necessary.
192259c7dd3dc37dc42339406d08f1cde4d6194a4ccfIvan Martinez */
1923727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __devinit driver_cb_pcidas_pci_probe(struct pci_dev *dev,
1924727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas						const struct pci_device_id *ent)
1925727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1926727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return comedi_pci_auto_config(dev, driver_cb_pcidas.driver_name);
1927727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1928727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1929727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __devexit driver_cb_pcidas_pci_remove(struct pci_dev *dev)
1930727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1931727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_pci_auto_unconfig(dev);
1932727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1933727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1934727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic struct pci_driver driver_cb_pcidas_pci_driver = {
1935727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.id_table = cb_pcidas_pci_table,
1936727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.probe = &driver_cb_pcidas_pci_probe,
1937727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	.remove = __devexit_p(&driver_cb_pcidas_pci_remove)
1938727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas};
1939727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1940727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic int __init driver_cb_pcidas_init_module(void)
1941727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1942727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	int retval;
1943727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1944727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	retval = comedi_driver_register(&driver_cb_pcidas);
1945727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	if (retval < 0)
1946727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas		return retval;
1947727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1948727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	driver_cb_pcidas_pci_driver.name = (char *)driver_cb_pcidas.driver_name;
1949727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	return pci_register_driver(&driver_cb_pcidas_pci_driver);
1950727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1951727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1952727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasstatic void __exit driver_cb_pcidas_cleanup_module(void)
1953727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas{
1954727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	pci_unregister_driver(&driver_cb_pcidas_pci_driver);
1955727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas	comedi_driver_unregister(&driver_cb_pcidas);
1956727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas}
1957727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomas
1958727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_init(driver_cb_pcidas_init_module);
1959727b286b44ea359d66f47d241cc2cdad36ed7bdcArun Thomasmodule_exit(driver_cb_pcidas_cleanup_module);
196090f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
196190f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
196290f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
196390f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1964