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