cb_pcidas.c revision 53b800198592b0ff96577ecc5f116f7d902a4362
1/*
2    comedi/drivers/cb_pcidas.c
3
4    Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
5    David Schleef and the rest of the Comedi developers comunity.
6
7    Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
8    Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
9
10    COMEDI - Linux Control and Measurement Device Interface
11    Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
12
13    This program is free software; you can redistribute it and/or modify
14    it under the terms of the GNU General Public License as published by
15    the Free Software Foundation; either version 2 of the License, or
16    (at your option) any later version.
17
18    This program is distributed in the hope that it will be useful,
19    but WITHOUT ANY WARRANTY; without even the implied warranty of
20    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21    GNU General Public License for more details.
22
23    You should have received a copy of the GNU General Public License
24    along with this program; if not, write to the Free Software
25    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27************************************************************************
28*/
29/*
30Driver: cb_pcidas
31Description: MeasurementComputing PCI-DAS series
32  with the AMCC S5933 PCI controller
33Author: Ivan Martinez <imr@oersted.dtu.dk>,
34  Frank Mori Hess <fmhess@users.sourceforge.net>
35Updated: 2003-3-11
36Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
37  PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
38  PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
39
40Status:
41  There are many reports of the driver being used with most of the
42  supported cards. Despite no detailed log is maintained, it can
43  be said that the driver is quite tested and stable.
44
45  The boards may be autocalibrated using the comedi_calibrate
46  utility.
47
48Configuration options: not applicable, uses PCI auto config
49
50For commands, the scanned channels must be consecutive
51(i.e. 4-5-6-7, 2-3-4,...), and must all have the same
52range and aref.
53
54AI Triggering:
55   For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
56   For 1602 series, the start_arg is interpreted as follows:
57     start_arg == 0                   => gated trigger (level high)
58     start_arg == CR_INVERT           => gated trigger (level low)
59     start_arg == CR_EDGE             => Rising edge
60     start_arg == CR_EDGE | CR_INVERT => Falling edge
61   For the other boards the trigger will be done on rising edge
62*/
63/*
64
65TODO:
66
67analog triggering on 1602 series
68*/
69
70#include "../comedidev.h"
71#include <linux/delay.h>
72#include <linux/interrupt.h>
73
74#include "8253.h"
75#include "8255.h"
76#include "amcc_s5933.h"
77#include "comedi_fc.h"
78
79#define TIMER_BASE		100	/* 10MHz master clock */
80#define AI_BUFFER_SIZE		1024	/* max ai fifo size */
81#define AO_BUFFER_SIZE		1024	/* max ao fifo size */
82#define NUM_CHANNELS_8800	8
83#define NUM_CHANNELS_7376	1
84#define NUM_CHANNELS_8402	2
85#define NUM_CHANNELS_DAC08	1
86
87/* Control/Status registers */
88#define INT_ADCFIFO		0	/* INTERRUPT / ADC FIFO register */
89#define   INT_EOS		0x1	/* int end of scan */
90#define   INT_FHF		0x2	/* int fifo half full */
91#define   INT_FNE		0x3	/* int fifo not empty */
92#define   INT_MASK		0x3	/* mask of int select bits */
93#define   INTE			0x4	/* int enable */
94#define   DAHFIE		0x8	/* dac half full int enable */
95#define   EOAIE			0x10	/* end of acq. int enable */
96#define   DAHFI			0x20	/* dac half full status / clear */
97#define   EOAI			0x40	/* end of acq. int status / clear */
98#define   INT			0x80	/* int status / clear */
99#define   EOBI			0x200	/* end of burst int status */
100#define   ADHFI			0x400	/* half-full int status */
101#define   ADNEI			0x800	/* fifo not empty int status (latch) */
102#define   ADNE			0x1000	/* fifo not empty status (realtime) */
103#define   DAEMIE		0x1000	/* dac empty int enable */
104#define   LADFUL		0x2000	/* fifo overflow / clear */
105#define   DAEMI			0x4000	/* dac fifo empty int status / clear */
106
107#define ADCMUX_CONT		2	/* ADC CHANNEL MUX AND CONTROL reg */
108#define   BEGIN_SCAN(x)		((x) & 0xf)
109#define   END_SCAN(x)		(((x) & 0xf) << 4)
110#define   GAIN_BITS(x)		(((x) & 0x3) << 8)
111#define   UNIP			0x800	/* Analog front-end unipolar mode */
112#define   SE			0x400	/* Inputs in single-ended mode */
113#define   PACER_MASK		0x3000	/* pacer source bits */
114#define   PACER_INT		0x1000	/* int. pacer */
115#define   PACER_EXT_FALL	0x2000	/* ext. falling edge */
116#define   PACER_EXT_RISE	0x3000	/* ext. rising edge */
117#define   EOC			0x4000	/* adc not busy */
118
119#define TRIG_CONTSTAT		 4	/* TRIGGER CONTROL/STATUS register */
120#define   SW_TRIGGER		0x1	/* software start trigger */
121#define   EXT_TRIGGER		0x2	/* ext. start trigger */
122#define   ANALOG_TRIGGER	0x3	/* ext. analog trigger */
123#define   TRIGGER_MASK		0x3	/* start trigger mask */
124#define   TGPOL			0x04	/* invert trigger (1602 only) */
125#define   TGSEL			0x08	/* edge/level trigerred (1602 only) */
126#define   TGEN			0x10	/* enable external start trigger */
127#define   BURSTE		0x20	/* burst mode enable */
128#define   XTRCL			0x80	/* clear external trigger */
129
130#define CALIBRATION_REG		6	/* CALIBRATION register */
131#define   SELECT_8800_BIT	0x100	/* select 8800 caldac */
132#define   SELECT_TRIMPOT_BIT	0x200	/* select ad7376 trim pot */
133#define   SELECT_DAC08_BIT	0x400	/* select dac08 caldac */
134#define   CAL_SRC_BITS(x)	(((x) & 0x7) << 11)
135#define   CAL_EN_BIT		0x4000	/* calibration source enable */
136#define   SERIAL_DATA_IN_BIT	0x8000	/* serial data bit going to caldac */
137
138#define DAC_CSR			0x8	/* dac control and status register */
139#define   DACEN			0x02	/* dac enable */
140#define   DAC_MODE_UPDATE_BOTH	0x80	/* update both dacs */
141
142static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
143{
144	return (range & 0x3) << (8 + 2 * (channel & 0x1));
145}
146
147static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
148{
149	return 0x3 << (8 + 2 * (channel & 0x1));
150};
151
152/* bits for 1602 series only */
153#define   DAC_EMPTY		0x1	/* fifo empty, read, write clear */
154#define   DAC_START		0x4	/* start/arm fifo operations */
155#define   DAC_PACER_MASK	0x18	/* bits that set pacer source */
156#define   DAC_PACER_INT		0x8	/* int. pacing */
157#define   DAC_PACER_EXT_FALL	0x10	/* ext. pacing, falling edge */
158#define   DAC_PACER_EXT_RISE	0x18	/* ext. pacing, rising edge */
159
160static inline unsigned int DAC_CHAN_EN(unsigned int channel)
161{
162	return 1 << (5 + (channel & 0x1));	/*  enable channel 0 or 1 */
163};
164
165/* analog input fifo */
166#define ADCDATA			0	/* ADC DATA register */
167#define ADCFIFOCLR		2	/* ADC FIFO CLEAR */
168
169/* pacer, counter, dio registers */
170#define ADC8254			0
171#define DIO_8255		4
172#define DAC8254			8
173
174/* analog output registers for 100x, 1200 series */
175static inline unsigned int DAC_DATA_REG(unsigned int channel)
176{
177	return 2 * (channel & 0x1);
178}
179
180/* analog output registers for 1602 series*/
181#define DACDATA			0	/* DAC DATA register */
182#define DACFIFOCLR		2	/* DAC FIFO CLEAR */
183
184#define IS_UNIPOLAR		0x4	/* unipolar range mask */
185
186/* analog input ranges for most boards */
187static const struct comedi_lrange cb_pcidas_ranges = {
188	8,
189	{
190	 BIP_RANGE(10),
191	 BIP_RANGE(5),
192	 BIP_RANGE(2.5),
193	 BIP_RANGE(1.25),
194	 UNI_RANGE(10),
195	 UNI_RANGE(5),
196	 UNI_RANGE(2.5),
197	 UNI_RANGE(1.25)
198	 }
199};
200
201/* pci-das1001 input ranges */
202static const struct comedi_lrange cb_pcidas_alt_ranges = {
203	8,
204	{
205	 BIP_RANGE(10),
206	 BIP_RANGE(1),
207	 BIP_RANGE(0.1),
208	 BIP_RANGE(0.01),
209	 UNI_RANGE(10),
210	 UNI_RANGE(1),
211	 UNI_RANGE(0.1),
212	 UNI_RANGE(0.01)
213	 }
214};
215
216/* analog output ranges */
217static const struct comedi_lrange cb_pcidas_ao_ranges = {
218	4,
219	{
220	 BIP_RANGE(5),
221	 BIP_RANGE(10),
222	 UNI_RANGE(5),
223	 UNI_RANGE(10),
224	 }
225};
226
227enum trimpot_model {
228	AD7376,
229	AD8402,
230};
231
232struct cb_pcidas_board {
233	const char *name;
234	unsigned short device_id;
235	int ai_nchan;		/*  Inputs in single-ended mode */
236	int ai_bits;		/*  analog input resolution */
237	int ai_speed;		/*  fastest conversion period in ns */
238	int ao_nchan;		/*  number of analog out channels */
239	int has_ao_fifo;	/*  analog output has fifo */
240	int ao_scan_speed;	/*  analog output scan speed for 1602 series */
241	int fifo_size;		/*  number of samples fifo can hold */
242	const struct comedi_lrange *ranges;
243	enum trimpot_model trimpot;
244	unsigned has_dac08:1;
245	unsigned is_1602:1;
246};
247
248static const struct cb_pcidas_board cb_pcidas_boards[] = {
249	{
250		.name		= "pci-das1602/16",
251		.device_id	= 0x1,
252		.ai_nchan	= 16,
253		.ai_bits	= 16,
254		.ai_speed	= 5000,
255		.ao_nchan	= 2,
256		.has_ao_fifo	= 1,
257		.ao_scan_speed	= 10000,
258		.fifo_size	= 512,
259		.ranges		= &cb_pcidas_ranges,
260		.trimpot	= AD8402,
261		.has_dac08	= 1,
262		.is_1602	= 1,
263	}, {
264		.name		= "pci-das1200",
265		.device_id	= 0xF,
266		.ai_nchan	= 16,
267		.ai_bits	= 12,
268		.ai_speed	= 3200,
269		.ao_nchan	= 2,
270		.fifo_size	= 1024,
271		.ranges		= &cb_pcidas_ranges,
272		.trimpot	= AD7376,
273	}, {
274		.name		= "pci-das1602/12",
275		.device_id	= 0x10,
276		.ai_nchan	= 16,
277		.ai_bits	= 12,
278		.ai_speed	= 3200,
279		.ao_nchan	= 2,
280		.has_ao_fifo	= 1,
281		.ao_scan_speed	= 4000,
282		.fifo_size	= 1024,
283		.ranges		= &cb_pcidas_ranges,
284		.trimpot	= AD7376,
285		.is_1602	= 1,
286	}, {
287		.name		= "pci-das1200/jr",
288		.device_id	= 0x19,
289		.ai_nchan	= 16,
290		.ai_bits	= 12,
291		.ai_speed	= 3200,
292		.fifo_size	= 1024,
293		.ranges		= &cb_pcidas_ranges,
294		.trimpot	= AD7376,
295	}, {
296		.name		= "pci-das1602/16/jr",
297		.device_id	= 0x1C,
298		.ai_nchan	= 16,
299		.ai_bits	= 16,
300		.ai_speed	= 5000,
301		.fifo_size	= 512,
302		.ranges		= &cb_pcidas_ranges,
303		.trimpot	= AD8402,
304		.has_dac08	= 1,
305		.is_1602	= 1,
306	}, {
307		.name		= "pci-das1000",
308		.device_id	= 0x4C,
309		.ai_nchan	= 16,
310		.ai_bits	= 12,
311		.ai_speed	= 4000,
312		.fifo_size	= 1024,
313		.ranges		= &cb_pcidas_ranges,
314		.trimpot	= AD7376,
315	}, {
316		.name		= "pci-das1001",
317		.device_id	= 0x1a,
318		.ai_nchan	= 16,
319		.ai_bits	= 12,
320		.ai_speed	= 6800,
321		.ao_nchan	= 2,
322		.fifo_size	= 1024,
323		.ranges		= &cb_pcidas_alt_ranges,
324		.trimpot	= AD7376,
325	}, {
326		.name		= "pci-das1002",
327		.device_id	= 0x1b,
328		.ai_nchan	= 16,
329		.ai_bits	= 12,
330		.ai_speed	= 6800,
331		.ao_nchan	= 2,
332		.fifo_size	= 1024,
333		.ranges		= &cb_pcidas_ranges,
334		.trimpot	= AD7376,
335	},
336};
337
338struct cb_pcidas_private {
339	/* base addresses */
340	unsigned long s5933_config;
341	unsigned long control_status;
342	unsigned long adc_fifo;
343	unsigned long pacer_counter_dio;
344	unsigned long ao_registers;
345	/* divisors of master clock for analog input pacing */
346	unsigned int divisor1;
347	unsigned int divisor2;
348	/* number of analog input samples remaining */
349	unsigned int count;
350	/* bits to write to registers */
351	unsigned int adc_fifo_bits;
352	unsigned int s5933_intcsr_bits;
353	unsigned int ao_control_bits;
354	/* fifo buffers */
355	short ai_buffer[AI_BUFFER_SIZE];
356	short ao_buffer[AO_BUFFER_SIZE];
357	/* divisors of master clock for analog output pacing */
358	unsigned int ao_divisor1;
359	unsigned int ao_divisor2;
360	/* number of analog output samples remaining */
361	unsigned int ao_count;
362	/* cached values for readback */
363	int ao_value[2];
364	unsigned int caldac_value[NUM_CHANNELS_8800];
365	unsigned int trimpot_value[NUM_CHANNELS_8402];
366	unsigned int dac08_value;
367	unsigned int calibration_source;
368};
369
370static inline unsigned int cal_enable_bits(struct comedi_device *dev)
371{
372	struct cb_pcidas_private *devpriv = dev->private;
373
374	return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
375}
376
377static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
378			      struct comedi_subdevice *s,
379			      struct comedi_insn *insn, unsigned int *data)
380{
381	struct cb_pcidas_private *devpriv = dev->private;
382	unsigned int chan = CR_CHAN(insn->chanspec);
383	unsigned int range = CR_RANGE(insn->chanspec);
384	unsigned int aref = CR_AREF(insn->chanspec);
385	unsigned int bits;
386	int n, i;
387
388	/* enable calibration input if appropriate */
389	if (insn->chanspec & CR_ALT_SOURCE) {
390		outw(cal_enable_bits(dev),
391		     devpriv->control_status + CALIBRATION_REG);
392		chan = 0;
393	} else {
394		outw(0, devpriv->control_status + CALIBRATION_REG);
395	}
396
397	/* set mux limits and gain */
398	bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range);
399	/* set unipolar/bipolar */
400	if (range & IS_UNIPOLAR)
401		bits |= UNIP;
402	/* set single-ended/differential */
403	if (aref != AREF_DIFF)
404		bits |= SE;
405	outw(bits, devpriv->control_status + ADCMUX_CONT);
406
407	/* clear fifo */
408	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
409
410	/* convert n samples */
411	for (n = 0; n < insn->n; n++) {
412		/* trigger conversion */
413		outw(0, devpriv->adc_fifo + ADCDATA);
414
415		/* wait for conversion to end */
416		/* return -ETIMEDOUT if there is a timeout */
417		for (i = 0; i < 10000; i++) {
418			if (inw(devpriv->control_status + ADCMUX_CONT) & EOC)
419				break;
420		}
421		if (i == 10000)
422			return -ETIMEDOUT;
423
424		/* read data */
425		data[n] = inw(devpriv->adc_fifo + ADCDATA);
426	}
427
428	/* return the number of samples read/written */
429	return n;
430}
431
432static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
433			  struct comedi_insn *insn, unsigned int *data)
434{
435	struct cb_pcidas_private *devpriv = dev->private;
436	int id = data[0];
437	unsigned int source = data[1];
438
439	switch (id) {
440	case INSN_CONFIG_ALT_SOURCE:
441		if (source >= 8) {
442			dev_err(dev->class_dev,
443				"invalid calibration source: %i\n",
444				source);
445			return -EINVAL;
446		}
447		devpriv->calibration_source = source;
448		break;
449	default:
450		return -EINVAL;
451		break;
452	}
453	return insn->n;
454}
455
456/* analog output insn for pcidas-1000 and 1200 series */
457static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
458				     struct comedi_subdevice *s,
459				     struct comedi_insn *insn,
460				     unsigned int *data)
461{
462	struct cb_pcidas_private *devpriv = dev->private;
463	unsigned int chan = CR_CHAN(insn->chanspec);
464	unsigned int range = CR_RANGE(insn->chanspec);
465	unsigned long flags;
466
467	/* set channel and range */
468	spin_lock_irqsave(&dev->spinlock, flags);
469	devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH &
470				     ~DAC_RANGE_MASK(chan));
471	devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range));
472	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
473	spin_unlock_irqrestore(&dev->spinlock, flags);
474
475	/* remember value for readback */
476	devpriv->ao_value[chan] = data[0];
477
478	/* send data */
479	outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan));
480
481	return insn->n;
482}
483
484/* analog output insn for pcidas-1602 series */
485static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
486				   struct comedi_subdevice *s,
487				   struct comedi_insn *insn, unsigned int *data)
488{
489	struct cb_pcidas_private *devpriv = dev->private;
490	unsigned int chan = CR_CHAN(insn->chanspec);
491	unsigned int range = CR_RANGE(insn->chanspec);
492	unsigned long flags;
493
494	/* clear dac fifo */
495	outw(0, devpriv->ao_registers + DACFIFOCLR);
496
497	/* set channel and range */
498	spin_lock_irqsave(&dev->spinlock, flags);
499	devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) &
500				     ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK);
501	devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) |
502				     DAC_CHAN_EN(chan) | DAC_START);
503	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
504	spin_unlock_irqrestore(&dev->spinlock, flags);
505
506	/* remember value for readback */
507	devpriv->ao_value[chan] = data[0];
508
509	/* send data */
510	outw(data[0], devpriv->ao_registers + DACDATA);
511
512	return insn->n;
513}
514
515static int cb_pcidas_ao_readback_insn(struct comedi_device *dev,
516				      struct comedi_subdevice *s,
517				      struct comedi_insn *insn,
518				      unsigned int *data)
519{
520	struct cb_pcidas_private *devpriv = dev->private;
521
522	data[0] = devpriv->ao_value[CR_CHAN(insn->chanspec)];
523
524	return 1;
525}
526
527static int wait_for_nvram_ready(unsigned long s5933_base_addr)
528{
529	static const int timeout = 1000;
530	unsigned int i;
531
532	for (i = 0; i < timeout; i++) {
533		if ((inb(s5933_base_addr +
534			 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
535		    == 0)
536			return 0;
537		udelay(1);
538	}
539	return -1;
540}
541
542static int nvram_read(struct comedi_device *dev, unsigned int address,
543			uint8_t *data)
544{
545	struct cb_pcidas_private *devpriv = dev->private;
546	unsigned long iobase = devpriv->s5933_config;
547
548	if (wait_for_nvram_ready(iobase) < 0)
549		return -ETIMEDOUT;
550
551	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
552	     iobase + AMCC_OP_REG_MCSR_NVCMD);
553	outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
554	outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
555	     iobase + AMCC_OP_REG_MCSR_NVCMD);
556	outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
557	outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
558
559	if (wait_for_nvram_ready(iobase) < 0)
560		return -ETIMEDOUT;
561
562	*data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
563
564	return 0;
565}
566
567static int eeprom_read_insn(struct comedi_device *dev,
568			    struct comedi_subdevice *s,
569			    struct comedi_insn *insn, unsigned int *data)
570{
571	uint8_t nvram_data;
572	int retval;
573
574	retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
575	if (retval < 0)
576		return retval;
577
578	data[0] = nvram_data;
579
580	return 1;
581}
582
583static void write_calibration_bitstream(struct comedi_device *dev,
584					unsigned int register_bits,
585					unsigned int bitstream,
586					unsigned int bitstream_length)
587{
588	struct cb_pcidas_private *devpriv = dev->private;
589	static const int write_delay = 1;
590	unsigned int bit;
591
592	for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
593		if (bitstream & bit)
594			register_bits |= SERIAL_DATA_IN_BIT;
595		else
596			register_bits &= ~SERIAL_DATA_IN_BIT;
597		udelay(write_delay);
598		outw(register_bits, devpriv->control_status + CALIBRATION_REG);
599	}
600}
601
602static int caldac_8800_write(struct comedi_device *dev, unsigned int address,
603			     uint8_t value)
604{
605	struct cb_pcidas_private *devpriv = dev->private;
606	static const int num_caldac_channels = 8;
607	static const int bitstream_length = 11;
608	unsigned int bitstream = ((address & 0x7) << 8) | value;
609	static const int caldac_8800_udelay = 1;
610
611	if (address >= num_caldac_channels) {
612		comedi_error(dev, "illegal caldac channel");
613		return -1;
614	}
615
616	if (value == devpriv->caldac_value[address])
617		return 1;
618
619	devpriv->caldac_value[address] = value;
620
621	write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
622				    bitstream_length);
623
624	udelay(caldac_8800_udelay);
625	outw(cal_enable_bits(dev) | SELECT_8800_BIT,
626	     devpriv->control_status + CALIBRATION_REG);
627	udelay(caldac_8800_udelay);
628	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
629
630	return 1;
631}
632
633static int caldac_write_insn(struct comedi_device *dev,
634			     struct comedi_subdevice *s,
635			     struct comedi_insn *insn, unsigned int *data)
636{
637	const unsigned int channel = CR_CHAN(insn->chanspec);
638
639	return caldac_8800_write(dev, channel, data[0]);
640}
641
642static int caldac_read_insn(struct comedi_device *dev,
643			    struct comedi_subdevice *s,
644			    struct comedi_insn *insn, unsigned int *data)
645{
646	struct cb_pcidas_private *devpriv = dev->private;
647
648	data[0] = devpriv->caldac_value[CR_CHAN(insn->chanspec)];
649
650	return 1;
651}
652
653/* 1602/16 pregain offset */
654static void dac08_write(struct comedi_device *dev, unsigned int value)
655{
656	struct cb_pcidas_private *devpriv = dev->private;
657	unsigned long cal_reg;
658
659	if (devpriv->dac08_value != value) {
660		devpriv->dac08_value = value;
661
662		cal_reg = devpriv->control_status + CALIBRATION_REG;
663
664		value &= 0xff;
665		value |= cal_enable_bits(dev);
666
667		/* latch the new value into the caldac */
668		outw(value, cal_reg);
669		udelay(1);
670		outw(value | SELECT_DAC08_BIT, cal_reg);
671		udelay(1);
672		outw(value, cal_reg);
673		udelay(1);
674	}
675}
676
677static int dac08_write_insn(struct comedi_device *dev,
678			    struct comedi_subdevice *s,
679			    struct comedi_insn *insn, unsigned int *data)
680{
681	int i;
682
683	for (i = 0; i < insn->n; i++)
684		dac08_write(dev, data[i]);
685
686	return insn->n;
687}
688
689static int dac08_read_insn(struct comedi_device *dev,
690			   struct comedi_subdevice *s, struct comedi_insn *insn,
691			   unsigned int *data)
692{
693	struct cb_pcidas_private *devpriv = dev->private;
694
695	data[0] = devpriv->dac08_value;
696
697	return 1;
698}
699
700static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
701{
702	struct cb_pcidas_private *devpriv = dev->private;
703	static const int bitstream_length = 7;
704	unsigned int bitstream = value & 0x7f;
705	unsigned int register_bits;
706	static const int ad7376_udelay = 1;
707
708	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
709	udelay(ad7376_udelay);
710	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
711
712	write_calibration_bitstream(dev, register_bits, bitstream,
713				    bitstream_length);
714
715	udelay(ad7376_udelay);
716	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
717
718	return 0;
719}
720
721/* For 1602/16 only
722 * ch 0 : adc gain
723 * ch 1 : adc postgain offset */
724static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
725			      uint8_t value)
726{
727	struct cb_pcidas_private *devpriv = dev->private;
728	static const int bitstream_length = 10;
729	unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
730	unsigned int register_bits;
731	static const int ad8402_udelay = 1;
732
733	register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
734	udelay(ad8402_udelay);
735	outw(register_bits, devpriv->control_status + CALIBRATION_REG);
736
737	write_calibration_bitstream(dev, register_bits, bitstream,
738				    bitstream_length);
739
740	udelay(ad8402_udelay);
741	outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
742
743	return 0;
744}
745
746static int cb_pcidas_trimpot_write(struct comedi_device *dev,
747				   unsigned int channel, unsigned int value)
748{
749	const struct cb_pcidas_board *thisboard = comedi_board(dev);
750	struct cb_pcidas_private *devpriv = dev->private;
751
752	if (devpriv->trimpot_value[channel] == value)
753		return 1;
754
755	devpriv->trimpot_value[channel] = value;
756	switch (thisboard->trimpot) {
757	case AD7376:
758		trimpot_7376_write(dev, value);
759		break;
760	case AD8402:
761		trimpot_8402_write(dev, channel, value);
762		break;
763	default:
764		comedi_error(dev, "driver bug?");
765		return -1;
766		break;
767	}
768
769	return 1;
770}
771
772static int trimpot_write_insn(struct comedi_device *dev,
773			      struct comedi_subdevice *s,
774			      struct comedi_insn *insn, unsigned int *data)
775{
776	unsigned int channel = CR_CHAN(insn->chanspec);
777
778	return cb_pcidas_trimpot_write(dev, channel, data[0]);
779}
780
781static int trimpot_read_insn(struct comedi_device *dev,
782			     struct comedi_subdevice *s,
783			     struct comedi_insn *insn, unsigned int *data)
784{
785	struct cb_pcidas_private *devpriv = dev->private;
786	unsigned int channel = CR_CHAN(insn->chanspec);
787
788	data[0] = devpriv->trimpot_value[channel];
789
790	return 1;
791}
792
793static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
794				struct comedi_subdevice *s,
795				struct comedi_cmd *cmd)
796{
797	const struct cb_pcidas_board *thisboard = comedi_board(dev);
798	struct cb_pcidas_private *devpriv = dev->private;
799	int err = 0;
800	int tmp;
801	int i, gain, start_chan;
802
803	/* Step 1 : check if triggers are trivially valid */
804
805	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
806	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
807					TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
808	err |= cfc_check_trigger_src(&cmd->convert_src,
809					TRIG_TIMER | TRIG_NOW | TRIG_EXT);
810	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
811	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
812
813	if (err)
814		return 1;
815
816	/* Step 2a : make sure trigger sources are unique */
817
818	err |= cfc_check_trigger_is_unique(cmd->start_src);
819	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
820	err |= cfc_check_trigger_is_unique(cmd->convert_src);
821	err |= cfc_check_trigger_is_unique(cmd->stop_src);
822
823	/* Step 2b : and mutually compatible */
824
825	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
826		err |= -EINVAL;
827	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
828		err |= -EINVAL;
829	if (cmd->start_src == TRIG_EXT &&
830	    (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
831		err |= -EINVAL;
832
833	if (err)
834		return 2;
835
836	/* step 3: arguments are trivially compatible */
837
838	switch (cmd->start_src) {
839	case TRIG_EXT:
840		/* External trigger, only CR_EDGE and CR_INVERT flags allowed */
841		if ((cmd->start_arg
842		     & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
843			cmd->start_arg &= ~(CR_FLAGS_MASK &
844						~(CR_EDGE | CR_INVERT));
845			err |= -EINVAL;
846		}
847		if (!thisboard->is_1602 && (cmd->start_arg & CR_INVERT)) {
848			cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
849			err |= -EINVAL;
850		}
851		break;
852	default:
853		err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
854		break;
855	}
856
857	if (cmd->scan_begin_src == TRIG_TIMER)
858		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
859				thisboard->ai_speed * cmd->chanlist_len);
860
861	if (cmd->convert_src == TRIG_TIMER)
862		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
863						 thisboard->ai_speed);
864
865	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
866
867	if (cmd->stop_src == TRIG_NONE)
868		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
869
870	if (err)
871		return 3;
872
873	/* step 4: fix up any arguments */
874
875	if (cmd->scan_begin_src == TRIG_TIMER) {
876		tmp = cmd->scan_begin_arg;
877		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
878					       &(devpriv->divisor1),
879					       &(devpriv->divisor2),
880					       &(cmd->scan_begin_arg),
881					       cmd->flags & TRIG_ROUND_MASK);
882		if (tmp != cmd->scan_begin_arg)
883			err++;
884	}
885	if (cmd->convert_src == TRIG_TIMER) {
886		tmp = cmd->convert_arg;
887		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
888					       &(devpriv->divisor1),
889					       &(devpriv->divisor2),
890					       &(cmd->convert_arg),
891					       cmd->flags & TRIG_ROUND_MASK);
892		if (tmp != cmd->convert_arg)
893			err++;
894	}
895
896	if (err)
897		return 4;
898
899	/*  check channel/gain list against card's limitations */
900	if (cmd->chanlist) {
901		gain = CR_RANGE(cmd->chanlist[0]);
902		start_chan = CR_CHAN(cmd->chanlist[0]);
903		for (i = 1; i < cmd->chanlist_len; i++) {
904			if (CR_CHAN(cmd->chanlist[i]) !=
905			    (start_chan + i) % s->n_chan) {
906				comedi_error(dev,
907					     "entries in chanlist must be consecutive channels, counting upwards\n");
908				err++;
909			}
910			if (CR_RANGE(cmd->chanlist[i]) != gain) {
911				comedi_error(dev,
912					     "entries in chanlist must all have the same gain\n");
913				err++;
914			}
915		}
916	}
917
918	if (err)
919		return 5;
920
921	return 0;
922}
923
924static void cb_pcidas_load_counters(struct comedi_device *dev, unsigned int *ns,
925				    int rounding_flags)
926{
927	struct cb_pcidas_private *devpriv = dev->private;
928
929	i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
930				       &(devpriv->divisor2), ns,
931				       rounding_flags & TRIG_ROUND_MASK);
932
933	/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
934	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 1,
935		   devpriv->divisor1, 2);
936	i8254_load(devpriv->pacer_counter_dio + ADC8254, 0, 2,
937		   devpriv->divisor2, 2);
938}
939
940static int cb_pcidas_ai_cmd(struct comedi_device *dev,
941			    struct comedi_subdevice *s)
942{
943	const struct cb_pcidas_board *thisboard = comedi_board(dev);
944	struct cb_pcidas_private *devpriv = dev->private;
945	struct comedi_async *async = s->async;
946	struct comedi_cmd *cmd = &async->cmd;
947	unsigned int bits;
948	unsigned long flags;
949
950	/*  make sure CAL_EN_BIT is disabled */
951	outw(0, devpriv->control_status + CALIBRATION_REG);
952	/*  initialize before settings pacer source and count values */
953	outw(0, devpriv->control_status + TRIG_CONTSTAT);
954	/*  clear fifo */
955	outw(0, devpriv->adc_fifo + ADCFIFOCLR);
956
957	/*  set mux limits, gain and pacer source */
958	bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
959	    END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
960	    GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
961	/*  set unipolar/bipolar */
962	if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
963		bits |= UNIP;
964	/*  set singleended/differential */
965	if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
966		bits |= SE;
967	/*  set pacer source */
968	if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
969		bits |= PACER_EXT_RISE;
970	else
971		bits |= PACER_INT;
972	outw(bits, devpriv->control_status + ADCMUX_CONT);
973
974	/*  load counters */
975	if (cmd->convert_src == TRIG_TIMER)
976		cb_pcidas_load_counters(dev, &cmd->convert_arg,
977					cmd->flags & TRIG_ROUND_MASK);
978	else if (cmd->scan_begin_src == TRIG_TIMER)
979		cb_pcidas_load_counters(dev, &cmd->scan_begin_arg,
980					cmd->flags & TRIG_ROUND_MASK);
981
982	/*  set number of conversions */
983	if (cmd->stop_src == TRIG_COUNT)
984		devpriv->count = cmd->chanlist_len * cmd->stop_arg;
985	/*  enable interrupts */
986	spin_lock_irqsave(&dev->spinlock, flags);
987	devpriv->adc_fifo_bits |= INTE;
988	devpriv->adc_fifo_bits &= ~INT_MASK;
989	if (cmd->flags & TRIG_WAKE_EOS) {
990		if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
991			/* interrupt end of burst */
992			devpriv->adc_fifo_bits |= INT_EOS;
993		} else {
994			/* interrupt fifo not empty */
995			devpriv->adc_fifo_bits |= INT_FNE;
996		}
997	} else {
998		/* interrupt fifo half full */
999		devpriv->adc_fifo_bits |= INT_FHF;
1000	}
1001
1002	/*  enable (and clear) interrupts */
1003	outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
1004	     devpriv->control_status + INT_ADCFIFO);
1005	spin_unlock_irqrestore(&dev->spinlock, flags);
1006
1007	/*  set start trigger and burst mode */
1008	bits = 0;
1009	if (cmd->start_src == TRIG_NOW)
1010		bits |= SW_TRIGGER;
1011	else if (cmd->start_src == TRIG_EXT) {
1012		bits |= EXT_TRIGGER | TGEN | XTRCL;
1013		if (thisboard->is_1602) {
1014			if (cmd->start_arg & CR_INVERT)
1015				bits |= TGPOL;
1016			if (cmd->start_arg & CR_EDGE)
1017				bits |= TGSEL;
1018		}
1019	} else {
1020		comedi_error(dev, "bug!");
1021		return -1;
1022	}
1023	if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
1024		bits |= BURSTE;
1025	outw(bits, devpriv->control_status + TRIG_CONTSTAT);
1026
1027	return 0;
1028}
1029
1030static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
1031				struct comedi_subdevice *s,
1032				struct comedi_cmd *cmd)
1033{
1034	const struct cb_pcidas_board *thisboard = comedi_board(dev);
1035	struct cb_pcidas_private *devpriv = dev->private;
1036	int err = 0;
1037	int tmp;
1038
1039	/* Step 1 : check if triggers are trivially valid */
1040
1041	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
1042	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
1043					TRIG_TIMER | TRIG_EXT);
1044	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
1045	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1046	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1047
1048	if (err)
1049		return 1;
1050
1051	/* Step 2a : make sure trigger sources are unique */
1052
1053	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1054	err |= cfc_check_trigger_is_unique(cmd->stop_src);
1055
1056	/* Step 2b : and mutually compatible */
1057
1058	if (err)
1059		return 2;
1060
1061	/* Step 3: check if arguments are trivially valid */
1062
1063	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1064
1065	if (cmd->scan_begin_src == TRIG_TIMER)
1066		err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1067						 thisboard->ao_scan_speed);
1068
1069	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1070
1071	if (cmd->stop_src == TRIG_NONE)
1072		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1073
1074	if (err)
1075		return 3;
1076
1077	/* step 4: fix up any arguments */
1078
1079	if (cmd->scan_begin_src == TRIG_TIMER) {
1080		tmp = cmd->scan_begin_arg;
1081		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1082					       &(devpriv->ao_divisor1),
1083					       &(devpriv->ao_divisor2),
1084					       &(cmd->scan_begin_arg),
1085					       cmd->flags & TRIG_ROUND_MASK);
1086		if (tmp != cmd->scan_begin_arg)
1087			err++;
1088	}
1089
1090	if (err)
1091		return 4;
1092
1093	/*  check channel/gain list against card's limitations */
1094	if (cmd->chanlist && cmd->chanlist_len > 1) {
1095		if (CR_CHAN(cmd->chanlist[0]) != 0 ||
1096		    CR_CHAN(cmd->chanlist[1]) != 1) {
1097			comedi_error(dev,
1098				     "channels must be ordered channel 0, channel 1 in chanlist\n");
1099			err++;
1100		}
1101	}
1102
1103	if (err)
1104		return 5;
1105
1106	return 0;
1107}
1108
1109/* cancel analog input command */
1110static int cb_pcidas_cancel(struct comedi_device *dev,
1111			    struct comedi_subdevice *s)
1112{
1113	struct cb_pcidas_private *devpriv = dev->private;
1114	unsigned long flags;
1115
1116	spin_lock_irqsave(&dev->spinlock, flags);
1117	/*  disable interrupts */
1118	devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1119	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1120	spin_unlock_irqrestore(&dev->spinlock, flags);
1121
1122	/*  disable start trigger source and burst mode */
1123	outw(0, devpriv->control_status + TRIG_CONTSTAT);
1124	/*  software pacer source */
1125	outw(0, devpriv->control_status + ADCMUX_CONT);
1126
1127	return 0;
1128}
1129
1130static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1131				struct comedi_subdevice *s,
1132				unsigned int trig_num)
1133{
1134	const struct cb_pcidas_board *thisboard = comedi_board(dev);
1135	struct cb_pcidas_private *devpriv = dev->private;
1136	unsigned int num_bytes, num_points = thisboard->fifo_size;
1137	struct comedi_async *async = s->async;
1138	struct comedi_cmd *cmd = &s->async->cmd;
1139	unsigned long flags;
1140
1141	if (trig_num != 0)
1142		return -EINVAL;
1143
1144	/*  load up fifo */
1145	if (cmd->stop_src == TRIG_COUNT && devpriv->ao_count < num_points)
1146		num_points = devpriv->ao_count;
1147
1148	num_bytes = cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1149					       num_points * sizeof(short));
1150	num_points = num_bytes / sizeof(short);
1151
1152	if (cmd->stop_src == TRIG_COUNT)
1153		devpriv->ao_count -= num_points;
1154	/*  write data to board's fifo */
1155	outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, num_bytes);
1156
1157	/*  enable dac half-full and empty interrupts */
1158	spin_lock_irqsave(&dev->spinlock, flags);
1159	devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
1160
1161	/*  enable and clear interrupts */
1162	outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
1163	     devpriv->control_status + INT_ADCFIFO);
1164
1165	/*  start dac */
1166	devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
1167	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1168
1169	spin_unlock_irqrestore(&dev->spinlock, flags);
1170
1171	async->inttrig = NULL;
1172
1173	return 0;
1174}
1175
1176static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1177			    struct comedi_subdevice *s)
1178{
1179	struct cb_pcidas_private *devpriv = dev->private;
1180	struct comedi_async *async = s->async;
1181	struct comedi_cmd *cmd = &async->cmd;
1182	unsigned int i;
1183	unsigned long flags;
1184
1185	/*  set channel limits, gain */
1186	spin_lock_irqsave(&dev->spinlock, flags);
1187	for (i = 0; i < cmd->chanlist_len; i++) {
1188		/*  enable channel */
1189		devpriv->ao_control_bits |=
1190		    DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1191		/*  set range */
1192		devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
1193						      CR_RANGE(cmd->
1194							       chanlist[i]));
1195	}
1196
1197	/*  disable analog out before settings pacer source and count values */
1198	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1199	spin_unlock_irqrestore(&dev->spinlock, flags);
1200
1201	/*  clear fifo */
1202	outw(0, devpriv->ao_registers + DACFIFOCLR);
1203
1204	/*  load counters */
1205	if (cmd->scan_begin_src == TRIG_TIMER) {
1206		i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1207					       &(devpriv->ao_divisor1),
1208					       &(devpriv->ao_divisor2),
1209					       &(cmd->scan_begin_arg),
1210					       cmd->flags);
1211
1212		/* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1213		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 1,
1214			   devpriv->ao_divisor1, 2);
1215		i8254_load(devpriv->pacer_counter_dio + DAC8254, 0, 2,
1216			   devpriv->ao_divisor2, 2);
1217	}
1218	/*  set number of conversions */
1219	if (cmd->stop_src == TRIG_COUNT)
1220		devpriv->ao_count = cmd->chanlist_len * cmd->stop_arg;
1221	/*  set pacer source */
1222	spin_lock_irqsave(&dev->spinlock, flags);
1223	switch (cmd->scan_begin_src) {
1224	case TRIG_TIMER:
1225		devpriv->ao_control_bits |= DAC_PACER_INT;
1226		break;
1227	case TRIG_EXT:
1228		devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1229		break;
1230	default:
1231		spin_unlock_irqrestore(&dev->spinlock, flags);
1232		comedi_error(dev, "error setting dac pacer source");
1233		return -1;
1234		break;
1235	}
1236	spin_unlock_irqrestore(&dev->spinlock, flags);
1237
1238	async->inttrig = cb_pcidas_ao_inttrig;
1239
1240	return 0;
1241}
1242
1243/* cancel analog output command */
1244static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1245			       struct comedi_subdevice *s)
1246{
1247	struct cb_pcidas_private *devpriv = dev->private;
1248	unsigned long flags;
1249
1250	spin_lock_irqsave(&dev->spinlock, flags);
1251	/*  disable interrupts */
1252	devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1253	outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1254
1255	/*  disable output */
1256	devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1257	outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1258	spin_unlock_irqrestore(&dev->spinlock, flags);
1259
1260	return 0;
1261}
1262
1263static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
1264{
1265	const struct cb_pcidas_board *thisboard = comedi_board(dev);
1266	struct cb_pcidas_private *devpriv = dev->private;
1267	struct comedi_subdevice *s = dev->write_subdev;
1268	struct comedi_async *async = s->async;
1269	struct comedi_cmd *cmd = &async->cmd;
1270	unsigned int half_fifo = thisboard->fifo_size / 2;
1271	unsigned int num_points;
1272	unsigned long flags;
1273
1274	async->events = 0;
1275
1276	if (status & DAEMI) {
1277		/*  clear dac empty interrupt latch */
1278		spin_lock_irqsave(&dev->spinlock, flags);
1279		outw(devpriv->adc_fifo_bits | DAEMI,
1280		     devpriv->control_status + INT_ADCFIFO);
1281		spin_unlock_irqrestore(&dev->spinlock, flags);
1282		if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1283			if (cmd->stop_src == TRIG_NONE ||
1284			    (cmd->stop_src == TRIG_COUNT
1285			     && devpriv->ao_count)) {
1286				comedi_error(dev, "dac fifo underflow");
1287				cb_pcidas_ao_cancel(dev, s);
1288				async->events |= COMEDI_CB_ERROR;
1289			}
1290			async->events |= COMEDI_CB_EOA;
1291		}
1292	} else if (status & DAHFI) {
1293		unsigned int num_bytes;
1294
1295		/*  figure out how many points we are writing to fifo */
1296		num_points = half_fifo;
1297		if (cmd->stop_src == TRIG_COUNT &&
1298		    devpriv->ao_count < num_points)
1299			num_points = devpriv->ao_count;
1300		num_bytes =
1301		    cfc_read_array_from_buffer(s, devpriv->ao_buffer,
1302					       num_points * sizeof(short));
1303		num_points = num_bytes / sizeof(short);
1304
1305		if (async->cmd.stop_src == TRIG_COUNT)
1306			devpriv->ao_count -= num_points;
1307		/*  write data to board's fifo */
1308		outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer,
1309		      num_points);
1310		/*  clear half-full interrupt latch */
1311		spin_lock_irqsave(&dev->spinlock, flags);
1312		outw(devpriv->adc_fifo_bits | DAHFI,
1313		     devpriv->control_status + INT_ADCFIFO);
1314		spin_unlock_irqrestore(&dev->spinlock, flags);
1315	}
1316
1317	comedi_event(dev, s);
1318}
1319
1320static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1321{
1322	struct comedi_device *dev = (struct comedi_device *)d;
1323	const struct cb_pcidas_board *thisboard = comedi_board(dev);
1324	struct cb_pcidas_private *devpriv = dev->private;
1325	struct comedi_subdevice *s = dev->read_subdev;
1326	struct comedi_async *async;
1327	int status, s5933_status;
1328	int half_fifo = thisboard->fifo_size / 2;
1329	unsigned int num_samples, i;
1330	static const int timeout = 10000;
1331	unsigned long flags;
1332
1333	if (dev->attached == 0)
1334		return IRQ_NONE;
1335
1336	async = s->async;
1337	async->events = 0;
1338
1339	s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1340
1341	if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1342		return IRQ_NONE;
1343
1344	/*  make sure mailbox 4 is empty */
1345	inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1346	/*  clear interrupt on amcc s5933 */
1347	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1348	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1349
1350	status = inw(devpriv->control_status + INT_ADCFIFO);
1351
1352	/*  check for analog output interrupt */
1353	if (status & (DAHFI | DAEMI))
1354		handle_ao_interrupt(dev, status);
1355	/*  check for analog input interrupts */
1356	/*  if fifo half-full */
1357	if (status & ADHFI) {
1358		/*  read data */
1359		num_samples = half_fifo;
1360		if (async->cmd.stop_src == TRIG_COUNT &&
1361		    num_samples > devpriv->count) {
1362			num_samples = devpriv->count;
1363		}
1364		insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
1365		     num_samples);
1366		cfc_write_array_to_buffer(s, devpriv->ai_buffer,
1367					  num_samples * sizeof(short));
1368		devpriv->count -= num_samples;
1369		if (async->cmd.stop_src == TRIG_COUNT && devpriv->count == 0) {
1370			async->events |= COMEDI_CB_EOA;
1371			cb_pcidas_cancel(dev, s);
1372		}
1373		/*  clear half-full interrupt latch */
1374		spin_lock_irqsave(&dev->spinlock, flags);
1375		outw(devpriv->adc_fifo_bits | INT,
1376		     devpriv->control_status + INT_ADCFIFO);
1377		spin_unlock_irqrestore(&dev->spinlock, flags);
1378		/*  else if fifo not empty */
1379	} else if (status & (ADNEI | EOBI)) {
1380		for (i = 0; i < timeout; i++) {
1381			/*  break if fifo is empty */
1382			if ((ADNE & inw(devpriv->control_status +
1383					INT_ADCFIFO)) == 0)
1384				break;
1385			cfc_write_to_buffer(s, inw(devpriv->adc_fifo));
1386			if (async->cmd.stop_src == TRIG_COUNT &&
1387			    --devpriv->count == 0) {
1388				/* end of acquisition */
1389				cb_pcidas_cancel(dev, s);
1390				async->events |= COMEDI_CB_EOA;
1391				break;
1392			}
1393		}
1394		/*  clear not-empty interrupt latch */
1395		spin_lock_irqsave(&dev->spinlock, flags);
1396		outw(devpriv->adc_fifo_bits | INT,
1397		     devpriv->control_status + INT_ADCFIFO);
1398		spin_unlock_irqrestore(&dev->spinlock, flags);
1399	} else if (status & EOAI) {
1400		comedi_error(dev,
1401			     "bug! encountered end of acquisition interrupt?");
1402		/*  clear EOA interrupt latch */
1403		spin_lock_irqsave(&dev->spinlock, flags);
1404		outw(devpriv->adc_fifo_bits | EOAI,
1405		     devpriv->control_status + INT_ADCFIFO);
1406		spin_unlock_irqrestore(&dev->spinlock, flags);
1407	}
1408	/* check for fifo overflow */
1409	if (status & LADFUL) {
1410		comedi_error(dev, "fifo overflow");
1411		/*  clear overflow interrupt latch */
1412		spin_lock_irqsave(&dev->spinlock, flags);
1413		outw(devpriv->adc_fifo_bits | LADFUL,
1414		     devpriv->control_status + INT_ADCFIFO);
1415		spin_unlock_irqrestore(&dev->spinlock, flags);
1416		cb_pcidas_cancel(dev, s);
1417		async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
1418	}
1419
1420	comedi_event(dev, s);
1421
1422	return IRQ_HANDLED;
1423}
1424
1425static const void *cb_pcidas_find_boardinfo(struct comedi_device *dev,
1426					    struct pci_dev *pcidev)
1427{
1428	const struct cb_pcidas_board *thisboard;
1429	int i;
1430
1431	for (i = 0; i < ARRAY_SIZE(cb_pcidas_boards); i++) {
1432		thisboard = &cb_pcidas_boards[i];
1433		if (thisboard->device_id == pcidev->device)
1434			return thisboard;
1435	}
1436	return NULL;
1437}
1438
1439static int cb_pcidas_auto_attach(struct comedi_device *dev,
1440					   unsigned long context_unused)
1441{
1442	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1443	const struct cb_pcidas_board *thisboard;
1444	struct cb_pcidas_private *devpriv;
1445	struct comedi_subdevice *s;
1446	int i;
1447	int ret;
1448
1449	thisboard = cb_pcidas_find_boardinfo(dev, pcidev);
1450	if (!thisboard)
1451		return -ENODEV;
1452	dev->board_ptr  = thisboard;
1453	dev->board_name = thisboard->name;
1454
1455	devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1456	if (!devpriv)
1457		return -ENOMEM;
1458	dev->private = devpriv;
1459
1460	ret = comedi_pci_enable(pcidev, dev->board_name);
1461	if (ret)
1462		return ret;
1463
1464	devpriv->s5933_config = pci_resource_start(pcidev, 0);
1465	devpriv->control_status = pci_resource_start(pcidev, 1);
1466	devpriv->adc_fifo = pci_resource_start(pcidev, 2);
1467	devpriv->pacer_counter_dio = pci_resource_start(pcidev, 3);
1468	if (thisboard->ao_nchan)
1469		devpriv->ao_registers = pci_resource_start(pcidev, 4);
1470
1471	/*  disable and clear interrupts on amcc s5933 */
1472	outl(INTCSR_INBOX_INTR_STATUS,
1473	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1474
1475	if (request_irq(pcidev->irq, cb_pcidas_interrupt,
1476			IRQF_SHARED, dev->driver->driver_name, dev)) {
1477		dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1478			pcidev->irq);
1479		return -EINVAL;
1480	}
1481	dev->irq = pcidev->irq;
1482
1483	ret = comedi_alloc_subdevices(dev, 7);
1484	if (ret)
1485		return ret;
1486
1487	s = &dev->subdevices[0];
1488	/* analog input subdevice */
1489	dev->read_subdev = s;
1490	s->type = COMEDI_SUBD_AI;
1491	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
1492	/* WARNING: Number of inputs in differential mode is ignored */
1493	s->n_chan = thisboard->ai_nchan;
1494	s->len_chanlist = thisboard->ai_nchan;
1495	s->maxdata = (1 << thisboard->ai_bits) - 1;
1496	s->range_table = thisboard->ranges;
1497	s->insn_read = cb_pcidas_ai_rinsn;
1498	s->insn_config = ai_config_insn;
1499	s->do_cmd = cb_pcidas_ai_cmd;
1500	s->do_cmdtest = cb_pcidas_ai_cmdtest;
1501	s->cancel = cb_pcidas_cancel;
1502
1503	/* analog output subdevice */
1504	s = &dev->subdevices[1];
1505	if (thisboard->ao_nchan) {
1506		s->type = COMEDI_SUBD_AO;
1507		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1508		s->n_chan = thisboard->ao_nchan;
1509		/*
1510		 * analog out resolution is the same as
1511		 * analog input resolution, so use ai_bits
1512		 */
1513		s->maxdata = (1 << thisboard->ai_bits) - 1;
1514		s->range_table = &cb_pcidas_ao_ranges;
1515		s->insn_read = cb_pcidas_ao_readback_insn;
1516		if (thisboard->has_ao_fifo) {
1517			dev->write_subdev = s;
1518			s->subdev_flags |= SDF_CMD_WRITE;
1519			s->insn_write = cb_pcidas_ao_fifo_winsn;
1520			s->do_cmdtest = cb_pcidas_ao_cmdtest;
1521			s->do_cmd = cb_pcidas_ao_cmd;
1522			s->cancel = cb_pcidas_ao_cancel;
1523		} else {
1524			s->insn_write = cb_pcidas_ao_nofifo_winsn;
1525		}
1526	} else {
1527		s->type = COMEDI_SUBD_UNUSED;
1528	}
1529
1530	/* 8255 */
1531	s = &dev->subdevices[2];
1532	ret = subdev_8255_init(dev, s, NULL,
1533			       devpriv->pacer_counter_dio + DIO_8255);
1534	if (ret)
1535		return ret;
1536
1537	/*  serial EEPROM, */
1538	s = &dev->subdevices[3];
1539	s->type = COMEDI_SUBD_MEMORY;
1540	s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1541	s->n_chan = 256;
1542	s->maxdata = 0xff;
1543	s->insn_read = eeprom_read_insn;
1544
1545	/*  8800 caldac */
1546	s = &dev->subdevices[4];
1547	s->type = COMEDI_SUBD_CALIB;
1548	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1549	s->n_chan = NUM_CHANNELS_8800;
1550	s->maxdata = 0xff;
1551	s->insn_read = caldac_read_insn;
1552	s->insn_write = caldac_write_insn;
1553	for (i = 0; i < s->n_chan; i++)
1554		caldac_8800_write(dev, i, s->maxdata / 2);
1555
1556	/*  trim potentiometer */
1557	s = &dev->subdevices[5];
1558	s->type = COMEDI_SUBD_CALIB;
1559	s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1560	if (thisboard->trimpot == AD7376) {
1561		s->n_chan = NUM_CHANNELS_7376;
1562		s->maxdata = 0x7f;
1563	} else {
1564		s->n_chan = NUM_CHANNELS_8402;
1565		s->maxdata = 0xff;
1566	}
1567	s->insn_read = trimpot_read_insn;
1568	s->insn_write = trimpot_write_insn;
1569	for (i = 0; i < s->n_chan; i++)
1570		cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1571
1572	/*  dac08 caldac */
1573	s = &dev->subdevices[6];
1574	if (thisboard->has_dac08) {
1575		s->type = COMEDI_SUBD_CALIB;
1576		s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1577		s->n_chan = NUM_CHANNELS_DAC08;
1578		s->insn_read = dac08_read_insn;
1579		s->insn_write = dac08_write_insn;
1580		s->maxdata = 0xff;
1581		dac08_write(dev, s->maxdata / 2);
1582	} else
1583		s->type = COMEDI_SUBD_UNUSED;
1584
1585	/*  make sure mailbox 4 is empty */
1586	inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1587	/* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1588	devpriv->s5933_intcsr_bits =
1589	    INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1590	    INTCSR_INBOX_FULL_INT;
1591	/*  clear and enable interrupt on amcc s5933 */
1592	outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1593	     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1594
1595	dev_info(dev->class_dev, "%s: %s attached\n",
1596		dev->driver->driver_name, dev->board_name);
1597
1598	return 0;
1599}
1600
1601static void cb_pcidas_detach(struct comedi_device *dev)
1602{
1603	struct cb_pcidas_private *devpriv = dev->private;
1604	struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1605
1606	if (devpriv) {
1607		if (devpriv->s5933_config) {
1608			outl(INTCSR_INBOX_INTR_STATUS,
1609			     devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1610		}
1611	}
1612	if (dev->irq)
1613		free_irq(dev->irq, dev);
1614	if (dev->subdevices)
1615		subdev_8255_cleanup(dev, &dev->subdevices[2]);
1616	if (pcidev) {
1617		if (devpriv->s5933_config)
1618			comedi_pci_disable(pcidev);
1619	}
1620}
1621
1622static struct comedi_driver cb_pcidas_driver = {
1623	.driver_name	= "cb_pcidas",
1624	.module		= THIS_MODULE,
1625	.auto_attach	= cb_pcidas_auto_attach,
1626	.detach		= cb_pcidas_detach,
1627};
1628
1629static int cb_pcidas_pci_probe(struct pci_dev *dev,
1630					 const struct pci_device_id *ent)
1631{
1632	return comedi_pci_auto_config(dev, &cb_pcidas_driver);
1633}
1634
1635static void cb_pcidas_pci_remove(struct pci_dev *dev)
1636{
1637	comedi_pci_auto_unconfig(dev);
1638}
1639
1640static DEFINE_PCI_DEVICE_TABLE(cb_pcidas_pci_table) = {
1641	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0001) },
1642	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x000f) },
1643	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0010) },
1644	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x0019) },
1645	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001c) },
1646	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x004c) },
1647	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001a) },
1648	{ PCI_DEVICE(PCI_VENDOR_ID_CB, 0x001b) },
1649	{ 0 }
1650};
1651MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
1652
1653static struct pci_driver cb_pcidas_pci_driver = {
1654	.name		= "cb_pcidas",
1655	.id_table	= cb_pcidas_pci_table,
1656	.probe		= cb_pcidas_pci_probe,
1657	.remove		= cb_pcidas_pci_remove
1658};
1659module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
1660
1661MODULE_AUTHOR("Comedi http://www.comedi.org");
1662MODULE_DESCRIPTION("Comedi low-level driver");
1663MODULE_LICENSE("GPL");
1664