[go: nahoru, domu]

1/*
2 * dt282x.c
3 * Comedi driver for Data Translation DT2821 series
4 *
5 * COMEDI - Linux Control and Measurement Device Interface
6 * Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 */
18
19/*
20 * Driver: dt282x
21 * Description: Data Translation DT2821 series (including DT-EZ)
22 * Author: ds
23 * Devices: (Data Translation) DT2821 [dt2821]
24 *	    (Data Translation) DT2821-F-16SE [dt2821-f]
25 *	    (Data Translation) DT2821-F-8DI [dt2821-f]
26 *	    (Data Translation) DT2821-G-16SE [dt2821-g]
27 *	    (Data Translation) DT2821-G-8DI [dt2821-g]
28 *	    (Data Translation) DT2823 [dt2823]
29 *	    (Data Translation) DT2824-PGH [dt2824-pgh]
30 *	    (Data Translation) DT2824-PGL [dt2824-pgl]
31 *	    (Data Translation) DT2825 [dt2825]
32 *	    (Data Translation) DT2827 [dt2827]
33 *	    (Data Translation) DT2828 [dt2828]
34 *	    (Data Translation) DT2928 [dt2829]
35 *	    (Data Translation) DT21-EZ [dt21-ez]
36 *	    (Data Translation) DT23-EZ [dt23-ez]
37 *	    (Data Translation) DT24-EZ [dt24-ez]
38 *	    (Data Translation) DT24-EZ-PGL [dt24-ez-pgl]
39 * Status: complete
40 * Updated: Wed, 22 Aug 2001 17:11:34 -0700
41 *
42 * Configuration options:
43 *   [0] - I/O port base address
44 *   [1] - IRQ (optional, required for async command support)
45 *   [2] - DMA 1 (optional, required for async command support)
46 *   [3] - DMA 2 (optional, required for async command support)
47 *   [4] - AI jumpered for 0=single ended, 1=differential
48 *   [5] - AI jumpered for 0=straight binary, 1=2's complement
49 *   [6] - AO 0 data format (deprecated, see below)
50 *   [7] - AO 1 data format (deprecated, see below)
51 *   [8] - AI jumpered for 0=[-10,10]V, 1=[0,10], 2=[-5,5], 3=[0,5]
52 *   [9] - AO channel 0 range (deprecated, see below)
53 *   [10]- AO channel 1 range (deprecated, see below)
54 *
55 * Notes:
56 *   - AO commands might be broken.
57 *   - If you try to run a command on both the AI and AO subdevices
58 *     simultaneously, bad things will happen.  The driver needs to
59 *     be fixed to check for this situation and return an error.
60 *   - AO range is not programmable. The AO subdevice has a range_table
61 *     containing all the possible analog output ranges. Use the range
62 *     that matches your board configuration to convert between data
63 *     values and physical units. The format of the data written to the
64 *     board is handled automatically based on the unipolar/bipolar
65 *     range that is selected.
66 */
67
68#include <linux/module.h>
69#include "../comedidev.h"
70
71#include <linux/delay.h>
72#include <linux/gfp.h>
73#include <linux/interrupt.h>
74#include <linux/io.h>
75
76#include <asm/dma.h>
77
78#include "comedi_fc.h"
79
80/*
81 * Register map
82 */
83#define DT2821_ADCSR_REG		0x00
84#define DT2821_ADCSR_ADERR		(1 << 15)
85#define DT2821_ADCSR_ADCLK		(1 << 9)
86#define DT2821_ADCSR_MUXBUSY		(1 << 8)
87#define DT2821_ADCSR_ADDONE		(1 << 7)
88#define DT2821_ADCSR_IADDONE		(1 << 6)
89#define DT2821_ADCSR_GS(x)		(((x) & 0x3) << 4)
90#define DT2821_ADCSR_CHAN(x)		(((x) & 0xf) << 0)
91#define DT2821_CHANCSR_REG		0x02
92#define DT2821_CHANCSR_LLE		(1 << 15)
93#define DT2821_CHANCSR_PRESLA(x)	(((x) & 0xf) >> 8)
94#define DT2821_CHANCSR_NUMB(x)		((((x) - 1) & 0xf) << 0)
95#define DT2821_ADDAT_REG		0x04
96#define DT2821_DACSR_REG		0x06
97#define DT2821_DACSR_DAERR		(1 << 15)
98#define DT2821_DACSR_YSEL(x)		((x) << 9)
99#define DT2821_DACSR_SSEL		(1 << 8)
100#define DT2821_DACSR_DACRDY		(1 << 7)
101#define DT2821_DACSR_IDARDY		(1 << 6)
102#define DT2821_DACSR_DACLK		(1 << 5)
103#define DT2821_DACSR_HBOE		(1 << 1)
104#define DT2821_DACSR_LBOE		(1 << 0)
105#define DT2821_DADAT_REG		0x08
106#define DT2821_DIODAT_REG		0x0a
107#define DT2821_SUPCSR_REG		0x0c
108#define DT2821_SUPCSR_DMAD		(1 << 15)
109#define DT2821_SUPCSR_ERRINTEN		(1 << 14)
110#define DT2821_SUPCSR_CLRDMADNE		(1 << 13)
111#define DT2821_SUPCSR_DDMA		(1 << 12)
112#define DT2821_SUPCSR_DS_PIO		(0 << 10)
113#define DT2821_SUPCSR_DS_AD_CLK		(1 << 10)
114#define DT2821_SUPCSR_DS_DA_CLK		(2 << 10)
115#define DT2821_SUPCSR_DS_AD_TRIG	(3 << 10)
116#define DT2821_SUPCSR_BUFFB		(1 << 9)
117#define DT2821_SUPCSR_SCDN		(1 << 8)
118#define DT2821_SUPCSR_DACON		(1 << 7)
119#define DT2821_SUPCSR_ADCINIT		(1 << 6)
120#define DT2821_SUPCSR_DACINIT		(1 << 5)
121#define DT2821_SUPCSR_PRLD		(1 << 4)
122#define DT2821_SUPCSR_STRIG		(1 << 3)
123#define DT2821_SUPCSR_XTRIG		(1 << 2)
124#define DT2821_SUPCSR_XCLK		(1 << 1)
125#define DT2821_SUPCSR_BDINIT		(1 << 0)
126#define DT2821_TMRCTR_REG		0x0e
127
128static const struct comedi_lrange range_dt282x_ai_lo_bipolar = {
129	4, {
130		BIP_RANGE(10),
131		BIP_RANGE(5),
132		BIP_RANGE(2.5),
133		BIP_RANGE(1.25)
134	}
135};
136
137static const struct comedi_lrange range_dt282x_ai_lo_unipolar = {
138	4, {
139		UNI_RANGE(10),
140		UNI_RANGE(5),
141		UNI_RANGE(2.5),
142		UNI_RANGE(1.25)
143	}
144};
145
146static const struct comedi_lrange range_dt282x_ai_5_bipolar = {
147	4, {
148		BIP_RANGE(5),
149		BIP_RANGE(2.5),
150		BIP_RANGE(1.25),
151		BIP_RANGE(0.625)
152	}
153};
154
155static const struct comedi_lrange range_dt282x_ai_5_unipolar = {
156	4, {
157		UNI_RANGE(5),
158		UNI_RANGE(2.5),
159		UNI_RANGE(1.25),
160		UNI_RANGE(0.625)
161	}
162};
163
164static const struct comedi_lrange range_dt282x_ai_hi_bipolar = {
165	4, {
166		BIP_RANGE(10),
167		BIP_RANGE(1),
168		BIP_RANGE(0.1),
169		BIP_RANGE(0.02)
170	}
171};
172
173static const struct comedi_lrange range_dt282x_ai_hi_unipolar = {
174	4, {
175		UNI_RANGE(10),
176		UNI_RANGE(1),
177		UNI_RANGE(0.1),
178		UNI_RANGE(0.02)
179	}
180};
181
182/*
183 * The Analog Output range is set per-channel using jumpers on the board.
184 * All of these ranges may not be available on some DT2821 series boards.
185 * The default jumper setting has both channels set for +/-10V output.
186 */
187static const struct comedi_lrange dt282x_ao_range = {
188	5, {
189		BIP_RANGE(10),
190		BIP_RANGE(5),
191		BIP_RANGE(2.5),
192		UNI_RANGE(10),
193		UNI_RANGE(5),
194	}
195};
196
197struct dt282x_board {
198	const char *name;
199	unsigned int ai_maxdata;
200	int adchan_se;
201	int adchan_di;
202	int ai_speed;
203	int ispgl;
204	int dachan;
205	unsigned int ao_maxdata;
206};
207
208static const struct dt282x_board boardtypes[] = {
209	{
210		.name		= "dt2821",
211		.ai_maxdata	= 0x0fff,
212		.adchan_se	= 16,
213		.adchan_di	= 8,
214		.ai_speed	= 20000,
215		.dachan		= 2,
216		.ao_maxdata	= 0x0fff,
217	}, {
218		.name		= "dt2821-f",
219		.ai_maxdata	= 0x0fff,
220		.adchan_se	= 16,
221		.adchan_di	= 8,
222		.ai_speed	= 6500,
223		.dachan		= 2,
224		.ao_maxdata	= 0x0fff,
225	}, {
226		.name		= "dt2821-g",
227		.ai_maxdata	= 0x0fff,
228		.adchan_se	= 16,
229		.adchan_di	= 8,
230		.ai_speed	= 4000,
231		.dachan		= 2,
232		.ao_maxdata	= 0x0fff,
233	}, {
234		.name		= "dt2823",
235		.ai_maxdata	= 0xffff,
236		.adchan_di	= 4,
237		.ai_speed	= 10000,
238		.dachan		= 2,
239		.ao_maxdata	= 0xffff,
240	}, {
241		.name		= "dt2824-pgh",
242		.ai_maxdata	= 0x0fff,
243		.adchan_se	= 16,
244		.adchan_di	= 8,
245		.ai_speed	= 20000,
246	}, {
247		.name		= "dt2824-pgl",
248		.ai_maxdata	= 0x0fff,
249		.adchan_se	= 16,
250		.adchan_di	= 8,
251		.ai_speed	= 20000,
252		.ispgl		= 1,
253	}, {
254		.name		= "dt2825",
255		.ai_maxdata	= 0x0fff,
256		.adchan_se	= 16,
257		.adchan_di	= 8,
258		.ai_speed	= 20000,
259		.ispgl		= 1,
260		.dachan		= 2,
261		.ao_maxdata	= 0x0fff,
262	}, {
263		.name		= "dt2827",
264		.ai_maxdata	= 0xffff,
265		.adchan_di	= 4,
266		.ai_speed	= 10000,
267		.dachan		= 2,
268		.ao_maxdata	= 0x0fff,
269	}, {
270		.name		= "dt2828",
271		.ai_maxdata	= 0x0fff,
272		.adchan_se	= 4,
273		.ai_speed	= 10000,
274		.dachan		= 2,
275		.ao_maxdata	= 0x0fff,
276	}, {
277		.name		= "dt2829",
278		.ai_maxdata	= 0xffff,
279		.adchan_se	= 8,
280		.ai_speed	= 33250,
281		.dachan		= 2,
282		.ao_maxdata	= 0xffff,
283	}, {
284		.name		= "dt21-ez",
285		.ai_maxdata	= 0x0fff,
286		.adchan_se	= 16,
287		.adchan_di	= 8,
288		.ai_speed	= 10000,
289		.dachan		= 2,
290		.ao_maxdata	= 0x0fff,
291	}, {
292		.name		= "dt23-ez",
293		.ai_maxdata	= 0xffff,
294		.adchan_se	= 16,
295		.adchan_di	= 8,
296		.ai_speed	= 10000,
297	}, {
298		.name		= "dt24-ez",
299		.ai_maxdata	= 0x0fff,
300		.adchan_se	= 16,
301		.adchan_di	= 8,
302		.ai_speed	= 10000,
303	}, {
304		.name		= "dt24-ez-pgl",
305		.ai_maxdata	= 0x0fff,
306		.adchan_se	= 16,
307		.adchan_di	= 8,
308		.ai_speed	= 10000,
309		.ispgl		= 1,
310	},
311};
312
313struct dt282x_private {
314	unsigned int ad_2scomp:1;
315
316	unsigned int divisor;
317
318	int dacsr;	/* software copies of registers */
319	int adcsr;
320	int supcsr;
321
322	int ntrig;
323	int nread;
324
325	struct {
326		int chan;
327		unsigned short *buf;	/* DMA buffer */
328		int size;	/* size of current transfer */
329	} dma[2];
330	int dma_maxsize;	/* max size of DMA transfer (in bytes) */
331	int current_dma_index;
332	int dma_dir;
333};
334
335static int dt282x_prep_ai_dma(struct comedi_device *dev, int dma_index, int n)
336{
337	struct dt282x_private *devpriv = dev->private;
338	int dma_chan;
339	unsigned long dma_ptr;
340	unsigned long flags;
341
342	if (!devpriv->ntrig)
343		return 0;
344
345	if (n == 0)
346		n = devpriv->dma_maxsize;
347	if (n > devpriv->ntrig * 2)
348		n = devpriv->ntrig * 2;
349	devpriv->ntrig -= n / 2;
350
351	devpriv->dma[dma_index].size = n;
352	dma_chan = devpriv->dma[dma_index].chan;
353	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
354
355	set_dma_mode(dma_chan, DMA_MODE_READ);
356	flags = claim_dma_lock();
357	clear_dma_ff(dma_chan);
358	set_dma_addr(dma_chan, dma_ptr);
359	set_dma_count(dma_chan, n);
360	release_dma_lock(flags);
361
362	enable_dma(dma_chan);
363
364	return n;
365}
366
367static int dt282x_prep_ao_dma(struct comedi_device *dev, int dma_index, int n)
368{
369	struct dt282x_private *devpriv = dev->private;
370	int dma_chan;
371	unsigned long dma_ptr;
372	unsigned long flags;
373
374	devpriv->dma[dma_index].size = n;
375	dma_chan = devpriv->dma[dma_index].chan;
376	dma_ptr = virt_to_bus(devpriv->dma[dma_index].buf);
377
378	set_dma_mode(dma_chan, DMA_MODE_WRITE);
379	flags = claim_dma_lock();
380	clear_dma_ff(dma_chan);
381	set_dma_addr(dma_chan, dma_ptr);
382	set_dma_count(dma_chan, n);
383	release_dma_lock(flags);
384
385	enable_dma(dma_chan);
386
387	return n;
388}
389
390static void dt282x_disable_dma(struct comedi_device *dev)
391{
392	struct dt282x_private *devpriv = dev->private;
393
394	disable_dma(devpriv->dma[0].chan);
395	disable_dma(devpriv->dma[1].chan);
396}
397
398static unsigned int dt282x_ns_to_timer(unsigned int *ns, unsigned int flags)
399{
400	unsigned int prescale, base, divider;
401
402	for (prescale = 0; prescale < 16; prescale++) {
403		if (prescale == 1)
404			continue;
405		base = 250 * (1 << prescale);
406		switch (flags & CMDF_ROUND_MASK) {
407		case CMDF_ROUND_NEAREST:
408		default:
409			divider = (*ns + base / 2) / base;
410			break;
411		case CMDF_ROUND_DOWN:
412			divider = (*ns) / base;
413			break;
414		case CMDF_ROUND_UP:
415			divider = (*ns + base - 1) / base;
416			break;
417		}
418		if (divider < 256) {
419			*ns = divider * base;
420			return (prescale << 8) | (255 - divider);
421		}
422	}
423	base = 250 * (1 << 15);
424	divider = 255;
425	*ns = divider * base;
426	return (15 << 8) | (255 - divider);
427}
428
429static void dt282x_munge(struct comedi_device *dev,
430			 struct comedi_subdevice *s,
431			 unsigned short *buf,
432			 unsigned int nbytes)
433{
434	struct dt282x_private *devpriv = dev->private;
435	unsigned int val;
436	int i;
437
438	if (nbytes % 2)
439		dev_err(dev->class_dev,
440			"bug! odd number of bytes from dma xfer\n");
441
442	for (i = 0; i < nbytes / 2; i++) {
443		val = buf[i];
444		val &= s->maxdata;
445		if (devpriv->ad_2scomp)
446			val = comedi_offset_munge(s, val);
447
448		buf[i] = val;
449	}
450}
451
452static void dt282x_ao_dma_interrupt(struct comedi_device *dev,
453				    struct comedi_subdevice *s)
454{
455	struct dt282x_private *devpriv = dev->private;
456	int cur_dma = devpriv->current_dma_index;
457	void *ptr = devpriv->dma[cur_dma].buf;
458	int size;
459
460	outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
461	     dev->iobase + DT2821_SUPCSR_REG);
462
463	disable_dma(devpriv->dma[cur_dma].chan);
464
465	devpriv->current_dma_index = 1 - cur_dma;
466
467	size = cfc_read_array_from_buffer(s, ptr, devpriv->dma_maxsize);
468	if (size == 0) {
469		dev_err(dev->class_dev, "AO underrun\n");
470		s->async->events |= COMEDI_CB_OVERFLOW;
471	} else {
472		dt282x_prep_ao_dma(dev, cur_dma, size);
473	}
474}
475
476static void dt282x_ai_dma_interrupt(struct comedi_device *dev,
477				    struct comedi_subdevice *s)
478{
479	struct dt282x_private *devpriv = dev->private;
480	int cur_dma = devpriv->current_dma_index;
481	void *ptr = devpriv->dma[cur_dma].buf;
482	int size = devpriv->dma[cur_dma].size;
483	int ret;
484
485	outw(devpriv->supcsr | DT2821_SUPCSR_CLRDMADNE,
486	     dev->iobase + DT2821_SUPCSR_REG);
487
488	disable_dma(devpriv->dma[cur_dma].chan);
489
490	devpriv->current_dma_index = 1 - cur_dma;
491
492	dt282x_munge(dev, s, ptr, size);
493	ret = cfc_write_array_to_buffer(s, ptr, size);
494	if (ret != size) {
495		s->async->events |= COMEDI_CB_OVERFLOW;
496		return;
497	}
498
499	devpriv->nread -= size / 2;
500	if (devpriv->nread < 0) {
501		dev_info(dev->class_dev, "nread off by one\n");
502		devpriv->nread = 0;
503	}
504	if (!devpriv->nread) {
505		s->async->events |= COMEDI_CB_EOA;
506		return;
507	}
508#if 0
509	/* clear the dual dma flag, making this the last dma segment */
510	/* XXX probably wrong */
511	if (!devpriv->ntrig) {
512		devpriv->supcsr &= ~DT2821_SUPCSR_DDMA;
513		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
514	}
515#endif
516	/* restart the channel */
517	dt282x_prep_ai_dma(dev, cur_dma, 0);
518}
519
520static irqreturn_t dt282x_interrupt(int irq, void *d)
521{
522	struct comedi_device *dev = d;
523	struct dt282x_private *devpriv = dev->private;
524	struct comedi_subdevice *s = dev->read_subdev;
525	struct comedi_subdevice *s_ao = dev->write_subdev;
526	unsigned int supcsr, adcsr, dacsr;
527	int handled = 0;
528
529	if (!dev->attached) {
530		dev_err(dev->class_dev, "spurious interrupt\n");
531		return IRQ_HANDLED;
532	}
533
534	adcsr = inw(dev->iobase + DT2821_ADCSR_REG);
535	dacsr = inw(dev->iobase + DT2821_DACSR_REG);
536	supcsr = inw(dev->iobase + DT2821_SUPCSR_REG);
537	if (supcsr & DT2821_SUPCSR_DMAD) {
538		if (devpriv->dma_dir == DMA_MODE_READ)
539			dt282x_ai_dma_interrupt(dev, s);
540		else
541			dt282x_ao_dma_interrupt(dev, s_ao);
542		handled = 1;
543	}
544	if (adcsr & DT2821_ADCSR_ADERR) {
545		if (devpriv->nread != 0) {
546			dev_err(dev->class_dev, "A/D error\n");
547			s->async->events |= COMEDI_CB_ERROR;
548		}
549		handled = 1;
550	}
551	if (dacsr & DT2821_DACSR_DAERR) {
552		dev_err(dev->class_dev, "D/A error\n");
553		s_ao->async->events |= COMEDI_CB_ERROR;
554		handled = 1;
555	}
556#if 0
557	if (adcsr & DT2821_ADCSR_ADDONE) {
558		int ret;
559		unsigned short data;
560
561		data = inw(dev->iobase + DT2821_ADDAT_REG);
562		data &= s->maxdata;
563		if (devpriv->ad_2scomp)
564			data = comedi_offset_munge(s, data);
565
566		ret = comedi_buf_put(s, data);
567
568		if (ret == 0)
569			s->async->events |= COMEDI_CB_OVERFLOW;
570
571		devpriv->nread--;
572		if (!devpriv->nread) {
573			s->async->events |= COMEDI_CB_EOA;
574		} else {
575			if (supcsr & DT2821_SUPCSR_SCDN)
576				outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
577				     dev->iobase + DT2821_SUPCSR_REG);
578		}
579		handled = 1;
580	}
581#endif
582	cfc_handle_events(dev, s);
583	cfc_handle_events(dev, s_ao);
584
585	return IRQ_RETVAL(handled);
586}
587
588static void dt282x_load_changain(struct comedi_device *dev, int n,
589				 unsigned int *chanlist)
590{
591	struct dt282x_private *devpriv = dev->private;
592	int i;
593
594	outw(DT2821_CHANCSR_LLE | DT2821_CHANCSR_NUMB(n),
595	     dev->iobase + DT2821_CHANCSR_REG);
596	for (i = 0; i < n; i++) {
597		unsigned int chan = CR_CHAN(chanlist[i]);
598		unsigned int range = CR_RANGE(chanlist[i]);
599
600		outw(devpriv->adcsr |
601		     DT2821_ADCSR_GS(range) |
602		     DT2821_ADCSR_CHAN(chan),
603		     dev->iobase + DT2821_ADCSR_REG);
604	}
605	outw(DT2821_CHANCSR_NUMB(n), dev->iobase + DT2821_CHANCSR_REG);
606}
607
608static int dt282x_ai_timeout(struct comedi_device *dev,
609			     struct comedi_subdevice *s,
610			     struct comedi_insn *insn,
611			     unsigned long context)
612{
613	unsigned int status;
614
615	status = inw(dev->iobase + DT2821_ADCSR_REG);
616	switch (context) {
617	case DT2821_ADCSR_MUXBUSY:
618		if ((status & DT2821_ADCSR_MUXBUSY) == 0)
619			return 0;
620		break;
621	case DT2821_ADCSR_ADDONE:
622		if (status & DT2821_ADCSR_ADDONE)
623			return 0;
624		break;
625	default:
626		return -EINVAL;
627	}
628	return -EBUSY;
629}
630
631/*
632 *    Performs a single A/D conversion.
633 *      - Put channel/gain into channel-gain list
634 *      - preload multiplexer
635 *      - trigger conversion and wait for it to finish
636 */
637static int dt282x_ai_insn_read(struct comedi_device *dev,
638			       struct comedi_subdevice *s,
639			       struct comedi_insn *insn,
640			       unsigned int *data)
641{
642	struct dt282x_private *devpriv = dev->private;
643	unsigned int val;
644	int ret;
645	int i;
646
647	/* XXX should we really be enabling the ad clock here? */
648	devpriv->adcsr = DT2821_ADCSR_ADCLK;
649	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
650
651	dt282x_load_changain(dev, 1, &insn->chanspec);
652
653	outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
654	     dev->iobase + DT2821_SUPCSR_REG);
655	ret = comedi_timeout(dev, s, insn,
656			     dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
657	if (ret)
658		return ret;
659
660	for (i = 0; i < insn->n; i++) {
661		outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
662		     dev->iobase + DT2821_SUPCSR_REG);
663
664		ret = comedi_timeout(dev, s, insn,
665				     dt282x_ai_timeout, DT2821_ADCSR_ADDONE);
666		if (ret)
667			return ret;
668
669		val = inw(dev->iobase + DT2821_ADDAT_REG);
670		val &= s->maxdata;
671		if (devpriv->ad_2scomp)
672			val = comedi_offset_munge(s, val);
673
674		data[i] = val;
675	}
676
677	return i;
678}
679
680static int dt282x_ai_cmdtest(struct comedi_device *dev,
681			     struct comedi_subdevice *s,
682			     struct comedi_cmd *cmd)
683{
684	const struct dt282x_board *board = dev->board_ptr;
685	struct dt282x_private *devpriv = dev->private;
686	int err = 0;
687	unsigned int arg;
688
689	/* Step 1 : check if triggers are trivially valid */
690
691	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
692	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
693					TRIG_FOLLOW | TRIG_EXT);
694	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER);
695	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
696	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
697
698	if (err)
699		return 1;
700
701	/* Step 2a : make sure trigger sources are unique */
702
703	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
704	err |= cfc_check_trigger_is_unique(cmd->stop_src);
705
706	/* Step 2b : and mutually compatible */
707
708	if (err)
709		return 2;
710
711	/* Step 3: check if arguments are trivially valid */
712
713	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
714
715	if (cmd->scan_begin_src == TRIG_FOLLOW) {
716		/* internal trigger */
717		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
718	} else {
719		/* external trigger */
720		/* should be level/edge, hi/lo specification here */
721		err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
722	}
723
724	err |= cfc_check_trigger_arg_min(&cmd->convert_arg, 4000);
725
726#define SLOWEST_TIMER	(250*(1<<15)*255)
727	err |= cfc_check_trigger_arg_max(&cmd->convert_arg, SLOWEST_TIMER);
728	err |= cfc_check_trigger_arg_min(&cmd->convert_arg, board->ai_speed);
729	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
730
731	if (cmd->stop_src == TRIG_COUNT)
732		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
733	else	/* TRIG_EXT | TRIG_NONE */
734		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
735
736	if (err)
737		return 3;
738
739	/* step 4: fix up any arguments */
740
741	arg = cmd->convert_arg;
742	devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
743	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
744
745	if (err)
746		return 4;
747
748	return 0;
749}
750
751static int dt282x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
752{
753	struct dt282x_private *devpriv = dev->private;
754	struct comedi_cmd *cmd = &s->async->cmd;
755	int ret;
756
757	dt282x_disable_dma(dev);
758
759	outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
760
761	devpriv->supcsr = DT2821_SUPCSR_ERRINTEN;
762	if (cmd->scan_begin_src == TRIG_FOLLOW)
763		devpriv->supcsr = DT2821_SUPCSR_DS_AD_CLK;
764	else
765		devpriv->supcsr = DT2821_SUPCSR_DS_AD_TRIG;
766	outw(devpriv->supcsr |
767	     DT2821_SUPCSR_CLRDMADNE |
768	     DT2821_SUPCSR_BUFFB |
769	     DT2821_SUPCSR_ADCINIT,
770	     dev->iobase + DT2821_SUPCSR_REG);
771
772	devpriv->ntrig = cmd->stop_arg * cmd->scan_end_arg;
773	devpriv->nread = devpriv->ntrig;
774
775	devpriv->dma_dir = DMA_MODE_READ;
776	devpriv->current_dma_index = 0;
777	dt282x_prep_ai_dma(dev, 0, 0);
778	if (devpriv->ntrig) {
779		dt282x_prep_ai_dma(dev, 1, 0);
780		devpriv->supcsr |= DT2821_SUPCSR_DDMA;
781		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
782	}
783
784	devpriv->adcsr = 0;
785
786	dt282x_load_changain(dev, cmd->chanlist_len, cmd->chanlist);
787
788	devpriv->adcsr = DT2821_ADCSR_ADCLK | DT2821_ADCSR_IADDONE;
789	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
790
791	outw(devpriv->supcsr | DT2821_SUPCSR_PRLD,
792	     dev->iobase + DT2821_SUPCSR_REG);
793	ret = comedi_timeout(dev, s, NULL,
794			     dt282x_ai_timeout, DT2821_ADCSR_MUXBUSY);
795	if (ret)
796		return ret;
797
798	if (cmd->scan_begin_src == TRIG_FOLLOW) {
799		outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
800			dev->iobase + DT2821_SUPCSR_REG);
801	} else {
802		devpriv->supcsr |= DT2821_SUPCSR_XTRIG;
803		outw(devpriv->supcsr, dev->iobase + DT2821_SUPCSR_REG);
804	}
805
806	return 0;
807}
808
809static int dt282x_ai_cancel(struct comedi_device *dev,
810			    struct comedi_subdevice *s)
811{
812	struct dt282x_private *devpriv = dev->private;
813
814	dt282x_disable_dma(dev);
815
816	devpriv->adcsr = 0;
817	outw(devpriv->adcsr, dev->iobase + DT2821_ADCSR_REG);
818
819	devpriv->supcsr = 0;
820	outw(devpriv->supcsr | DT2821_SUPCSR_ADCINIT,
821	     dev->iobase + DT2821_SUPCSR_REG);
822
823	return 0;
824}
825
826static int dt282x_ao_insn_write(struct comedi_device *dev,
827				struct comedi_subdevice *s,
828				struct comedi_insn *insn,
829				unsigned int *data)
830{
831	struct dt282x_private *devpriv = dev->private;
832	unsigned int chan = CR_CHAN(insn->chanspec);
833	unsigned int range = CR_RANGE(insn->chanspec);
834	int i;
835
836	devpriv->dacsr |= DT2821_DACSR_SSEL | DT2821_DACSR_YSEL(chan);
837
838	for (i = 0; i < insn->n; i++) {
839		unsigned int val = data[i];
840
841		s->readback[chan] = val;
842
843		if (comedi_range_is_bipolar(s, range))
844			val = comedi_offset_munge(s, val);
845
846		outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
847
848		outw(val, dev->iobase + DT2821_DADAT_REG);
849
850		outw(devpriv->supcsr | DT2821_SUPCSR_DACON,
851		     dev->iobase + DT2821_SUPCSR_REG);
852	}
853
854	return insn->n;
855}
856
857static int dt282x_ao_cmdtest(struct comedi_device *dev,
858			     struct comedi_subdevice *s,
859			     struct comedi_cmd *cmd)
860{
861	struct dt282x_private *devpriv = dev->private;
862	int err = 0;
863	unsigned int arg;
864
865	/* Step 1 : check if triggers are trivially valid */
866
867	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT);
868	err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER);
869	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
870	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
871	err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
872
873	if (err)
874		return 1;
875
876	/* Step 2a : make sure trigger sources are unique */
877
878	err |= cfc_check_trigger_is_unique(cmd->stop_src);
879
880	/* Step 2b : and mutually compatible */
881
882	if (err)
883		return 2;
884
885	/* Step 3: check if arguments are trivially valid */
886
887	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
888	err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, 5000);
889	err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
890	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
891
892	if (cmd->stop_src == TRIG_COUNT)
893		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
894	else	/* TRIG_EXT | TRIG_NONE */
895		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
896
897	if (err)
898		return 3;
899
900	/* step 4: fix up any arguments */
901
902	arg = cmd->scan_begin_arg;
903	devpriv->divisor = dt282x_ns_to_timer(&arg, cmd->flags);
904	err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
905
906	if (err)
907		return 4;
908
909	return 0;
910
911}
912
913static int dt282x_ao_inttrig(struct comedi_device *dev,
914			     struct comedi_subdevice *s,
915			     unsigned int trig_num)
916{
917	struct dt282x_private *devpriv = dev->private;
918	struct comedi_cmd *cmd = &s->async->cmd;
919	int size;
920
921	if (trig_num != cmd->start_src)
922		return -EINVAL;
923
924	size = cfc_read_array_from_buffer(s, devpriv->dma[0].buf,
925					  devpriv->dma_maxsize);
926	if (size == 0) {
927		dev_err(dev->class_dev, "AO underrun\n");
928		return -EPIPE;
929	}
930	dt282x_prep_ao_dma(dev, 0, size);
931
932	size = cfc_read_array_from_buffer(s, devpriv->dma[1].buf,
933					  devpriv->dma_maxsize);
934	if (size == 0) {
935		dev_err(dev->class_dev, "AO underrun\n");
936		return -EPIPE;
937	}
938	dt282x_prep_ao_dma(dev, 1, size);
939
940	outw(devpriv->supcsr | DT2821_SUPCSR_STRIG,
941	     dev->iobase + DT2821_SUPCSR_REG);
942	s->async->inttrig = NULL;
943
944	return 1;
945}
946
947static int dt282x_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
948{
949	struct dt282x_private *devpriv = dev->private;
950	struct comedi_cmd *cmd = &s->async->cmd;
951
952	dt282x_disable_dma(dev);
953
954	devpriv->supcsr = DT2821_SUPCSR_ERRINTEN |
955			  DT2821_SUPCSR_DS_DA_CLK |
956			  DT2821_SUPCSR_DDMA;
957	outw(devpriv->supcsr |
958	     DT2821_SUPCSR_CLRDMADNE |
959	     DT2821_SUPCSR_BUFFB |
960	     DT2821_SUPCSR_DACINIT,
961	     dev->iobase + DT2821_SUPCSR_REG);
962
963	devpriv->ntrig = cmd->stop_arg * cmd->chanlist_len;
964	devpriv->nread = devpriv->ntrig;
965
966	devpriv->dma_dir = DMA_MODE_WRITE;
967	devpriv->current_dma_index = 0;
968
969	outw(devpriv->divisor, dev->iobase + DT2821_TMRCTR_REG);
970
971	/* clear all bits but the DIO direction bits */
972	devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
973
974	devpriv->dacsr |= (DT2821_DACSR_SSEL |
975			   DT2821_DACSR_DACLK |
976			   DT2821_DACSR_IDARDY);
977	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
978
979	s->async->inttrig = dt282x_ao_inttrig;
980
981	return 0;
982}
983
984static int dt282x_ao_cancel(struct comedi_device *dev,
985			    struct comedi_subdevice *s)
986{
987	struct dt282x_private *devpriv = dev->private;
988
989	dt282x_disable_dma(dev);
990
991	/* clear all bits but the DIO direction bits */
992	devpriv->dacsr &= (DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
993
994	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
995
996	devpriv->supcsr = 0;
997	outw(devpriv->supcsr | DT2821_SUPCSR_DACINIT,
998	     dev->iobase + DT2821_SUPCSR_REG);
999
1000	return 0;
1001}
1002
1003static int dt282x_dio_insn_bits(struct comedi_device *dev,
1004				struct comedi_subdevice *s,
1005				struct comedi_insn *insn,
1006				unsigned int *data)
1007{
1008	if (comedi_dio_update_state(s, data))
1009		outw(s->state, dev->iobase + DT2821_DIODAT_REG);
1010
1011	data[1] = inw(dev->iobase + DT2821_DIODAT_REG);
1012
1013	return insn->n;
1014}
1015
1016static int dt282x_dio_insn_config(struct comedi_device *dev,
1017				  struct comedi_subdevice *s,
1018				  struct comedi_insn *insn,
1019				  unsigned int *data)
1020{
1021	struct dt282x_private *devpriv = dev->private;
1022	unsigned int chan = CR_CHAN(insn->chanspec);
1023	unsigned int mask;
1024	int ret;
1025
1026	if (chan < 8)
1027		mask = 0x00ff;
1028	else
1029		mask = 0xff00;
1030
1031	ret = comedi_dio_insn_config(dev, s, insn, data, mask);
1032	if (ret)
1033		return ret;
1034
1035	devpriv->dacsr &= ~(DT2821_DACSR_LBOE | DT2821_DACSR_HBOE);
1036	if (s->io_bits & 0x00ff)
1037		devpriv->dacsr |= DT2821_DACSR_LBOE;
1038	if (s->io_bits & 0xff00)
1039		devpriv->dacsr |= DT2821_DACSR_HBOE;
1040
1041	outw(devpriv->dacsr, dev->iobase + DT2821_DACSR_REG);
1042
1043	return insn->n;
1044}
1045
1046static const struct comedi_lrange *const ai_range_table[] = {
1047	&range_dt282x_ai_lo_bipolar,
1048	&range_dt282x_ai_lo_unipolar,
1049	&range_dt282x_ai_5_bipolar,
1050	&range_dt282x_ai_5_unipolar
1051};
1052
1053static const struct comedi_lrange *const ai_range_pgl_table[] = {
1054	&range_dt282x_ai_hi_bipolar,
1055	&range_dt282x_ai_hi_unipolar
1056};
1057
1058static const struct comedi_lrange *opt_ai_range_lkup(int ispgl, int x)
1059{
1060	if (ispgl) {
1061		if (x < 0 || x >= 2)
1062			x = 0;
1063		return ai_range_pgl_table[x];
1064	}
1065
1066	if (x < 0 || x >= 4)
1067		x = 0;
1068	return ai_range_table[x];
1069}
1070
1071static int dt282x_grab_dma(struct comedi_device *dev, int dma1, int dma2)
1072{
1073	struct dt282x_private *devpriv = dev->private;
1074	int ret;
1075
1076	ret = request_dma(dma1, "dt282x A");
1077	if (ret)
1078		return -EBUSY;
1079	devpriv->dma[0].chan = dma1;
1080
1081	ret = request_dma(dma2, "dt282x B");
1082	if (ret)
1083		return -EBUSY;
1084	devpriv->dma[1].chan = dma2;
1085
1086	devpriv->dma_maxsize = PAGE_SIZE;
1087	devpriv->dma[0].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
1088	devpriv->dma[1].buf = (void *)__get_free_page(GFP_KERNEL | GFP_DMA);
1089	if (!devpriv->dma[0].buf || !devpriv->dma[1].buf)
1090		return -ENOMEM;
1091
1092	return 0;
1093}
1094
1095static void dt282x_free_dma(struct comedi_device *dev)
1096{
1097	struct dt282x_private *devpriv = dev->private;
1098	int i;
1099
1100	if (!devpriv)
1101		return;
1102
1103	for (i = 0; i < 2; i++) {
1104		if (devpriv->dma[i].chan)
1105			free_dma(devpriv->dma[i].chan);
1106		if (devpriv->dma[i].buf)
1107			free_page((unsigned long)devpriv->dma[i].buf);
1108		devpriv->dma[i].chan = 0;
1109		devpriv->dma[i].buf = NULL;
1110	}
1111}
1112
1113static int dt282x_initialize(struct comedi_device *dev)
1114{
1115	/* Initialize board */
1116	outw(DT2821_SUPCSR_BDINIT, dev->iobase + DT2821_SUPCSR_REG);
1117	inw(dev->iobase + DT2821_ADCSR_REG);
1118
1119	/*
1120	 * At power up, some registers are in a well-known state.
1121	 * Check them to see if a DT2821 series board is present.
1122	 */
1123	if (((inw(dev->iobase + DT2821_ADCSR_REG) & 0xfff0) != 0x7c00) ||
1124	    ((inw(dev->iobase + DT2821_CHANCSR_REG) & 0xf0f0) != 0x70f0) ||
1125	    ((inw(dev->iobase + DT2821_DACSR_REG) & 0x7c93) != 0x7c90) ||
1126	    ((inw(dev->iobase + DT2821_SUPCSR_REG) & 0xf8ff) != 0x0000) ||
1127	    ((inw(dev->iobase + DT2821_TMRCTR_REG) & 0xff00) != 0xf000)) {
1128		dev_err(dev->class_dev, "board not found\n");
1129		return -EIO;
1130	}
1131	return 0;
1132}
1133
1134/*
1135   options:
1136   0	i/o base
1137   1	irq
1138   2	dma1
1139   3	dma2
1140   4	0=single ended, 1=differential
1141   5	ai 0=straight binary, 1=2's comp
1142   6	ao0 0=straight binary, 1=2's comp
1143   7	ao1 0=straight binary, 1=2's comp
1144   8	ai 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V
1145   9	ao0 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
1146   10	ao1 0=±10 V, 1=0-10 V, 2=±5 V, 3=0-5 V, 4=±2.5 V
1147 */
1148static int dt282x_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1149{
1150	const struct dt282x_board *board = dev->board_ptr;
1151	struct dt282x_private *devpriv;
1152	struct comedi_subdevice *s;
1153	int ret;
1154
1155	ret = comedi_request_region(dev, it->options[0], 0x10);
1156	if (ret)
1157		return ret;
1158
1159	ret = dt282x_initialize(dev);
1160	if (ret)
1161		return ret;
1162
1163	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1164	if (!devpriv)
1165		return -ENOMEM;
1166
1167	/* an IRQ and 2 DMA channels are required for async command support */
1168	if (it->options[1] && it->options[2] && it->options[3]) {
1169		unsigned int irq = it->options[1];
1170		unsigned int dma1 = it->options[2];
1171		unsigned int dma2 = it->options[3];
1172
1173		if (dma2 < dma1) {
1174			unsigned int swap;
1175
1176			swap = dma1;
1177			dma1 = dma2;
1178			dma2 = swap;
1179		}
1180
1181		if (dma1 != dma2 &&
1182		    dma1 >= 5 && dma1 <= 7 &&
1183		    dma2 >= 5 && dma2 <= 7) {
1184			ret = request_irq(irq, dt282x_interrupt, 0,
1185					  dev->board_name, dev);
1186			if (ret == 0) {
1187				dev->irq = irq;
1188
1189				ret = dt282x_grab_dma(dev, dma1, dma2);
1190				if (ret < 0) {
1191					dt282x_free_dma(dev);
1192					free_irq(dev->irq, dev);
1193					dev->irq = 0;
1194				}
1195			}
1196		}
1197	}
1198
1199	ret = comedi_alloc_subdevices(dev, 3);
1200	if (ret)
1201		return ret;
1202
1203	/* Analog Input subdevice */
1204	s = &dev->subdevices[0];
1205	s->type		= COMEDI_SUBD_AI;
1206	s->subdev_flags	= SDF_READABLE;
1207	if ((it->options[4] && board->adchan_di) || board->adchan_se == 0) {
1208		s->subdev_flags	|= SDF_DIFF;
1209		s->n_chan	= board->adchan_di;
1210	} else {
1211		s->subdev_flags	|= SDF_COMMON;
1212		s->n_chan	= board->adchan_se;
1213	}
1214	s->maxdata	= board->ai_maxdata;
1215
1216	s->range_table = opt_ai_range_lkup(board->ispgl, it->options[8]);
1217	devpriv->ad_2scomp = it->options[5] ? 1 : 0;
1218
1219	s->insn_read	= dt282x_ai_insn_read;
1220	if (dev->irq) {
1221		dev->read_subdev = s;
1222		s->subdev_flags	|= SDF_CMD_READ;
1223		s->len_chanlist	= s->n_chan;
1224		s->do_cmdtest	= dt282x_ai_cmdtest;
1225		s->do_cmd	= dt282x_ai_cmd;
1226		s->cancel	= dt282x_ai_cancel;
1227	}
1228
1229	/* Analog Output subdevice */
1230	s = &dev->subdevices[1];
1231	if (board->dachan) {
1232		s->type		= COMEDI_SUBD_AO;
1233		s->subdev_flags	= SDF_WRITABLE;
1234		s->n_chan	= board->dachan;
1235		s->maxdata	= board->ao_maxdata;
1236		/* ranges are per-channel, set by jumpers on the board */
1237		s->range_table	= &dt282x_ao_range;
1238		s->insn_write	= dt282x_ao_insn_write;
1239		s->insn_read	= comedi_readback_insn_read;
1240		if (dev->irq) {
1241			dev->write_subdev = s;
1242			s->subdev_flags	|= SDF_CMD_WRITE;
1243			s->len_chanlist	= s->n_chan;
1244			s->do_cmdtest	= dt282x_ao_cmdtest;
1245			s->do_cmd	= dt282x_ao_cmd;
1246			s->cancel	= dt282x_ao_cancel;
1247		}
1248
1249		ret = comedi_alloc_subdev_readback(s);
1250		if (ret)
1251			return ret;
1252	} else {
1253		s->type		= COMEDI_SUBD_UNUSED;
1254	}
1255
1256	/* Digital I/O subdevice */
1257	s = &dev->subdevices[2];
1258	s->type		= COMEDI_SUBD_DIO;
1259	s->subdev_flags	= SDF_READABLE | SDF_WRITABLE;
1260	s->n_chan	= 16;
1261	s->maxdata	= 1;
1262	s->range_table	= &range_digital;
1263	s->insn_bits	= dt282x_dio_insn_bits;
1264	s->insn_config	= dt282x_dio_insn_config;
1265
1266	return 0;
1267}
1268
1269static void dt282x_detach(struct comedi_device *dev)
1270{
1271	dt282x_free_dma(dev);
1272	comedi_legacy_detach(dev);
1273}
1274
1275static struct comedi_driver dt282x_driver = {
1276	.driver_name	= "dt282x",
1277	.module		= THIS_MODULE,
1278	.attach		= dt282x_attach,
1279	.detach		= dt282x_detach,
1280	.board_name	= &boardtypes[0].name,
1281	.num_names	= ARRAY_SIZE(boardtypes),
1282	.offset		= sizeof(struct dt282x_board),
1283};
1284module_comedi_driver(dt282x_driver);
1285
1286MODULE_AUTHOR("Comedi http://www.comedi.org");
1287MODULE_DESCRIPTION("Comedi driver for Data Translation DT2821 series");
1288MODULE_LICENSE("GPL");
1289