das1800.c revision 65a62aaec2e888b6271a4f302f10ad72e966cc10
1/*
2    comedi/drivers/das1800.c
3    Driver for Keitley das1700/das1800 series boards
4    Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
5
6    COMEDI - Linux Control and Measurement Device Interface
7    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18*/
19/*
20Driver: das1800
21Description: Keithley Metrabyte DAS1800 (& compatibles)
22Author: Frank Mori Hess <fmhess@users.sourceforge.net>
23Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
24  DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
25  DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
26  DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
27  DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
28  DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
29  DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
30  DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
31  DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
32  DAS-1802AO (das-1802ao)
33Status: works
34
35The waveform analog output on the 'ao' cards is not supported.
36If you need it, send me (Frank Hess) an email.
37
38Configuration options:
39  [0] - I/O port base address
40  [1] - IRQ (optional, required for timed or externally triggered conversions)
41  [2] - DMA0 (optional, requires irq)
42  [3] - DMA1 (optional, requires irq and dma0)
43*/
44/*
45
46This driver supports the following Keithley boards:
47
48das-1701st
49das-1701st-da
50das-1701ao
51das-1702st
52das-1702st-da
53das-1702hr
54das-1702hr-da
55das-1702ao
56das-1801st
57das-1801st-da
58das-1801hc
59das-1801ao
60das-1802st
61das-1802st-da
62das-1802hr
63das-1802hr-da
64das-1802hc
65das-1802ao
66
67Options:
68	[0] - base io address
69	[1] - irq (optional, required for timed or externally triggered conversions)
70	[2] - dma0 (optional, requires irq)
71	[3] - dma1 (optional, requires irq and dma0)
72
73irq can be omitted, although the cmd interface will not work without it.
74
75analog input cmd triggers supported:
76	start_src:      TRIG_NOW | TRIG_EXT
77	scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
78	scan_end_src:   TRIG_COUNT
79	convert_src:    TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
80	stop_src:       TRIG_COUNT | TRIG_EXT | TRIG_NONE
81
82scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
83'burst mode' which limits the valid conversion time to 64 microseconds
84(convert_arg <= 64000).  This limitation does not apply if scan_begin_src
85is TRIG_FOLLOW.
86
87NOTES:
88Only the DAS-1801ST has been tested by me.
89Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
90
91TODO:
92	Make it automatically allocate irq and dma channels if they are not specified
93	Add support for analog out on 'ao' cards
94	read insn for analog out
95*/
96
97#include <linux/module.h>
98#include <linux/interrupt.h>
99#include <linux/slab.h>
100#include <linux/io.h>
101#include "../comedidev.h"
102
103#include <asm/dma.h>
104
105#include "8253.h"
106#include "comedi_fc.h"
107
108/* misc. defines */
109#define DAS1800_SIZE           16	/* uses 16 io addresses */
110#define FIFO_SIZE              1024	/*  1024 sample fifo */
111#define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
112#define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
113
114/* Registers for the das1800 */
115#define DAS1800_FIFO            0x0
116#define DAS1800_QRAM            0x0
117#define DAS1800_DAC             0x0
118#define DAS1800_SELECT          0x2
119#define   ADC                     0x0
120#define   QRAM                    0x1
121#define   DAC(a)                  (0x2 + a)
122#define DAS1800_DIGITAL         0x3
123#define DAS1800_CONTROL_A       0x4
124#define   FFEN                    0x1
125#define   CGEN                    0x4
126#define   CGSL                    0x8
127#define   TGEN                    0x10
128#define   TGSL                    0x20
129#define   ATEN                    0x80
130#define DAS1800_CONTROL_B       0x5
131#define   DMA_CH5                 0x1
132#define   DMA_CH6                 0x2
133#define   DMA_CH7                 0x3
134#define   DMA_CH5_CH6             0x5
135#define   DMA_CH6_CH7             0x6
136#define   DMA_CH7_CH5             0x7
137#define   DMA_ENABLED             0x3	/* mask used to determine if dma is enabled */
138#define   DMA_DUAL                0x4
139#define   IRQ3                    0x8
140#define   IRQ5                    0x10
141#define   IRQ7                    0x18
142#define   IRQ10                   0x28
143#define   IRQ11                   0x30
144#define   IRQ15                   0x38
145#define   FIMD                    0x40
146#define DAS1800_CONTROL_C       0X6
147#define   IPCLK                   0x1
148#define   XPCLK                   0x3
149#define   BMDE                    0x4
150#define   CMEN                    0x8
151#define   UQEN                    0x10
152#define   SD                      0x40
153#define   UB                      0x80
154#define DAS1800_STATUS          0x7
155/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
156#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
157#define   INT                     0x1
158#define   DMATC                   0x2
159#define   CT0TC                   0x8
160#define   OVF                     0x10
161#define   FHF                     0x20
162#define   FNE                     0x40
163#define   CVEN_MASK               0x40	/*  masks CVEN on write */
164#define   CVEN                    0x80
165#define DAS1800_BURST_LENGTH    0x8
166#define DAS1800_BURST_RATE      0x9
167#define DAS1800_QRAM_ADDRESS    0xa
168#define DAS1800_COUNTER         0xc
169
170#define IOBASE2                   0x400	/* offset of additional ioports used on 'ao' cards */
171
172enum {
173	das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
174	das1702hr_da,
175	das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
176	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
177};
178
179/* analog input ranges */
180static const struct comedi_lrange range_ai_das1801 = {
181	8,
182	{
183	 RANGE(-5, 5),
184	 RANGE(-1, 1),
185	 RANGE(-0.1, 0.1),
186	 RANGE(-0.02, 0.02),
187	 RANGE(0, 5),
188	 RANGE(0, 1),
189	 RANGE(0, 0.1),
190	 RANGE(0, 0.02),
191	 }
192};
193
194static const struct comedi_lrange range_ai_das1802 = {
195	8,
196	{
197	 RANGE(-10, 10),
198	 RANGE(-5, 5),
199	 RANGE(-2.5, 2.5),
200	 RANGE(-1.25, 1.25),
201	 RANGE(0, 10),
202	 RANGE(0, 5),
203	 RANGE(0, 2.5),
204	 RANGE(0, 1.25),
205	 }
206};
207
208struct das1800_board {
209	const char *name;
210	int ai_speed;		/* max conversion period in nanoseconds */
211	int resolution;		/* bits of ai resolution */
212	int qram_len;		/* length of card's channel / gain queue */
213	int common;		/* supports AREF_COMMON flag */
214	int do_n_chan;		/* number of digital output channels */
215	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
216	int ao_n_chan;		/* number of analog out channels */
217	const struct comedi_lrange *range_ai;	/* available input ranges */
218};
219
220/* Warning: the maximum conversion speeds listed below are
221 * not always achievable depending on board setup (see
222 * user manual.)
223 */
224static const struct das1800_board das1800_boards[] = {
225	{
226	 .name = "das-1701st",
227	 .ai_speed = 6250,
228	 .resolution = 12,
229	 .qram_len = 256,
230	 .common = 1,
231	 .do_n_chan = 4,
232	 .ao_ability = 0,
233	 .ao_n_chan = 0,
234	 .range_ai = &range_ai_das1801,
235	 },
236	{
237	 .name = "das-1701st-da",
238	 .ai_speed = 6250,
239	 .resolution = 12,
240	 .qram_len = 256,
241	 .common = 1,
242	 .do_n_chan = 4,
243	 .ao_ability = 1,
244	 .ao_n_chan = 4,
245	 .range_ai = &range_ai_das1801,
246	 },
247	{
248	 .name = "das-1702st",
249	 .ai_speed = 6250,
250	 .resolution = 12,
251	 .qram_len = 256,
252	 .common = 1,
253	 .do_n_chan = 4,
254	 .ao_ability = 0,
255	 .ao_n_chan = 0,
256	 .range_ai = &range_ai_das1802,
257	 },
258	{
259	 .name = "das-1702st-da",
260	 .ai_speed = 6250,
261	 .resolution = 12,
262	 .qram_len = 256,
263	 .common = 1,
264	 .do_n_chan = 4,
265	 .ao_ability = 1,
266	 .ao_n_chan = 4,
267	 .range_ai = &range_ai_das1802,
268	 },
269	{
270	 .name = "das-1702hr",
271	 .ai_speed = 20000,
272	 .resolution = 16,
273	 .qram_len = 256,
274	 .common = 1,
275	 .do_n_chan = 4,
276	 .ao_ability = 0,
277	 .ao_n_chan = 0,
278	 .range_ai = &range_ai_das1802,
279	 },
280	{
281	 .name = "das-1702hr-da",
282	 .ai_speed = 20000,
283	 .resolution = 16,
284	 .qram_len = 256,
285	 .common = 1,
286	 .do_n_chan = 4,
287	 .ao_ability = 1,
288	 .ao_n_chan = 2,
289	 .range_ai = &range_ai_das1802,
290	 },
291	{
292	 .name = "das-1701ao",
293	 .ai_speed = 6250,
294	 .resolution = 12,
295	 .qram_len = 256,
296	 .common = 1,
297	 .do_n_chan = 4,
298	 .ao_ability = 2,
299	 .ao_n_chan = 2,
300	 .range_ai = &range_ai_das1801,
301	 },
302	{
303	 .name = "das-1702ao",
304	 .ai_speed = 6250,
305	 .resolution = 12,
306	 .qram_len = 256,
307	 .common = 1,
308	 .do_n_chan = 4,
309	 .ao_ability = 2,
310	 .ao_n_chan = 2,
311	 .range_ai = &range_ai_das1802,
312	 },
313	{
314	 .name = "das-1801st",
315	 .ai_speed = 3000,
316	 .resolution = 12,
317	 .qram_len = 256,
318	 .common = 1,
319	 .do_n_chan = 4,
320	 .ao_ability = 0,
321	 .ao_n_chan = 0,
322	 .range_ai = &range_ai_das1801,
323	 },
324	{
325	 .name = "das-1801st-da",
326	 .ai_speed = 3000,
327	 .resolution = 12,
328	 .qram_len = 256,
329	 .common = 1,
330	 .do_n_chan = 4,
331	 .ao_ability = 0,
332	 .ao_n_chan = 4,
333	 .range_ai = &range_ai_das1801,
334	 },
335	{
336	 .name = "das-1802st",
337	 .ai_speed = 3000,
338	 .resolution = 12,
339	 .qram_len = 256,
340	 .common = 1,
341	 .do_n_chan = 4,
342	 .ao_ability = 0,
343	 .ao_n_chan = 0,
344	 .range_ai = &range_ai_das1802,
345	 },
346	{
347	 .name = "das-1802st-da",
348	 .ai_speed = 3000,
349	 .resolution = 12,
350	 .qram_len = 256,
351	 .common = 1,
352	 .do_n_chan = 4,
353	 .ao_ability = 1,
354	 .ao_n_chan = 4,
355	 .range_ai = &range_ai_das1802,
356	 },
357	{
358	 .name = "das-1802hr",
359	 .ai_speed = 10000,
360	 .resolution = 16,
361	 .qram_len = 256,
362	 .common = 1,
363	 .do_n_chan = 4,
364	 .ao_ability = 0,
365	 .ao_n_chan = 0,
366	 .range_ai = &range_ai_das1802,
367	 },
368	{
369	 .name = "das-1802hr-da",
370	 .ai_speed = 10000,
371	 .resolution = 16,
372	 .qram_len = 256,
373	 .common = 1,
374	 .do_n_chan = 4,
375	 .ao_ability = 1,
376	 .ao_n_chan = 2,
377	 .range_ai = &range_ai_das1802,
378	 },
379	{
380	 .name = "das-1801hc",
381	 .ai_speed = 3000,
382	 .resolution = 12,
383	 .qram_len = 64,
384	 .common = 0,
385	 .do_n_chan = 8,
386	 .ao_ability = 1,
387	 .ao_n_chan = 2,
388	 .range_ai = &range_ai_das1801,
389	 },
390	{
391	 .name = "das-1802hc",
392	 .ai_speed = 3000,
393	 .resolution = 12,
394	 .qram_len = 64,
395	 .common = 0,
396	 .do_n_chan = 8,
397	 .ao_ability = 1,
398	 .ao_n_chan = 2,
399	 .range_ai = &range_ai_das1802,
400	 },
401	{
402	 .name = "das-1801ao",
403	 .ai_speed = 3000,
404	 .resolution = 12,
405	 .qram_len = 256,
406	 .common = 1,
407	 .do_n_chan = 4,
408	 .ao_ability = 2,
409	 .ao_n_chan = 2,
410	 .range_ai = &range_ai_das1801,
411	 },
412	{
413	 .name = "das-1802ao",
414	 .ai_speed = 3000,
415	 .resolution = 12,
416	 .qram_len = 256,
417	 .common = 1,
418	 .do_n_chan = 4,
419	 .ao_ability = 2,
420	 .ao_n_chan = 2,
421	 .range_ai = &range_ai_das1802,
422	 },
423};
424
425struct das1800_private {
426	volatile unsigned int count;	/* number of data points left to be taken */
427	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
428	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
429	int irq_dma_bits;	/* bits for control register b */
430	/* dma bits for control register b, stored so that dma can be
431	 * turned on and off */
432	int dma_bits;
433	unsigned int dma0;	/* dma channels used */
434	unsigned int dma1;
435	volatile unsigned int dma_current;	/* dma channel currently in use */
436	uint16_t *ai_buf0;	/* pointers to dma buffers */
437	uint16_t *ai_buf1;
438	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
439	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
440	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
441	unsigned short ao_update_bits;	/* remembers the last write to the
442					 * 'update' dac */
443};
444
445/* analog out range for 'ao' boards */
446/*
447static const struct comedi_lrange range_ao_2 = {
448	2,
449	{
450		RANGE(-10, 10),
451		RANGE(-5, 5),
452	}
453};
454*/
455
456static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
457					    uint16_t sample)
458{
459	const struct das1800_board *thisboard = comedi_board(dev);
460
461	sample += 1 << (thisboard->resolution - 1);
462	return sample;
463}
464
465static void munge_data(struct comedi_device *dev, uint16_t * array,
466		       unsigned int num_elements)
467{
468	unsigned int i;
469	int unipolar;
470
471	/* see if card is using a unipolar or bipolar range so we can munge data correctly */
472	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
473
474	/* convert to unsigned type if we are in a bipolar mode */
475	if (!unipolar) {
476		for (i = 0; i < num_elements; i++)
477			array[i] = munge_bipolar_sample(dev, array[i]);
478	}
479}
480
481static void das1800_handle_fifo_half_full(struct comedi_device *dev,
482					  struct comedi_subdevice *s)
483{
484	struct das1800_private *devpriv = dev->private;
485	int numPoints = 0;	/* number of points to read */
486	struct comedi_cmd *cmd = &s->async->cmd;
487
488	numPoints = FIFO_SIZE / 2;
489	/* if we only need some of the points */
490	if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
491		numPoints = devpriv->count;
492	insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
493	munge_data(dev, devpriv->ai_buf0, numPoints);
494	cfc_write_array_to_buffer(s, devpriv->ai_buf0,
495				  numPoints * sizeof(devpriv->ai_buf0[0]));
496	if (cmd->stop_src == TRIG_COUNT)
497		devpriv->count -= numPoints;
498	return;
499}
500
501static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
502					  struct comedi_subdevice *s)
503{
504	struct das1800_private *devpriv = dev->private;
505	unsigned short dpnt;
506	int unipolar;
507	struct comedi_cmd *cmd = &s->async->cmd;
508
509	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
510
511	while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
512		if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
513			break;
514		dpnt = inw(dev->iobase + DAS1800_FIFO);
515		/* convert to unsigned type if we are in a bipolar mode */
516		if (!unipolar)
517			;
518		dpnt = munge_bipolar_sample(dev, dpnt);
519		cfc_write_to_buffer(s, dpnt);
520		if (cmd->stop_src == TRIG_COUNT)
521			devpriv->count--;
522	}
523
524	return;
525}
526
527/* Utility function used by das1800_flush_dma() and das1800_handle_dma().
528 * Assumes dma lock is held */
529static void das1800_flush_dma_channel(struct comedi_device *dev,
530				      struct comedi_subdevice *s,
531				      unsigned int channel, uint16_t *buffer)
532{
533	struct das1800_private *devpriv = dev->private;
534	unsigned int num_bytes, num_samples;
535	struct comedi_cmd *cmd = &s->async->cmd;
536
537	disable_dma(channel);
538
539	/* clear flip-flop to make sure 2-byte registers
540	 * get set correctly */
541	clear_dma_ff(channel);
542
543	/*  figure out how many points to read */
544	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
545	num_samples = num_bytes / sizeof(short);
546
547	/* if we only need some of the points */
548	if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
549		num_samples = devpriv->count;
550
551	munge_data(dev, buffer, num_samples);
552	cfc_write_array_to_buffer(s, buffer, num_bytes);
553	if (s->async->cmd.stop_src == TRIG_COUNT)
554		devpriv->count -= num_samples;
555
556	return;
557}
558
559/* flushes remaining data from board when external trigger has stopped acquisition
560 * and we are using dma transfers */
561static void das1800_flush_dma(struct comedi_device *dev,
562			      struct comedi_subdevice *s)
563{
564	struct das1800_private *devpriv = dev->private;
565	unsigned long flags;
566	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
567
568	flags = claim_dma_lock();
569	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
570				  devpriv->dma_current_buf);
571
572	if (dual_dma) {
573		/*  switch to other channel and flush it */
574		if (devpriv->dma_current == devpriv->dma0) {
575			devpriv->dma_current = devpriv->dma1;
576			devpriv->dma_current_buf = devpriv->ai_buf1;
577		} else {
578			devpriv->dma_current = devpriv->dma0;
579			devpriv->dma_current_buf = devpriv->ai_buf0;
580		}
581		das1800_flush_dma_channel(dev, s, devpriv->dma_current,
582					  devpriv->dma_current_buf);
583	}
584
585	release_dma_lock(flags);
586
587	/*  get any remaining samples in fifo */
588	das1800_handle_fifo_not_empty(dev, s);
589
590	return;
591}
592
593static void das1800_handle_dma(struct comedi_device *dev,
594			       struct comedi_subdevice *s, unsigned int status)
595{
596	struct das1800_private *devpriv = dev->private;
597	unsigned long flags;
598	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
599
600	flags = claim_dma_lock();
601	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
602				  devpriv->dma_current_buf);
603	/*  re-enable  dma channel */
604	set_dma_addr(devpriv->dma_current,
605		     virt_to_bus(devpriv->dma_current_buf));
606	set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
607	enable_dma(devpriv->dma_current);
608	release_dma_lock(flags);
609
610	if (status & DMATC) {
611		/*  clear DMATC interrupt bit */
612		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
613		/*  switch dma channels for next time, if appropriate */
614		if (dual_dma) {
615			/*  read data from the other channel next time */
616			if (devpriv->dma_current == devpriv->dma0) {
617				devpriv->dma_current = devpriv->dma1;
618				devpriv->dma_current_buf = devpriv->ai_buf1;
619			} else {
620				devpriv->dma_current = devpriv->dma0;
621				devpriv->dma_current_buf = devpriv->ai_buf0;
622			}
623		}
624	}
625
626	return;
627}
628
629static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
630{
631	struct das1800_private *devpriv = dev->private;
632
633	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
634	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
635	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
636	if (devpriv->dma0)
637		disable_dma(devpriv->dma0);
638	if (devpriv->dma1)
639		disable_dma(devpriv->dma1);
640	return 0;
641}
642
643/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
644static void das1800_ai_handler(struct comedi_device *dev)
645{
646	struct das1800_private *devpriv = dev->private;
647	struct comedi_subdevice *s = &dev->subdevices[0];
648	struct comedi_async *async = s->async;
649	struct comedi_cmd *cmd = &async->cmd;
650	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
651
652	async->events = 0;
653	/*  select adc for base address + 0 */
654	outb(ADC, dev->iobase + DAS1800_SELECT);
655	/*  dma buffer full */
656	if (devpriv->irq_dma_bits & DMA_ENABLED) {
657		/*  look for data from dma transfer even if dma terminal count hasn't happened yet */
658		das1800_handle_dma(dev, s, status);
659	} else if (status & FHF) {	/*  if fifo half full */
660		das1800_handle_fifo_half_full(dev, s);
661	} else if (status & FNE) {	/*  if fifo not empty */
662		das1800_handle_fifo_not_empty(dev, s);
663	}
664
665	async->events |= COMEDI_CB_BLOCK;
666	/* if the card's fifo has overflowed */
667	if (status & OVF) {
668		/*  clear OVF interrupt bit */
669		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
670		comedi_error(dev, "DAS1800 FIFO overflow");
671		das1800_cancel(dev, s);
672		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
673		comedi_event(dev, s);
674		return;
675	}
676	/*  stop taking data if appropriate */
677	/* stop_src TRIG_EXT */
678	if (status & CT0TC) {
679		/*  clear CT0TC interrupt bit */
680		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
681		/*  make sure we get all remaining data from board before quitting */
682		if (devpriv->irq_dma_bits & DMA_ENABLED)
683			das1800_flush_dma(dev, s);
684		else
685			das1800_handle_fifo_not_empty(dev, s);
686		das1800_cancel(dev, s);	/* disable hardware conversions */
687		async->events |= COMEDI_CB_EOA;
688	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	/*  stop_src TRIG_COUNT */
689		das1800_cancel(dev, s);	/* disable hardware conversions */
690		async->events |= COMEDI_CB_EOA;
691	}
692
693	comedi_event(dev, s);
694
695	return;
696}
697
698static int das1800_ai_poll(struct comedi_device *dev,
699			   struct comedi_subdevice *s)
700{
701	unsigned long flags;
702
703	/*  prevent race with interrupt handler */
704	spin_lock_irqsave(&dev->spinlock, flags);
705	das1800_ai_handler(dev);
706	spin_unlock_irqrestore(&dev->spinlock, flags);
707
708	return s->async->buf_write_count - s->async->buf_read_count;
709}
710
711static irqreturn_t das1800_interrupt(int irq, void *d)
712{
713	struct comedi_device *dev = d;
714	unsigned int status;
715
716	if (!dev->attached) {
717		comedi_error(dev, "premature interrupt");
718		return IRQ_HANDLED;
719	}
720
721	/* Prevent race with das1800_ai_poll() on multi processor systems.
722	 * Also protects indirect addressing in das1800_ai_handler */
723	spin_lock(&dev->spinlock);
724	status = inb(dev->iobase + DAS1800_STATUS);
725
726	/* if interrupt was not caused by das-1800 */
727	if (!(status & INT)) {
728		spin_unlock(&dev->spinlock);
729		return IRQ_NONE;
730	}
731	/* clear the interrupt status bit INT */
732	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
733	/*  handle interrupt */
734	das1800_ai_handler(dev);
735
736	spin_unlock(&dev->spinlock);
737	return IRQ_HANDLED;
738}
739
740/* converts requested conversion timing to timing compatible with
741 * hardware, used only when card is in 'burst mode'
742 */
743static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
744{
745	unsigned int micro_sec;
746
747	/*  in burst mode, the maximum conversion time is 64 microseconds */
748	if (convert_arg > 64000)
749		convert_arg = 64000;
750
751	/*  the conversion time must be an integral number of microseconds */
752	switch (round_mode) {
753	case TRIG_ROUND_NEAREST:
754	default:
755		micro_sec = (convert_arg + 500) / 1000;
756		break;
757	case TRIG_ROUND_DOWN:
758		micro_sec = convert_arg / 1000;
759		break;
760	case TRIG_ROUND_UP:
761		micro_sec = (convert_arg - 1) / 1000 + 1;
762		break;
763	}
764
765	/*  return number of nanoseconds */
766	return micro_sec * 1000;
767}
768
769/* test analog input cmd */
770static int das1800_ai_do_cmdtest(struct comedi_device *dev,
771				 struct comedi_subdevice *s,
772				 struct comedi_cmd *cmd)
773{
774	const struct das1800_board *thisboard = comedi_board(dev);
775	struct das1800_private *devpriv = dev->private;
776	int err = 0;
777	unsigned int tmp_arg;
778	int i;
779	int unipolar;
780
781	/* Step 1 : check if triggers are trivially valid */
782
783	err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
784	err |= cfc_check_trigger_src(&cmd->scan_begin_src,
785					TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
786	err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
787	err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
788	err |= cfc_check_trigger_src(&cmd->stop_src,
789					TRIG_COUNT | TRIG_EXT | TRIG_NONE);
790
791	if (err)
792		return 1;
793
794	/* Step 2a : make sure trigger sources are unique */
795
796	err |= cfc_check_trigger_is_unique(cmd->start_src);
797	err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
798	err |= cfc_check_trigger_is_unique(cmd->convert_src);
799	err |= cfc_check_trigger_is_unique(cmd->stop_src);
800
801	/* Step 2b : and mutually compatible */
802
803	if (cmd->scan_begin_src != TRIG_FOLLOW &&
804	    cmd->convert_src != TRIG_TIMER)
805		err |= -EINVAL;
806
807	if (err)
808		return 2;
809
810	/* Step 3: check if arguments are trivially valid */
811
812	err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
813
814	if (cmd->convert_src == TRIG_TIMER)
815		err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
816						 thisboard->ai_speed);
817
818	err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
819	err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
820
821	switch (cmd->stop_src) {
822	case TRIG_COUNT:
823		err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
824		break;
825	case TRIG_NONE:
826		err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
827		break;
828	default:
829		break;
830	}
831
832	if (err)
833		return 3;
834
835	/* step 4: fix up any arguments */
836
837	if (cmd->convert_src == TRIG_TIMER) {
838		/*  if we are not in burst mode */
839		if (cmd->scan_begin_src == TRIG_FOLLOW) {
840			tmp_arg = cmd->convert_arg;
841			/* calculate counter values that give desired timing */
842			i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
843						  &devpriv->divisor1,
844						  &devpriv->divisor2,
845						  &cmd->convert_arg,
846						  cmd->flags);
847			if (tmp_arg != cmd->convert_arg)
848				err++;
849		}
850		/*  if we are in burst mode */
851		else {
852			/*  check that convert_arg is compatible */
853			tmp_arg = cmd->convert_arg;
854			cmd->convert_arg =
855			    burst_convert_arg(cmd->convert_arg,
856					      cmd->flags & TRIG_ROUND_MASK);
857			if (tmp_arg != cmd->convert_arg)
858				err++;
859
860			if (cmd->scan_begin_src == TRIG_TIMER) {
861				/*  if scans are timed faster than conversion rate allows */
862				if (cmd->convert_arg * cmd->chanlist_len >
863				    cmd->scan_begin_arg) {
864					cmd->scan_begin_arg =
865					    cmd->convert_arg *
866					    cmd->chanlist_len;
867					err++;
868				}
869				tmp_arg = cmd->scan_begin_arg;
870				/* calculate counter values that give desired timing */
871				i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
872							  &devpriv->divisor1,
873							  &devpriv->divisor2,
874							  &cmd->scan_begin_arg,
875							  cmd->flags);
876				if (tmp_arg != cmd->scan_begin_arg)
877					err++;
878			}
879		}
880	}
881
882	if (err)
883		return 4;
884
885	/*  make sure user is not trying to mix unipolar and bipolar ranges */
886	if (cmd->chanlist) {
887		unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
888		for (i = 1; i < cmd->chanlist_len; i++) {
889			if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
890				comedi_error(dev,
891					     "unipolar and bipolar ranges cannot be mixed in the chanlist");
892				err++;
893				break;
894			}
895		}
896	}
897
898	if (err)
899		return 5;
900
901	return 0;
902}
903
904/* returns appropriate bits for control register a, depending on command */
905static int control_a_bits(const struct comedi_cmd *cmd)
906{
907	int control_a;
908
909	control_a = FFEN;	/* enable fifo */
910	if (cmd->stop_src == TRIG_EXT)
911		control_a |= ATEN;
912	switch (cmd->start_src) {
913	case TRIG_EXT:
914		control_a |= TGEN | CGSL;
915		break;
916	case TRIG_NOW:
917		control_a |= CGEN;
918		break;
919	default:
920		break;
921	}
922
923	return control_a;
924}
925
926/* returns appropriate bits for control register c, depending on command */
927static int control_c_bits(const struct comedi_cmd *cmd)
928{
929	int control_c;
930	int aref;
931
932	/* set clock source to internal or external, select analog reference,
933	 * select unipolar / bipolar
934	 */
935	aref = CR_AREF(cmd->chanlist[0]);
936	control_c = UQEN;	/* enable upper qram addresses */
937	if (aref != AREF_DIFF)
938		control_c |= SD;
939	if (aref == AREF_COMMON)
940		control_c |= CMEN;
941	/* if a unipolar range was selected */
942	if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
943		control_c |= UB;
944	switch (cmd->scan_begin_src) {
945	case TRIG_FOLLOW:	/*  not in burst mode */
946		switch (cmd->convert_src) {
947		case TRIG_TIMER:
948			/* trig on cascaded counters */
949			control_c |= IPCLK;
950			break;
951		case TRIG_EXT:
952			/* trig on falling edge of external trigger */
953			control_c |= XPCLK;
954			break;
955		default:
956			break;
957		}
958		break;
959	case TRIG_TIMER:
960		/*  burst mode with internal pacer clock */
961		control_c |= BMDE | IPCLK;
962		break;
963	case TRIG_EXT:
964		/*  burst mode with external trigger */
965		control_c |= BMDE | XPCLK;
966		break;
967	default:
968		break;
969	}
970
971	return control_c;
972}
973
974/* loads counters with divisor1, divisor2 from private structure */
975static int das1800_set_frequency(struct comedi_device *dev)
976{
977	struct das1800_private *devpriv = dev->private;
978	int err = 0;
979
980	/*  counter 1, mode 2 */
981	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
982		       2))
983		err++;
984	/*  counter 2, mode 2 */
985	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
986		       2))
987		err++;
988	if (err)
989		return -1;
990
991	return 0;
992}
993
994/* sets up counters */
995static int setup_counters(struct comedi_device *dev,
996			  const struct comedi_cmd *cmd)
997{
998	struct das1800_private *devpriv = dev->private;
999	unsigned int period;
1000
1001	/*  setup cascaded counters for conversion/scan frequency */
1002	switch (cmd->scan_begin_src) {
1003	case TRIG_FOLLOW:	/*  not in burst mode */
1004		if (cmd->convert_src == TRIG_TIMER) {
1005			/* set conversion frequency */
1006			period = cmd->convert_arg;
1007			i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1008						  &devpriv->divisor1,
1009						  &devpriv->divisor2,
1010						  &period, cmd->flags);
1011			if (das1800_set_frequency(dev) < 0)
1012				return -1;
1013		}
1014		break;
1015	case TRIG_TIMER:	/*  in burst mode */
1016		/* set scan frequency */
1017		period = cmd->scan_begin_arg;
1018		i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1019					  &devpriv->divisor1,
1020					  &devpriv->divisor2,
1021					  &period, cmd->flags);
1022		if (das1800_set_frequency(dev) < 0)
1023			return -1;
1024		break;
1025	default:
1026		break;
1027	}
1028
1029	/*  setup counter 0 for 'about triggering' */
1030	if (cmd->stop_src == TRIG_EXT) {
1031		/*  load counter 0 in mode 0 */
1032		i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1033	}
1034
1035	return 0;
1036}
1037
1038/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1039static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
1040{
1041	unsigned int size = DMA_BUF_SIZE;
1042	static const int sample_size = 2;	/*  size in bytes of one sample from board */
1043	unsigned int fill_time = 300000000;	/*  target time in nanoseconds for filling dma buffer */
1044	unsigned int max_size;	/*  maximum size we will allow for a transfer */
1045
1046	/*  make dma buffer fill in 0.3 seconds for timed modes */
1047	switch (cmd->scan_begin_src) {
1048	case TRIG_FOLLOW:	/*  not in burst mode */
1049		if (cmd->convert_src == TRIG_TIMER)
1050			size = (fill_time / cmd->convert_arg) * sample_size;
1051		break;
1052	case TRIG_TIMER:
1053		size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1054		    sample_size;
1055		break;
1056	default:
1057		size = DMA_BUF_SIZE;
1058		break;
1059	}
1060
1061	/*  set a minimum and maximum size allowed */
1062	max_size = DMA_BUF_SIZE;
1063	/*  if we are taking limited number of conversions, limit transfer size to that */
1064	if (cmd->stop_src == TRIG_COUNT &&
1065	    cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1066		max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1067
1068	if (size > max_size)
1069		size = max_size;
1070	if (size < sample_size)
1071		size = sample_size;
1072
1073	return size;
1074}
1075
1076/* sets up dma */
1077static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
1078{
1079	struct das1800_private *devpriv = dev->private;
1080	unsigned long lock_flags;
1081	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1082
1083	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1084		return;
1085
1086	/* determine a reasonable dma transfer size */
1087	devpriv->dma_transfer_size = suggest_transfer_size(cmd);
1088	lock_flags = claim_dma_lock();
1089	disable_dma(devpriv->dma0);
1090	/* clear flip-flop to make sure 2-byte registers for
1091	 * count and address get set correctly */
1092	clear_dma_ff(devpriv->dma0);
1093	set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1094	/*  set appropriate size of transfer */
1095	set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1096	devpriv->dma_current = devpriv->dma0;
1097	devpriv->dma_current_buf = devpriv->ai_buf0;
1098	enable_dma(devpriv->dma0);
1099	/*  set up dual dma if appropriate */
1100	if (dual_dma) {
1101		disable_dma(devpriv->dma1);
1102		/* clear flip-flop to make sure 2-byte registers for
1103		 * count and address get set correctly */
1104		clear_dma_ff(devpriv->dma1);
1105		set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1106		/*  set appropriate size of transfer */
1107		set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1108		enable_dma(devpriv->dma1);
1109	}
1110	release_dma_lock(lock_flags);
1111
1112	return;
1113}
1114
1115/* programs channel/gain list into card */
1116static void program_chanlist(struct comedi_device *dev,
1117			     const struct comedi_cmd *cmd)
1118{
1119	int i, n, chan_range;
1120	unsigned long irq_flags;
1121	const int range_mask = 0x3;	/* masks unipolar/bipolar bit off range */
1122	const int range_bitshift = 8;
1123
1124	n = cmd->chanlist_len;
1125	/*  spinlock protects indirect addressing */
1126	spin_lock_irqsave(&dev->spinlock, irq_flags);
1127	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1128	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*set QRAM address start */
1129	/* make channel / gain list */
1130	for (i = 0; i < n; i++) {
1131		chan_range =
1132		    CR_CHAN(cmd->chanlist[i]) |
1133		    ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
1134		     range_bitshift);
1135		outw(chan_range, dev->iobase + DAS1800_QRAM);
1136	}
1137	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1138	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1139
1140	return;
1141}
1142
1143/* analog input do_cmd */
1144static int das1800_ai_do_cmd(struct comedi_device *dev,
1145			     struct comedi_subdevice *s)
1146{
1147	struct das1800_private *devpriv = dev->private;
1148	int ret;
1149	int control_a, control_c;
1150	struct comedi_async *async = s->async;
1151	const struct comedi_cmd *cmd = &async->cmd;
1152
1153	if (!dev->irq) {
1154		comedi_error(dev,
1155			     "no irq assigned for das-1800, cannot do hardware conversions");
1156		return -1;
1157	}
1158
1159	/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1160	 * (because dma in handler is unsafe at hard real-time priority) */
1161	if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT))
1162		devpriv->irq_dma_bits &= ~DMA_ENABLED;
1163	else
1164		devpriv->irq_dma_bits |= devpriv->dma_bits;
1165	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
1166	if (cmd->flags & TRIG_WAKE_EOS) {
1167		/*  interrupt fifo not empty */
1168		devpriv->irq_dma_bits &= ~FIMD;
1169	} else {
1170		/*  interrupt fifo half full */
1171		devpriv->irq_dma_bits |= FIMD;
1172	}
1173	/*  determine how many conversions we need */
1174	if (cmd->stop_src == TRIG_COUNT)
1175		devpriv->count = cmd->stop_arg * cmd->chanlist_len;
1176
1177	das1800_cancel(dev, s);
1178
1179	/*  determine proper bits for control registers */
1180	control_a = control_a_bits(cmd);
1181	control_c = control_c_bits(cmd);
1182
1183	/* setup card and start */
1184	program_chanlist(dev, cmd);
1185	ret = setup_counters(dev, cmd);
1186	if (ret < 0) {
1187		comedi_error(dev, "Error setting up counters");
1188		return ret;
1189	}
1190	setup_dma(dev, cmd);
1191	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1192	/*  set conversion rate and length for burst mode */
1193	if (control_c & BMDE) {
1194		/*  program conversion period with number of microseconds minus 1 */
1195		outb(cmd->convert_arg / 1000 - 1,
1196		     dev->iobase + DAS1800_BURST_RATE);
1197		outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1198	}
1199	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	/*  enable irq/dma */
1200	outb(control_a, dev->iobase + DAS1800_CONTROL_A);	/* enable fifo and triggering */
1201	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1202
1203	return 0;
1204}
1205
1206/* read analog input */
1207static int das1800_ai_rinsn(struct comedi_device *dev,
1208			    struct comedi_subdevice *s,
1209			    struct comedi_insn *insn, unsigned int *data)
1210{
1211	const struct das1800_board *thisboard = comedi_board(dev);
1212	int i, n;
1213	int chan, range, aref, chan_range;
1214	int timeout = 1000;
1215	unsigned short dpnt;
1216	int conv_flags = 0;
1217	unsigned long irq_flags;
1218
1219	/* set up analog reference and unipolar / bipolar mode */
1220	aref = CR_AREF(insn->chanspec);
1221	conv_flags |= UQEN;
1222	if (aref != AREF_DIFF)
1223		conv_flags |= SD;
1224	if (aref == AREF_COMMON)
1225		conv_flags |= CMEN;
1226	/* if a unipolar range was selected */
1227	if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1228		conv_flags |= UB;
1229
1230	outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);	/* software conversion enabled */
1231	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1232	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* reset fifo */
1233	outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1234
1235	chan = CR_CHAN(insn->chanspec);
1236	/* mask of unipolar/bipolar bit from range */
1237	range = CR_RANGE(insn->chanspec) & 0x3;
1238	chan_range = chan | (range << 8);
1239	spin_lock_irqsave(&dev->spinlock, irq_flags);
1240	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1241	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/* set QRAM address start */
1242	outw(chan_range, dev->iobase + DAS1800_QRAM);
1243	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1244	outb(ADC, dev->iobase + DAS1800_SELECT);	/* select ADC for baseAddress + 0x0 */
1245
1246	for (n = 0; n < insn->n; n++) {
1247		/* trigger conversion */
1248		outb(0, dev->iobase + DAS1800_FIFO);
1249		for (i = 0; i < timeout; i++) {
1250			if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1251				break;
1252		}
1253		if (i == timeout) {
1254			comedi_error(dev, "timeout");
1255			n = -ETIME;
1256			goto exit;
1257		}
1258		dpnt = inw(dev->iobase + DAS1800_FIFO);
1259		/* shift data to offset binary for bipolar ranges */
1260		if ((conv_flags & UB) == 0)
1261			dpnt += 1 << (thisboard->resolution - 1);
1262		data[n] = dpnt;
1263	}
1264exit:
1265	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1266
1267	return n;
1268}
1269
1270/* writes to an analog output channel */
1271static int das1800_ao_winsn(struct comedi_device *dev,
1272			    struct comedi_subdevice *s,
1273			    struct comedi_insn *insn, unsigned int *data)
1274{
1275	const struct das1800_board *thisboard = comedi_board(dev);
1276	struct das1800_private *devpriv = dev->private;
1277	int chan = CR_CHAN(insn->chanspec);
1278/* int range = CR_RANGE(insn->chanspec); */
1279	int update_chan = thisboard->ao_n_chan - 1;
1280	unsigned short output;
1281	unsigned long irq_flags;
1282
1283	/*   card expects two's complement data */
1284	output = data[0] - (1 << (thisboard->resolution - 1));
1285	/*  if the write is to the 'update' channel, we need to remember its value */
1286	if (chan == update_chan)
1287		devpriv->ao_update_bits = output;
1288	/*  write to channel */
1289	spin_lock_irqsave(&dev->spinlock, irq_flags);
1290	outb(DAC(chan), dev->iobase + DAS1800_SELECT);	/* select dac channel for baseAddress + 0x0 */
1291	outw(output, dev->iobase + DAS1800_DAC);
1292	/*  now we need to write to 'update' channel to update all dac channels */
1293	if (chan != update_chan) {
1294		outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);	/* select 'update' channel for baseAddress + 0x0 */
1295		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1296	}
1297	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1298
1299	return 1;
1300}
1301
1302/* reads from digital input channels */
1303static int das1800_di_rbits(struct comedi_device *dev,
1304			    struct comedi_subdevice *s,
1305			    struct comedi_insn *insn, unsigned int *data)
1306{
1307
1308	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1309	data[0] = 0;
1310
1311	return insn->n;
1312}
1313
1314static int das1800_do_wbits(struct comedi_device *dev,
1315			    struct comedi_subdevice *s,
1316			    struct comedi_insn *insn,
1317			    unsigned int *data)
1318{
1319	if (comedi_dio_update_state(s, data))
1320		outb(s->state, dev->iobase + DAS1800_DIGITAL);
1321
1322	data[1] = s->state;
1323
1324	return insn->n;
1325}
1326
1327static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
1328			    unsigned int dma1)
1329{
1330	struct das1800_private *devpriv = dev->private;
1331	unsigned long flags;
1332
1333	/*  need an irq to do dma */
1334	if (dev->irq && dma0) {
1335		/* encode dma0 and dma1 into 2 digit hexadecimal for switch */
1336		switch ((dma0 & 0x7) | (dma1 << 4)) {
1337		case 0x5:	/*  dma0 == 5 */
1338			devpriv->dma_bits |= DMA_CH5;
1339			break;
1340		case 0x6:	/*  dma0 == 6 */
1341			devpriv->dma_bits |= DMA_CH6;
1342			break;
1343		case 0x7:	/*  dma0 == 7 */
1344			devpriv->dma_bits |= DMA_CH7;
1345			break;
1346		case 0x65:	/*  dma0 == 5, dma1 == 6 */
1347			devpriv->dma_bits |= DMA_CH5_CH6;
1348			break;
1349		case 0x76:	/*  dma0 == 6, dma1 == 7 */
1350			devpriv->dma_bits |= DMA_CH6_CH7;
1351			break;
1352		case 0x57:	/*  dma0 == 7, dma1 == 5 */
1353			devpriv->dma_bits |= DMA_CH7_CH5;
1354			break;
1355		default:
1356			dev_err(dev->class_dev,
1357				"only supports dma channels 5 through 7\n");
1358			dev_err(dev->class_dev,
1359				"Dual dma only allows the following combinations:\n");
1360			dev_err(dev->class_dev,
1361				"dma 5,6 / 6,7 / or 7,5\n");
1362			return -EINVAL;
1363			break;
1364		}
1365		if (request_dma(dma0, dev->driver->driver_name)) {
1366			dev_err(dev->class_dev,
1367				"failed to allocate dma channel %i\n", dma0);
1368			return -EINVAL;
1369		}
1370		devpriv->dma0 = dma0;
1371		devpriv->dma_current = dma0;
1372		if (dma1) {
1373			if (request_dma(dma1, dev->driver->driver_name)) {
1374				dev_err(dev->class_dev,
1375					"failed to allocate dma channel %i\n",
1376					dma1);
1377				return -EINVAL;
1378			}
1379			devpriv->dma1 = dma1;
1380		}
1381		devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1382		if (devpriv->ai_buf0 == NULL)
1383			return -ENOMEM;
1384		devpriv->dma_current_buf = devpriv->ai_buf0;
1385		if (dma1) {
1386			devpriv->ai_buf1 =
1387			    kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1388			if (devpriv->ai_buf1 == NULL)
1389				return -ENOMEM;
1390		}
1391		flags = claim_dma_lock();
1392		disable_dma(devpriv->dma0);
1393		set_dma_mode(devpriv->dma0, DMA_MODE_READ);
1394		if (dma1) {
1395			disable_dma(devpriv->dma1);
1396			set_dma_mode(devpriv->dma1, DMA_MODE_READ);
1397		}
1398		release_dma_lock(flags);
1399	}
1400	return 0;
1401}
1402
1403static int das1800_probe(struct comedi_device *dev)
1404{
1405	int id;
1406	int board;
1407
1408	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
1409	board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
1410
1411	switch (id) {
1412	case 0x3:
1413		if (board == das1801st_da || board == das1802st_da ||
1414		    board == das1701st_da || board == das1702st_da) {
1415			dev_dbg(dev->class_dev, "Board model: %s\n",
1416				das1800_boards[board].name);
1417			return board;
1418		}
1419		printk
1420		    (" Board model (probed, not recommended): das-1800st-da series\n");
1421		return das1801st;
1422		break;
1423	case 0x4:
1424		if (board == das1802hr_da || board == das1702hr_da) {
1425			dev_dbg(dev->class_dev, "Board model: %s\n",
1426				das1800_boards[board].name);
1427			return board;
1428		}
1429		printk
1430		    (" Board model (probed, not recommended): das-1802hr-da\n");
1431		return das1802hr;
1432		break;
1433	case 0x5:
1434		if (board == das1801ao || board == das1802ao ||
1435		    board == das1701ao || board == das1702ao) {
1436			dev_dbg(dev->class_dev, "Board model: %s\n",
1437				das1800_boards[board].name);
1438			return board;
1439		}
1440		printk
1441		    (" Board model (probed, not recommended): das-1800ao series\n");
1442		return das1801ao;
1443		break;
1444	case 0x6:
1445		if (board == das1802hr || board == das1702hr) {
1446			dev_dbg(dev->class_dev, "Board model: %s\n",
1447				das1800_boards[board].name);
1448			return board;
1449		}
1450		printk
1451		    (" Board model (probed, not recommended): das-1802hr\n");
1452		return das1802hr;
1453		break;
1454	case 0x7:
1455		if (board == das1801st || board == das1802st ||
1456		    board == das1701st || board == das1702st) {
1457			dev_dbg(dev->class_dev, "Board model: %s\n",
1458				das1800_boards[board].name);
1459			return board;
1460		}
1461		printk
1462		    (" Board model (probed, not recommended): das-1800st series\n");
1463		return das1801st;
1464		break;
1465	case 0x8:
1466		if (board == das1801hc || board == das1802hc) {
1467			dev_dbg(dev->class_dev, "Board model: %s\n",
1468				das1800_boards[board].name);
1469			return board;
1470		}
1471		printk
1472		    (" Board model (probed, not recommended): das-1800hc series\n");
1473		return das1801hc;
1474		break;
1475	default:
1476		printk
1477		    (" Board model: probe returned 0x%x (unknown, please report)\n",
1478		     id);
1479		return board;
1480		break;
1481	}
1482	return -1;
1483}
1484
1485static int das1800_attach(struct comedi_device *dev,
1486			  struct comedi_devconfig *it)
1487{
1488	const struct das1800_board *thisboard = comedi_board(dev);
1489	struct das1800_private *devpriv;
1490	struct comedi_subdevice *s;
1491	unsigned int irq = it->options[1];
1492	unsigned int dma0 = it->options[2];
1493	unsigned int dma1 = it->options[3];
1494	int board;
1495	int ret;
1496
1497	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1498	if (!devpriv)
1499		return -ENOMEM;
1500
1501	ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1502	if (ret)
1503		return ret;
1504
1505	board = das1800_probe(dev);
1506	if (board < 0) {
1507		dev_err(dev->class_dev, "unable to determine board type\n");
1508		return -ENODEV;
1509	}
1510
1511	dev->board_ptr = das1800_boards + board;
1512	thisboard = comedi_board(dev);
1513	dev->board_name = thisboard->name;
1514
1515	/*  if it is an 'ao' board with fancy analog out then we need extra io ports */
1516	if (thisboard->ao_ability == 2) {
1517		unsigned long iobase2 = dev->iobase + IOBASE2;
1518
1519		ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1520		if (ret)
1521			return ret;
1522		devpriv->iobase2 = iobase2;
1523	}
1524
1525	/* grab our IRQ */
1526	if (irq) {
1527		if (request_irq(irq, das1800_interrupt, 0,
1528				dev->driver->driver_name, dev)) {
1529			dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
1530				irq);
1531			return -EINVAL;
1532		}
1533	}
1534	dev->irq = irq;
1535
1536	/*  set bits that tell card which irq to use */
1537	switch (irq) {
1538	case 0:
1539		break;
1540	case 3:
1541		devpriv->irq_dma_bits |= 0x8;
1542		break;
1543	case 5:
1544		devpriv->irq_dma_bits |= 0x10;
1545		break;
1546	case 7:
1547		devpriv->irq_dma_bits |= 0x18;
1548		break;
1549	case 10:
1550		devpriv->irq_dma_bits |= 0x28;
1551		break;
1552	case 11:
1553		devpriv->irq_dma_bits |= 0x30;
1554		break;
1555	case 15:
1556		devpriv->irq_dma_bits |= 0x38;
1557		break;
1558	default:
1559		dev_err(dev->class_dev, "irq out of range\n");
1560		return -EINVAL;
1561		break;
1562	}
1563
1564	ret = das1800_init_dma(dev, dma0, dma1);
1565	if (ret < 0)
1566		return ret;
1567
1568	if (devpriv->ai_buf0 == NULL) {
1569		devpriv->ai_buf0 =
1570		    kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
1571		if (devpriv->ai_buf0 == NULL)
1572			return -ENOMEM;
1573	}
1574
1575	ret = comedi_alloc_subdevices(dev, 4);
1576	if (ret)
1577		return ret;
1578
1579	/* analog input subdevice */
1580	s = &dev->subdevices[0];
1581	dev->read_subdev = s;
1582	s->type = COMEDI_SUBD_AI;
1583	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
1584	if (thisboard->common)
1585		s->subdev_flags |= SDF_COMMON;
1586	s->n_chan = thisboard->qram_len;
1587	s->len_chanlist = thisboard->qram_len;
1588	s->maxdata = (1 << thisboard->resolution) - 1;
1589	s->range_table = thisboard->range_ai;
1590	s->do_cmd = das1800_ai_do_cmd;
1591	s->do_cmdtest = das1800_ai_do_cmdtest;
1592	s->insn_read = das1800_ai_rinsn;
1593	s->poll = das1800_ai_poll;
1594	s->cancel = das1800_cancel;
1595
1596	/* analog out */
1597	s = &dev->subdevices[1];
1598	if (thisboard->ao_ability == 1) {
1599		s->type = COMEDI_SUBD_AO;
1600		s->subdev_flags = SDF_WRITABLE;
1601		s->n_chan = thisboard->ao_n_chan;
1602		s->maxdata = (1 << thisboard->resolution) - 1;
1603		s->range_table = &range_bipolar10;
1604		s->insn_write = das1800_ao_winsn;
1605	} else {
1606		s->type = COMEDI_SUBD_UNUSED;
1607	}
1608
1609	/* di */
1610	s = &dev->subdevices[2];
1611	s->type = COMEDI_SUBD_DI;
1612	s->subdev_flags = SDF_READABLE;
1613	s->n_chan = 4;
1614	s->maxdata = 1;
1615	s->range_table = &range_digital;
1616	s->insn_bits = das1800_di_rbits;
1617
1618	/* do */
1619	s = &dev->subdevices[3];
1620	s->type = COMEDI_SUBD_DO;
1621	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1622	s->n_chan = thisboard->do_n_chan;
1623	s->maxdata = 1;
1624	s->range_table = &range_digital;
1625	s->insn_bits = das1800_do_wbits;
1626
1627	das1800_cancel(dev, dev->read_subdev);
1628
1629	/*  initialize digital out channels */
1630	outb(0, dev->iobase + DAS1800_DIGITAL);
1631
1632	/*  initialize analog out channels */
1633	if (thisboard->ao_ability == 1) {
1634		/*  select 'update' dac channel for baseAddress + 0x0 */
1635		outb(DAC(thisboard->ao_n_chan - 1),
1636		     dev->iobase + DAS1800_SELECT);
1637		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1638	}
1639
1640	return 0;
1641};
1642
1643static void das1800_detach(struct comedi_device *dev)
1644{
1645	struct das1800_private *devpriv = dev->private;
1646
1647	if (devpriv) {
1648		if (devpriv->dma0)
1649			free_dma(devpriv->dma0);
1650		if (devpriv->dma1)
1651			free_dma(devpriv->dma1);
1652		kfree(devpriv->ai_buf0);
1653		kfree(devpriv->ai_buf1);
1654		if (devpriv->iobase2)
1655			release_region(devpriv->iobase2, DAS1800_SIZE);
1656	}
1657	comedi_legacy_detach(dev);
1658}
1659
1660static struct comedi_driver das1800_driver = {
1661	.driver_name	= "das1800",
1662	.module		= THIS_MODULE,
1663	.attach		= das1800_attach,
1664	.detach		= das1800_detach,
1665	.num_names	= ARRAY_SIZE(das1800_boards),
1666	.board_name	= &das1800_boards[0].name,
1667	.offset		= sizeof(struct das1800_board),
1668};
1669module_comedi_driver(das1800_driver);
1670
1671MODULE_AUTHOR("Comedi http://www.comedi.org");
1672MODULE_DESCRIPTION("Comedi low-level driver");
1673MODULE_LICENSE("GPL");
1674