1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Comedi driver for Keithley DAS-1700/DAS-1800 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 
10 /*
11  * Driver: das1800
12  * Description: Keithley Metrabyte DAS1800 (& compatibles)
13  * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
14  * Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
15  *   DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
16  *   DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
17  *   DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
18  *   DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
19  *   DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
20  *   DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
21  *   DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
22  *   DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
23  *   DAS-1802AO (das-1802ao)
24  * Status: works
25  *
26  * Configuration options:
27  *   [0] - I/O port base address
28  *   [1] - IRQ (optional, required for analog input cmd support)
29  *   [2] - DMA0 (optional, requires irq)
30  *   [3] - DMA1 (optional, requires irq and dma0)
31  *
32  * analog input cmd triggers supported:
33  *
34  *   start_src		TRIG_NOW	command starts immediately
35  *			TRIG_EXT	command starts on external pin TGIN
36  *
37  *   scan_begin_src	TRIG_FOLLOW	paced/external scans start immediately
38  *			TRIG_TIMER	burst scans start periodically
39  *			TRIG_EXT	burst scans start on external pin XPCLK
40  *
41  *   scan_end_src	TRIG_COUNT	scan ends after last channel
42  *
43  *   convert_src	TRIG_TIMER	paced/burst conversions are timed
44  *			TRIG_EXT	conversions on external pin XPCLK
45  *					(requires scan_begin_src == TRIG_FOLLOW)
46  *
47  *   stop_src		TRIG_COUNT	command stops after stop_arg scans
48  *			TRIG_EXT	command stops on external pin TGIN
49  *			TRIG_NONE	command runs until canceled
50  *
51  * If TRIG_EXT is used for both the start_src and stop_src, the first TGIN
52  * trigger starts the command, and the second trigger will stop it. If only
53  * one is TRIG_EXT, the first trigger will either stop or start the command.
54  * The external pin TGIN is normally set for negative edge triggering. It
55  * can be set to positive edge with the CR_INVERT flag. If TRIG_EXT is used
56  * for both the start_src and stop_src they must have the same polarity.
57  *
58  * Minimum conversion speed is limited to 64 microseconds (convert_arg <= 64000)
59  * for 'burst' scans. This limitation does not apply for 'paced' scans. The
60  * maximum conversion speed is limited by the board (convert_arg >= ai_speed).
61  * Maximum conversion speeds are not always achievable depending on the
62  * board setup (see user manual).
63  *
64  * NOTES:
65  * Only the DAS-1801ST has been tested by me.
66  * Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
67  *
68  * The waveform analog output on the 'ao' cards is not supported.
69  * If you need it, send me (Frank Hess) an email.
70  */
71 
72 #include <linux/module.h>
73 #include <linux/interrupt.h>
74 #include <linux/slab.h>
75 #include <linux/io.h>
76 
77 #include "../comedidev.h"
78 
79 #include "comedi_isadma.h"
80 #include "comedi_8254.h"
81 
82 /* misc. defines */
83 #define DAS1800_SIZE           16	/* uses 16 io addresses */
84 #define FIFO_SIZE              1024	/*  1024 sample fifo */
85 #define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
86 
87 /* Registers for the das1800 */
88 #define DAS1800_FIFO            0x0
89 #define DAS1800_QRAM            0x0
90 #define DAS1800_DAC             0x0
91 #define DAS1800_SELECT          0x2
92 #define   ADC                     0x0
93 #define   QRAM                    0x1
94 #define   DAC(a)                  (0x2 + a)
95 #define DAS1800_DIGITAL         0x3
96 #define DAS1800_CONTROL_A       0x4
97 #define   FFEN                    0x1
98 #define   CGEN                    0x4
99 #define   CGSL                    0x8
100 #define   TGEN                    0x10
101 #define   TGSL                    0x20
102 #define   TGPL                    0x40
103 #define   ATEN                    0x80
104 #define DAS1800_CONTROL_B       0x5
105 #define   DMA_CH5                 0x1
106 #define   DMA_CH6                 0x2
107 #define   DMA_CH7                 0x3
108 #define   DMA_CH5_CH6             0x5
109 #define   DMA_CH6_CH7             0x6
110 #define   DMA_CH7_CH5             0x7
111 #define   DMA_ENABLED             0x3
112 #define   DMA_DUAL                0x4
113 #define   IRQ3                    0x8
114 #define   IRQ5                    0x10
115 #define   IRQ7                    0x18
116 #define   IRQ10                   0x28
117 #define   IRQ11                   0x30
118 #define   IRQ15                   0x38
119 #define   FIMD                    0x40
120 #define DAS1800_CONTROL_C       0X6
121 #define   IPCLK                   0x1
122 #define   XPCLK                   0x3
123 #define   BMDE                    0x4
124 #define   CMEN                    0x8
125 #define   UQEN                    0x10
126 #define   SD                      0x40
127 #define   UB                      0x80
128 #define DAS1800_STATUS          0x7
129 #define   INT                     0x1
130 #define   DMATC                   0x2
131 #define   CT0TC                   0x8
132 #define   OVF                     0x10
133 #define   FHF                     0x20
134 #define   FNE                     0x40
135 #define   CVEN                    0x80
136 #define   CVEN_MASK               0x40
137 #define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
138 #define DAS1800_BURST_LENGTH    0x8
139 #define DAS1800_BURST_RATE      0x9
140 #define DAS1800_QRAM_ADDRESS    0xa
141 #define DAS1800_COUNTER         0xc
142 
143 #define IOBASE2                   0x400
144 
145 static const struct comedi_lrange das1801_ai_range = {
146 	8, {
147 		BIP_RANGE(5),		/* bipolar gain = 1 */
148 		BIP_RANGE(1),		/* bipolar gain = 10 */
149 		BIP_RANGE(0.1),		/* bipolar gain = 50 */
150 		BIP_RANGE(0.02),	/* bipolar gain = 250 */
151 		UNI_RANGE(5),		/* unipolar gain = 1 */
152 		UNI_RANGE(1),		/* unipolar gain = 10 */
153 		UNI_RANGE(0.1),		/* unipolar gain = 50 */
154 		UNI_RANGE(0.02)		/* unipolar gain = 250 */
155 	}
156 };
157 
158 static const struct comedi_lrange das1802_ai_range = {
159 	8, {
160 		BIP_RANGE(10),		/* bipolar gain = 1 */
161 		BIP_RANGE(5),		/* bipolar gain = 2 */
162 		BIP_RANGE(2.5),		/* bipolar gain = 4 */
163 		BIP_RANGE(1.25),	/* bipolar gain = 8 */
164 		UNI_RANGE(10),		/* unipolar gain = 1 */
165 		UNI_RANGE(5),		/* unipolar gain = 2 */
166 		UNI_RANGE(2.5),		/* unipolar gain = 4 */
167 		UNI_RANGE(1.25)		/* unipolar gain = 8 */
168 	}
169 };
170 
171 /*
172  * The waveform analog outputs on the 'ao' boards are not currently
173  * supported. They have a comedi_lrange of:
174  * { 2, { BIP_RANGE(10), BIP_RANGE(5) } }
175  */
176 
177 enum das1800_boardid {
178 	BOARD_DAS1701ST,
179 	BOARD_DAS1701ST_DA,
180 	BOARD_DAS1702ST,
181 	BOARD_DAS1702ST_DA,
182 	BOARD_DAS1702HR,
183 	BOARD_DAS1702HR_DA,
184 	BOARD_DAS1701AO,
185 	BOARD_DAS1702AO,
186 	BOARD_DAS1801ST,
187 	BOARD_DAS1801ST_DA,
188 	BOARD_DAS1802ST,
189 	BOARD_DAS1802ST_DA,
190 	BOARD_DAS1802HR,
191 	BOARD_DAS1802HR_DA,
192 	BOARD_DAS1801HC,
193 	BOARD_DAS1802HC,
194 	BOARD_DAS1801AO,
195 	BOARD_DAS1802AO
196 };
197 
198 /* board probe id values (hi byte of the digital input register) */
199 #define DAS1800_ID_ST_DA		0x3
200 #define DAS1800_ID_HR_DA		0x4
201 #define DAS1800_ID_AO			0x5
202 #define DAS1800_ID_HR			0x6
203 #define DAS1800_ID_ST			0x7
204 #define DAS1800_ID_HC			0x8
205 
206 struct das1800_board {
207 	const char *name;
208 	unsigned char id;
209 	unsigned int ai_speed;
210 	unsigned int is_01_series:1;
211 };
212 
213 static const struct das1800_board das1800_boards[] = {
214 	[BOARD_DAS1701ST] = {
215 		.name		= "das-1701st",
216 		.id		= DAS1800_ID_ST,
217 		.ai_speed	= 6250,
218 		.is_01_series	= 1,
219 	},
220 	[BOARD_DAS1701ST_DA] = {
221 		.name		= "das-1701st-da",
222 		.id		= DAS1800_ID_ST_DA,
223 		.ai_speed	= 6250,
224 		.is_01_series	= 1,
225 	},
226 	[BOARD_DAS1702ST] = {
227 		.name		= "das-1702st",
228 		.id		= DAS1800_ID_ST,
229 		.ai_speed	= 6250,
230 	},
231 	[BOARD_DAS1702ST_DA] = {
232 		.name		= "das-1702st-da",
233 		.id		= DAS1800_ID_ST_DA,
234 		.ai_speed	= 6250,
235 	},
236 	[BOARD_DAS1702HR] = {
237 		.name		= "das-1702hr",
238 		.id		= DAS1800_ID_HR,
239 		.ai_speed	= 20000,
240 	},
241 	[BOARD_DAS1702HR_DA] = {
242 		.name		= "das-1702hr-da",
243 		.id		= DAS1800_ID_HR_DA,
244 		.ai_speed	= 20000,
245 	},
246 	[BOARD_DAS1701AO] = {
247 		.name		= "das-1701ao",
248 		.id		= DAS1800_ID_AO,
249 		.ai_speed	= 6250,
250 		.is_01_series	= 1,
251 	},
252 	[BOARD_DAS1702AO] = {
253 		.name		= "das-1702ao",
254 		.id		= DAS1800_ID_AO,
255 		.ai_speed	= 6250,
256 	},
257 	[BOARD_DAS1801ST] = {
258 		.name		= "das-1801st",
259 		.id		= DAS1800_ID_ST,
260 		.ai_speed	= 3000,
261 		.is_01_series	= 1,
262 	},
263 	[BOARD_DAS1801ST_DA] = {
264 		.name		= "das-1801st-da",
265 		.id		= DAS1800_ID_ST_DA,
266 		.ai_speed	= 3000,
267 		.is_01_series	= 1,
268 	},
269 	[BOARD_DAS1802ST] = {
270 		.name		= "das-1802st",
271 		.id		= DAS1800_ID_ST,
272 		.ai_speed	= 3000,
273 	},
274 	[BOARD_DAS1802ST_DA] = {
275 		.name		= "das-1802st-da",
276 		.id		= DAS1800_ID_ST_DA,
277 		.ai_speed	= 3000,
278 	},
279 	[BOARD_DAS1802HR] = {
280 		.name		= "das-1802hr",
281 		.id		= DAS1800_ID_HR,
282 		.ai_speed	= 10000,
283 	},
284 	[BOARD_DAS1802HR_DA] = {
285 		.name		= "das-1802hr-da",
286 		.id		= DAS1800_ID_HR_DA,
287 		.ai_speed	= 10000,
288 	},
289 	[BOARD_DAS1801HC] = {
290 		.name		= "das-1801hc",
291 		.id		= DAS1800_ID_HC,
292 		.ai_speed	= 3000,
293 		.is_01_series	= 1,
294 	},
295 	[BOARD_DAS1802HC] = {
296 		.name		= "das-1802hc",
297 		.id		= DAS1800_ID_HC,
298 		.ai_speed	= 3000,
299 	},
300 	[BOARD_DAS1801AO] = {
301 		.name		= "das-1801ao",
302 		.id		= DAS1800_ID_AO,
303 		.ai_speed	= 3000,
304 		.is_01_series	= 1,
305 	},
306 	[BOARD_DAS1802AO] = {
307 		.name		= "das-1802ao",
308 		.id		= DAS1800_ID_AO,
309 		.ai_speed	= 3000,
310 	},
311 };
312 
313 struct das1800_private {
314 	struct comedi_isadma *dma;
315 	int irq_dma_bits;
316 	int dma_bits;
317 	unsigned short *fifo_buf;
318 	unsigned long iobase2;
319 	bool ai_is_unipolar;
320 };
321 
das1800_ai_munge(struct comedi_device * dev,struct comedi_subdevice * s,void * data,unsigned int num_bytes,unsigned int start_chan_index)322 static void das1800_ai_munge(struct comedi_device *dev,
323 			     struct comedi_subdevice *s,
324 			     void *data, unsigned int num_bytes,
325 			     unsigned int start_chan_index)
326 {
327 	struct das1800_private *devpriv = dev->private;
328 	unsigned short *array = data;
329 	unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
330 	unsigned int i;
331 
332 	if (devpriv->ai_is_unipolar)
333 		return;
334 
335 	for (i = 0; i < num_samples; i++)
336 		array[i] = comedi_offset_munge(s, array[i]);
337 }
338 
das1800_handle_fifo_half_full(struct comedi_device * dev,struct comedi_subdevice * s)339 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
340 					  struct comedi_subdevice *s)
341 {
342 	struct das1800_private *devpriv = dev->private;
343 	unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
344 
345 	insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
346 	comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
347 }
348 
das1800_handle_fifo_not_empty(struct comedi_device * dev,struct comedi_subdevice * s)349 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
350 					  struct comedi_subdevice *s)
351 {
352 	struct comedi_cmd *cmd = &s->async->cmd;
353 	unsigned short dpnt;
354 
355 	while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
356 		dpnt = inw(dev->iobase + DAS1800_FIFO);
357 		comedi_buf_write_samples(s, &dpnt, 1);
358 
359 		if (cmd->stop_src == TRIG_COUNT &&
360 		    s->async->scans_done >= cmd->stop_arg)
361 			break;
362 	}
363 }
364 
das1800_flush_dma_channel(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_isadma_desc * desc)365 static void das1800_flush_dma_channel(struct comedi_device *dev,
366 				      struct comedi_subdevice *s,
367 				      struct comedi_isadma_desc *desc)
368 {
369 	unsigned int residue = comedi_isadma_disable(desc->chan);
370 	unsigned int nbytes = desc->size - residue;
371 	unsigned int nsamples;
372 
373 	/*  figure out how many points to read */
374 	nsamples = comedi_bytes_to_samples(s, nbytes);
375 	nsamples = comedi_nsamples_left(s, nsamples);
376 
377 	comedi_buf_write_samples(s, desc->virt_addr, nsamples);
378 }
379 
das1800_flush_dma(struct comedi_device * dev,struct comedi_subdevice * s)380 static void das1800_flush_dma(struct comedi_device *dev,
381 			      struct comedi_subdevice *s)
382 {
383 	struct das1800_private *devpriv = dev->private;
384 	struct comedi_isadma *dma = devpriv->dma;
385 	struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
386 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
387 
388 	das1800_flush_dma_channel(dev, s, desc);
389 
390 	if (dual_dma) {
391 		/*  switch to other channel and flush it */
392 		dma->cur_dma = 1 - dma->cur_dma;
393 		desc = &dma->desc[dma->cur_dma];
394 		das1800_flush_dma_channel(dev, s, desc);
395 	}
396 
397 	/*  get any remaining samples in fifo */
398 	das1800_handle_fifo_not_empty(dev, s);
399 }
400 
das1800_handle_dma(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int status)401 static void das1800_handle_dma(struct comedi_device *dev,
402 			       struct comedi_subdevice *s, unsigned int status)
403 {
404 	struct das1800_private *devpriv = dev->private;
405 	struct comedi_isadma *dma = devpriv->dma;
406 	struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
407 	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
408 
409 	das1800_flush_dma_channel(dev, s, desc);
410 
411 	/* re-enable dma channel */
412 	comedi_isadma_program(desc);
413 
414 	if (status & DMATC) {
415 		/*  clear DMATC interrupt bit */
416 		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
417 		/*  switch dma channels for next time, if appropriate */
418 		if (dual_dma)
419 			dma->cur_dma = 1 - dma->cur_dma;
420 	}
421 }
422 
das1800_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)423 static int das1800_ai_cancel(struct comedi_device *dev,
424 			     struct comedi_subdevice *s)
425 {
426 	struct das1800_private *devpriv = dev->private;
427 	struct comedi_isadma *dma = devpriv->dma;
428 	struct comedi_isadma_desc *desc;
429 	int i;
430 
431 	/* disable and stop conversions */
432 	outb(0x0, dev->iobase + DAS1800_STATUS);
433 	outb(0x0, dev->iobase + DAS1800_CONTROL_B);
434 	outb(0x0, dev->iobase + DAS1800_CONTROL_A);
435 
436 	if (dma) {
437 		for (i = 0; i < 2; i++) {
438 			desc = &dma->desc[i];
439 			if (desc->chan)
440 				comedi_isadma_disable(desc->chan);
441 		}
442 	}
443 
444 	return 0;
445 }
446 
das1800_ai_handler(struct comedi_device * dev)447 static void das1800_ai_handler(struct comedi_device *dev)
448 {
449 	struct das1800_private *devpriv = dev->private;
450 	struct comedi_subdevice *s = dev->read_subdev;
451 	struct comedi_async *async = s->async;
452 	struct comedi_cmd *cmd = &async->cmd;
453 	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
454 
455 	/* select adc register (spinlock is already held) */
456 	outb(ADC, dev->iobase + DAS1800_SELECT);
457 
458 	/* get samples with dma, fifo, or polled as necessary */
459 	if (devpriv->irq_dma_bits & DMA_ENABLED)
460 		das1800_handle_dma(dev, s, status);
461 	else if (status & FHF)
462 		das1800_handle_fifo_half_full(dev, s);
463 	else if (status & FNE)
464 		das1800_handle_fifo_not_empty(dev, s);
465 
466 	/* if the card's fifo has overflowed */
467 	if (status & OVF) {
468 		/*  clear OVF interrupt bit */
469 		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
470 		dev_err(dev->class_dev, "FIFO overflow\n");
471 		async->events |= COMEDI_CB_ERROR;
472 		comedi_handle_events(dev, s);
473 		return;
474 	}
475 	/*  stop taking data if appropriate */
476 	/* stop_src TRIG_EXT */
477 	if (status & CT0TC) {
478 		/*  clear CT0TC interrupt bit */
479 		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
480 		/* get all remaining samples before quitting */
481 		if (devpriv->irq_dma_bits & DMA_ENABLED)
482 			das1800_flush_dma(dev, s);
483 		else
484 			das1800_handle_fifo_not_empty(dev, s);
485 		async->events |= COMEDI_CB_EOA;
486 	} else if (cmd->stop_src == TRIG_COUNT &&
487 		   async->scans_done >= cmd->stop_arg) {
488 		async->events |= COMEDI_CB_EOA;
489 	}
490 
491 	comedi_handle_events(dev, s);
492 }
493 
das1800_ai_poll(struct comedi_device * dev,struct comedi_subdevice * s)494 static int das1800_ai_poll(struct comedi_device *dev,
495 			   struct comedi_subdevice *s)
496 {
497 	unsigned long flags;
498 
499 	/*
500 	 * Protects the indirect addressing selected by DAS1800_SELECT
501 	 * in das1800_ai_handler() also prevents race with das1800_interrupt().
502 	 */
503 	spin_lock_irqsave(&dev->spinlock, flags);
504 
505 	das1800_ai_handler(dev);
506 
507 	spin_unlock_irqrestore(&dev->spinlock, flags);
508 
509 	return comedi_buf_n_bytes_ready(s);
510 }
511 
das1800_interrupt(int irq,void * d)512 static irqreturn_t das1800_interrupt(int irq, void *d)
513 {
514 	struct comedi_device *dev = d;
515 	unsigned int status;
516 
517 	if (!dev->attached) {
518 		dev_err(dev->class_dev, "premature interrupt\n");
519 		return IRQ_HANDLED;
520 	}
521 
522 	/*
523 	 * Protects the indirect addressing selected by DAS1800_SELECT
524 	 * in das1800_ai_handler() also prevents race with das1800_ai_poll().
525 	 */
526 	spin_lock(&dev->spinlock);
527 
528 	status = inb(dev->iobase + DAS1800_STATUS);
529 
530 	/* if interrupt was not caused by das-1800 */
531 	if (!(status & INT)) {
532 		spin_unlock(&dev->spinlock);
533 		return IRQ_NONE;
534 	}
535 	/* clear the interrupt status bit INT */
536 	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
537 	/*  handle interrupt */
538 	das1800_ai_handler(dev);
539 
540 	spin_unlock(&dev->spinlock);
541 	return IRQ_HANDLED;
542 }
543 
das1800_ai_fixup_paced_timing(struct comedi_device * dev,struct comedi_cmd * cmd)544 static int das1800_ai_fixup_paced_timing(struct comedi_device *dev,
545 					 struct comedi_cmd *cmd)
546 {
547 	unsigned int arg = cmd->convert_arg;
548 
549 	/*
550 	 * Paced mode:
551 	 *	scan_begin_src is TRIG_FOLLOW
552 	 *	convert_src is TRIG_TIMER
553 	 *
554 	 * The convert_arg sets the pacer sample acquisition time.
555 	 * The max acquisition speed is limited to the boards
556 	 * 'ai_speed' (this was already verified). The min speed is
557 	 * limited by the cascaded 8254 timer.
558 	 */
559 	comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
560 	return comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
561 }
562 
das1800_ai_fixup_burst_timing(struct comedi_device * dev,struct comedi_cmd * cmd)563 static int das1800_ai_fixup_burst_timing(struct comedi_device *dev,
564 					 struct comedi_cmd *cmd)
565 {
566 	unsigned int arg = cmd->convert_arg;
567 	int err = 0;
568 
569 	/*
570 	 * Burst mode:
571 	 *	scan_begin_src is TRIG_TIMER or TRIG_EXT
572 	 *	convert_src is TRIG_TIMER
573 	 *
574 	 * The convert_arg sets burst sample acquisition time.
575 	 * The max acquisition speed is limited to the boards
576 	 * 'ai_speed' (this was already verified). The min speed is
577 	 * limiited to 64 microseconds,
578 	 */
579 	err |= comedi_check_trigger_arg_max(&arg, 64000);
580 
581 	/* round to microseconds then verify */
582 	switch (cmd->flags & CMDF_ROUND_MASK) {
583 	case CMDF_ROUND_NEAREST:
584 	default:
585 		arg = DIV_ROUND_CLOSEST(arg, 1000);
586 		break;
587 	case CMDF_ROUND_DOWN:
588 		arg = arg / 1000;
589 		break;
590 	case CMDF_ROUND_UP:
591 		arg = DIV_ROUND_UP(arg, 1000);
592 		break;
593 	}
594 	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg * 1000);
595 
596 	/*
597 	 * The pacer can be used to set the scan sample rate. The max scan
598 	 * speed is limited by the conversion speed and the number of channels
599 	 * to convert. The min speed is limited by the cascaded 8254 timer.
600 	 */
601 	if (cmd->scan_begin_src == TRIG_TIMER) {
602 		arg = cmd->convert_arg * cmd->chanlist_len;
603 		err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
604 
605 		arg = cmd->scan_begin_arg;
606 		comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
607 		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
608 	}
609 
610 	return err;
611 }
612 
das1800_ai_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)613 static int das1800_ai_check_chanlist(struct comedi_device *dev,
614 				     struct comedi_subdevice *s,
615 				     struct comedi_cmd *cmd)
616 {
617 	unsigned int range = CR_RANGE(cmd->chanlist[0]);
618 	bool unipolar0 = comedi_range_is_unipolar(s, range);
619 	int i;
620 
621 	for (i = 1; i < cmd->chanlist_len; i++) {
622 		range = CR_RANGE(cmd->chanlist[i]);
623 
624 		if (unipolar0 != comedi_range_is_unipolar(s, range)) {
625 			dev_dbg(dev->class_dev,
626 				"unipolar and bipolar ranges cannot be mixed in the chanlist\n");
627 			return -EINVAL;
628 		}
629 	}
630 
631 	return 0;
632 }
633 
das1800_ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)634 static int das1800_ai_cmdtest(struct comedi_device *dev,
635 			      struct comedi_subdevice *s,
636 			      struct comedi_cmd *cmd)
637 {
638 	const struct das1800_board *board = dev->board_ptr;
639 	int err = 0;
640 
641 	/* Step 1 : check if triggers are trivially valid */
642 
643 	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
644 	err |= comedi_check_trigger_src(&cmd->scan_begin_src,
645 					TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
646 	err |= comedi_check_trigger_src(&cmd->convert_src,
647 					TRIG_TIMER | TRIG_EXT);
648 	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
649 	err |= comedi_check_trigger_src(&cmd->stop_src,
650 					TRIG_COUNT | TRIG_EXT | TRIG_NONE);
651 
652 	if (err)
653 		return 1;
654 
655 	/* Step 2a : make sure trigger sources are unique */
656 
657 	err |= comedi_check_trigger_is_unique(cmd->start_src);
658 	err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
659 	err |= comedi_check_trigger_is_unique(cmd->convert_src);
660 	err |= comedi_check_trigger_is_unique(cmd->stop_src);
661 
662 	/* Step 2b : and mutually compatible */
663 
664 	/* burst scans must use timed conversions */
665 	if (cmd->scan_begin_src != TRIG_FOLLOW &&
666 	    cmd->convert_src != TRIG_TIMER)
667 		err |= -EINVAL;
668 
669 	/* the external pin TGIN must use the same polarity */
670 	if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
671 		err |= comedi_check_trigger_arg_is(&cmd->start_arg,
672 						   cmd->stop_arg);
673 
674 	if (err)
675 		return 2;
676 
677 	/* Step 3: check if arguments are trivially valid */
678 
679 	if (cmd->start_arg == TRIG_NOW)
680 		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
681 
682 	if (cmd->convert_src == TRIG_TIMER) {
683 		err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
684 						    board->ai_speed);
685 	}
686 
687 	err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
688 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
689 					   cmd->chanlist_len);
690 
691 	switch (cmd->stop_src) {
692 	case TRIG_COUNT:
693 		err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
694 		break;
695 	case TRIG_NONE:
696 		err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
697 		break;
698 	default:
699 		break;
700 	}
701 
702 	if (err)
703 		return 3;
704 
705 	/* Step 4: fix up any arguments */
706 
707 	if (cmd->convert_src == TRIG_TIMER) {
708 		if (cmd->scan_begin_src == TRIG_FOLLOW)
709 			err |= das1800_ai_fixup_paced_timing(dev, cmd);
710 		else /* TRIG_TIMER or TRIG_EXT */
711 			err |= das1800_ai_fixup_burst_timing(dev, cmd);
712 	}
713 
714 	if (err)
715 		return 4;
716 
717 	/* Step 5: check channel list if it exists */
718 	if (cmd->chanlist && cmd->chanlist_len > 0)
719 		err |= das1800_ai_check_chanlist(dev, s, cmd);
720 
721 	if (err)
722 		return 5;
723 
724 	return 0;
725 }
726 
das1800_ai_chanspec_bits(struct comedi_subdevice * s,unsigned int chanspec)727 static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s,
728 					      unsigned int chanspec)
729 {
730 	unsigned int range = CR_RANGE(chanspec);
731 	unsigned int aref = CR_AREF(chanspec);
732 	unsigned char bits;
733 
734 	bits = UQEN;
735 	if (aref != AREF_DIFF)
736 		bits |= SD;
737 	if (aref == AREF_COMMON)
738 		bits |= CMEN;
739 	if (comedi_range_is_unipolar(s, range))
740 		bits |= UB;
741 
742 	return bits;
743 }
744 
das1800_ai_transfer_size(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int maxbytes,unsigned int ns)745 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
746 					     struct comedi_subdevice *s,
747 					     unsigned int maxbytes,
748 					     unsigned int ns)
749 {
750 	struct comedi_cmd *cmd = &s->async->cmd;
751 	unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
752 	unsigned int samples;
753 
754 	samples = max_samples;
755 
756 	/* for timed modes, make dma buffer fill in 'ns' time */
757 	switch (cmd->scan_begin_src) {
758 	case TRIG_FOLLOW:	/* not in burst mode */
759 		if (cmd->convert_src == TRIG_TIMER)
760 			samples = ns / cmd->convert_arg;
761 		break;
762 	case TRIG_TIMER:
763 		samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
764 		break;
765 	}
766 
767 	/* limit samples to what is remaining in the command */
768 	samples = comedi_nsamples_left(s, samples);
769 
770 	if (samples > max_samples)
771 		samples = max_samples;
772 	if (samples < 1)
773 		samples = 1;
774 
775 	return comedi_samples_to_bytes(s, samples);
776 }
777 
das1800_ai_setup_dma(struct comedi_device * dev,struct comedi_subdevice * s)778 static void das1800_ai_setup_dma(struct comedi_device *dev,
779 				 struct comedi_subdevice *s)
780 {
781 	struct das1800_private *devpriv = dev->private;
782 	struct comedi_isadma *dma = devpriv->dma;
783 	struct comedi_isadma_desc *desc;
784 	unsigned int bytes;
785 
786 	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
787 		return;
788 
789 	dma->cur_dma = 0;
790 	desc = &dma->desc[0];
791 
792 	/* determine a dma transfer size to fill buffer in 0.3 sec */
793 	bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
794 
795 	desc->size = bytes;
796 	comedi_isadma_program(desc);
797 
798 	/* set up dual dma if appropriate */
799 	if (devpriv->irq_dma_bits & DMA_DUAL) {
800 		desc = &dma->desc[1];
801 		desc->size = bytes;
802 		comedi_isadma_program(desc);
803 	}
804 }
805 
das1800_ai_set_chanlist(struct comedi_device * dev,unsigned int * chanlist,unsigned int len)806 static void das1800_ai_set_chanlist(struct comedi_device *dev,
807 				    unsigned int *chanlist, unsigned int len)
808 {
809 	unsigned long flags;
810 	unsigned int i;
811 
812 	/* protects the indirect addressing selected by DAS1800_SELECT */
813 	spin_lock_irqsave(&dev->spinlock, flags);
814 
815 	/* select QRAM register and set start address */
816 	outb(QRAM, dev->iobase + DAS1800_SELECT);
817 	outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
818 
819 	/* make channel / gain list */
820 	for (i = 0; i < len; i++) {
821 		unsigned int chan = CR_CHAN(chanlist[i]);
822 		unsigned int range = CR_RANGE(chanlist[i]);
823 		unsigned short val;
824 
825 		val = chan | ((range & 0x3) << 8);
826 		outw(val, dev->iobase + DAS1800_QRAM);
827 	}
828 
829 	/* finish write to QRAM */
830 	outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
831 
832 	spin_unlock_irqrestore(&dev->spinlock, flags);
833 }
834 
das1800_ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)835 static int das1800_ai_cmd(struct comedi_device *dev,
836 			  struct comedi_subdevice *s)
837 {
838 	struct das1800_private *devpriv = dev->private;
839 	int control_a, control_c;
840 	struct comedi_async *async = s->async;
841 	const struct comedi_cmd *cmd = &async->cmd;
842 	unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
843 
844 	/*
845 	 * Disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY (because dma in
846 	 * handler is unsafe at hard real-time priority).
847 	 */
848 	if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
849 		devpriv->irq_dma_bits &= ~DMA_ENABLED;
850 	else
851 		devpriv->irq_dma_bits |= devpriv->dma_bits;
852 	/*  interrupt on end of conversion for CMDF_WAKE_EOS */
853 	if (cmd->flags & CMDF_WAKE_EOS) {
854 		/*  interrupt fifo not empty */
855 		devpriv->irq_dma_bits &= ~FIMD;
856 	} else {
857 		/*  interrupt fifo half full */
858 		devpriv->irq_dma_bits |= FIMD;
859 	}
860 
861 	das1800_ai_cancel(dev, s);
862 
863 	devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0);
864 
865 	control_a = FFEN;
866 	if (cmd->stop_src == TRIG_EXT)
867 		control_a |= ATEN;
868 	if (cmd->start_src == TRIG_EXT)
869 		control_a |= TGEN | CGSL;
870 	else /* TRIG_NOW */
871 		control_a |= CGEN;
872 	if (control_a & (ATEN | TGEN)) {
873 		if ((cmd->start_arg & CR_INVERT) || (cmd->stop_arg & CR_INVERT))
874 			control_a |= TGPL;
875 	}
876 
877 	control_c = das1800_ai_chanspec_bits(s, cmd->chanlist[0]);
878 	/* set clock source to internal or external */
879 	if (cmd->scan_begin_src == TRIG_FOLLOW) {
880 		/* not in burst mode */
881 		if (cmd->convert_src == TRIG_TIMER) {
882 			/* trig on cascaded counters */
883 			control_c |= IPCLK;
884 		} else { /* TRIG_EXT */
885 			/* trig on falling edge of external trigger */
886 			control_c |= XPCLK;
887 		}
888 	} else if (cmd->scan_begin_src == TRIG_TIMER) {
889 		/* burst mode with internal pacer clock */
890 		control_c |= BMDE | IPCLK;
891 	} else { /* TRIG_EXT */
892 		/* burst mode with external trigger */
893 		control_c |= BMDE | XPCLK;
894 	}
895 
896 	das1800_ai_set_chanlist(dev, cmd->chanlist, cmd->chanlist_len);
897 
898 	/* setup cascaded counters for conversion/scan frequency */
899 	if ((cmd->scan_begin_src == TRIG_FOLLOW ||
900 	     cmd->scan_begin_src == TRIG_TIMER) &&
901 	    cmd->convert_src == TRIG_TIMER) {
902 		comedi_8254_update_divisors(dev->pacer);
903 		comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
904 	}
905 
906 	/* setup counter 0 for 'about triggering' */
907 	if (cmd->stop_src == TRIG_EXT)
908 		comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
909 
910 	das1800_ai_setup_dma(dev, s);
911 	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
912 	/*  set conversion rate and length for burst mode */
913 	if (control_c & BMDE) {
914 		outb(cmd->convert_arg / 1000 - 1,	/* microseconds - 1 */
915 		     dev->iobase + DAS1800_BURST_RATE);
916 		outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
917 	}
918 
919 	/* enable and start conversions */
920 	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);
921 	outb(control_a, dev->iobase + DAS1800_CONTROL_A);
922 	outb(CVEN, dev->iobase + DAS1800_STATUS);
923 
924 	return 0;
925 }
926 
das1800_ai_eoc(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned long context)927 static int das1800_ai_eoc(struct comedi_device *dev,
928 			  struct comedi_subdevice *s,
929 			  struct comedi_insn *insn,
930 			  unsigned long context)
931 {
932 	unsigned char status;
933 
934 	status = inb(dev->iobase + DAS1800_STATUS);
935 	if (status & FNE)
936 		return 0;
937 	return -EBUSY;
938 }
939 
das1800_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)940 static int das1800_ai_insn_read(struct comedi_device *dev,
941 				struct comedi_subdevice *s,
942 				struct comedi_insn *insn,
943 				unsigned int *data)
944 {
945 	unsigned int range = CR_RANGE(insn->chanspec);
946 	bool is_unipolar = comedi_range_is_unipolar(s, range);
947 	int ret = 0;
948 	int n;
949 	unsigned short dpnt;
950 	unsigned long flags;
951 
952 	outb(das1800_ai_chanspec_bits(s, insn->chanspec),
953 	     dev->iobase + DAS1800_CONTROL_C);		/* software pacer */
954 	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
955 	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* reset fifo */
956 	outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
957 
958 	das1800_ai_set_chanlist(dev, &insn->chanspec, 1);
959 
960 	/* protects the indirect addressing selected by DAS1800_SELECT */
961 	spin_lock_irqsave(&dev->spinlock, flags);
962 
963 	/* select ai fifo register */
964 	outb(ADC, dev->iobase + DAS1800_SELECT);
965 
966 	for (n = 0; n < insn->n; n++) {
967 		/* trigger conversion */
968 		outb(0, dev->iobase + DAS1800_FIFO);
969 
970 		ret = comedi_timeout(dev, s, insn, das1800_ai_eoc, 0);
971 		if (ret)
972 			break;
973 
974 		dpnt = inw(dev->iobase + DAS1800_FIFO);
975 		if (!is_unipolar)
976 			dpnt = comedi_offset_munge(s, dpnt);
977 		data[n] = dpnt;
978 	}
979 	spin_unlock_irqrestore(&dev->spinlock, flags);
980 
981 	return ret ? ret : insn->n;
982 }
983 
das1800_ao_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)984 static int das1800_ao_insn_write(struct comedi_device *dev,
985 				 struct comedi_subdevice *s,
986 				 struct comedi_insn *insn,
987 				 unsigned int *data)
988 {
989 	unsigned int chan = CR_CHAN(insn->chanspec);
990 	unsigned int update_chan = s->n_chan - 1;
991 	unsigned long flags;
992 	int i;
993 
994 	/* protects the indirect addressing selected by DAS1800_SELECT */
995 	spin_lock_irqsave(&dev->spinlock, flags);
996 
997 	for (i = 0; i < insn->n; i++) {
998 		unsigned int val = data[i];
999 
1000 		s->readback[chan] = val;
1001 
1002 		val = comedi_offset_munge(s, val);
1003 
1004 		/* load this channel (and update if it's the last channel) */
1005 		outb(DAC(chan), dev->iobase + DAS1800_SELECT);
1006 		outw(val, dev->iobase + DAS1800_DAC);
1007 
1008 		/* update all channels */
1009 		if (chan != update_chan) {
1010 			val = comedi_offset_munge(s, s->readback[update_chan]);
1011 
1012 			outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);
1013 			outw(val, dev->iobase + DAS1800_DAC);
1014 		}
1015 	}
1016 	spin_unlock_irqrestore(&dev->spinlock, flags);
1017 
1018 	return insn->n;
1019 }
1020 
das1800_di_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1021 static int das1800_di_insn_bits(struct comedi_device *dev,
1022 				struct comedi_subdevice *s,
1023 				struct comedi_insn *insn,
1024 				unsigned int *data)
1025 {
1026 	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1027 	data[0] = 0;
1028 
1029 	return insn->n;
1030 }
1031 
das1800_do_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)1032 static int das1800_do_insn_bits(struct comedi_device *dev,
1033 				struct comedi_subdevice *s,
1034 				struct comedi_insn *insn,
1035 				unsigned int *data)
1036 {
1037 	if (comedi_dio_update_state(s, data))
1038 		outb(s->state, dev->iobase + DAS1800_DIGITAL);
1039 
1040 	data[1] = s->state;
1041 
1042 	return insn->n;
1043 }
1044 
das1800_init_dma(struct comedi_device * dev,struct comedi_devconfig * it)1045 static void das1800_init_dma(struct comedi_device *dev,
1046 			     struct comedi_devconfig *it)
1047 {
1048 	struct das1800_private *devpriv = dev->private;
1049 	unsigned int *dma_chan;
1050 
1051 	/*
1052 	 * it->options[2] is DMA channel 0
1053 	 * it->options[3] is DMA channel 1
1054 	 *
1055 	 * Encode the DMA channels into 2 digit hexadecimal for switch.
1056 	 */
1057 	dma_chan = &it->options[2];
1058 
1059 	switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1060 	case 0x5:	/*  dma0 == 5 */
1061 		devpriv->dma_bits = DMA_CH5;
1062 		break;
1063 	case 0x6:	/*  dma0 == 6 */
1064 		devpriv->dma_bits = DMA_CH6;
1065 		break;
1066 	case 0x7:	/*  dma0 == 7 */
1067 		devpriv->dma_bits = DMA_CH7;
1068 		break;
1069 	case 0x65:	/*  dma0 == 5, dma1 == 6 */
1070 		devpriv->dma_bits = DMA_CH5_CH6;
1071 		break;
1072 	case 0x76:	/*  dma0 == 6, dma1 == 7 */
1073 		devpriv->dma_bits = DMA_CH6_CH7;
1074 		break;
1075 	case 0x57:	/*  dma0 == 7, dma1 == 5 */
1076 		devpriv->dma_bits = DMA_CH7_CH5;
1077 		break;
1078 	default:
1079 		return;
1080 	}
1081 
1082 	/* DMA can use 1 or 2 buffers, each with a separate channel */
1083 	devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1084 					   dma_chan[0], dma_chan[1],
1085 					   DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1086 	if (!devpriv->dma)
1087 		devpriv->dma_bits = 0;
1088 }
1089 
das1800_free_dma(struct comedi_device * dev)1090 static void das1800_free_dma(struct comedi_device *dev)
1091 {
1092 	struct das1800_private *devpriv = dev->private;
1093 
1094 	if (devpriv)
1095 		comedi_isadma_free(devpriv->dma);
1096 }
1097 
das1800_probe(struct comedi_device * dev)1098 static int das1800_probe(struct comedi_device *dev)
1099 {
1100 	const struct das1800_board *board = dev->board_ptr;
1101 	unsigned char id;
1102 
1103 	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1104 
1105 	/*
1106 	 * The dev->board_ptr will be set by comedi_device_attach() if the
1107 	 * board name provided by the user matches a board->name in this
1108 	 * driver. If so, this function sanity checks the id to verify that
1109 	 * the board is correct.
1110 	 */
1111 	if (board) {
1112 		if (board->id == id)
1113 			return 0;
1114 		dev_err(dev->class_dev,
1115 			"probed id does not match board id (0x%x != 0x%x)\n",
1116 			id, board->id);
1117 		return -ENODEV;
1118 	}
1119 
1120 	 /*
1121 	  * If the dev->board_ptr is not set, the user is trying to attach
1122 	  * an unspecified board to this driver. In this case the id is used
1123 	  * to 'probe' for the dev->board_ptr.
1124 	  */
1125 	switch (id) {
1126 	case DAS1800_ID_ST_DA:
1127 		/* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */
1128 		board = &das1800_boards[BOARD_DAS1801ST_DA];
1129 		break;
1130 	case DAS1800_ID_HR_DA:
1131 		/* das-1702hr-da, das-1802hr-da */
1132 		board = &das1800_boards[BOARD_DAS1802HR_DA];
1133 		break;
1134 	case DAS1800_ID_AO:
1135 		/* das-1701ao, das-1702ao, das-1801ao, das-1802ao */
1136 		board = &das1800_boards[BOARD_DAS1801AO];
1137 		break;
1138 	case DAS1800_ID_HR:
1139 		/*  das-1702hr, das-1802hr */
1140 		board = &das1800_boards[BOARD_DAS1802HR];
1141 		break;
1142 	case DAS1800_ID_ST:
1143 		/* das-1701st, das-1702st, das-1801st, das-1802st */
1144 		board = &das1800_boards[BOARD_DAS1801ST];
1145 		break;
1146 	case DAS1800_ID_HC:
1147 		/* das-1801hc, das-1802hc */
1148 		board = &das1800_boards[BOARD_DAS1801HC];
1149 		break;
1150 	default:
1151 		dev_err(dev->class_dev, "invalid probe id 0x%x\n", id);
1152 		return -ENODEV;
1153 	}
1154 	dev->board_ptr = board;
1155 	dev->board_name = board->name;
1156 	dev_warn(dev->class_dev,
1157 		 "probed id 0x%0x: %s series (not recommended)\n",
1158 		 id, board->name);
1159 	return 0;
1160 }
1161 
das1800_attach(struct comedi_device * dev,struct comedi_devconfig * it)1162 static int das1800_attach(struct comedi_device *dev,
1163 			  struct comedi_devconfig *it)
1164 {
1165 	const struct das1800_board *board;
1166 	struct das1800_private *devpriv;
1167 	struct comedi_subdevice *s;
1168 	unsigned int irq = it->options[1];
1169 	bool is_16bit;
1170 	int ret;
1171 	int i;
1172 
1173 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1174 	if (!devpriv)
1175 		return -ENOMEM;
1176 
1177 	ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1178 	if (ret)
1179 		return ret;
1180 
1181 	ret = das1800_probe(dev);
1182 	if (ret)
1183 		return ret;
1184 	board = dev->board_ptr;
1185 
1186 	is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;
1187 
1188 	/* waveform 'ao' boards have additional io ports */
1189 	if (board->id == DAS1800_ID_AO) {
1190 		unsigned long iobase2 = dev->iobase + IOBASE2;
1191 
1192 		ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1193 		if (ret)
1194 			return ret;
1195 		devpriv->iobase2 = iobase2;
1196 	}
1197 
1198 	if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1199 	    irq == 15) {
1200 		ret = request_irq(irq, das1800_interrupt, 0,
1201 				  dev->board_name, dev);
1202 		if (ret == 0) {
1203 			dev->irq = irq;
1204 
1205 			switch (irq) {
1206 			case 3:
1207 				devpriv->irq_dma_bits |= 0x8;
1208 				break;
1209 			case 5:
1210 				devpriv->irq_dma_bits |= 0x10;
1211 				break;
1212 			case 7:
1213 				devpriv->irq_dma_bits |= 0x18;
1214 				break;
1215 			case 10:
1216 				devpriv->irq_dma_bits |= 0x28;
1217 				break;
1218 			case 11:
1219 				devpriv->irq_dma_bits |= 0x30;
1220 				break;
1221 			case 15:
1222 				devpriv->irq_dma_bits |= 0x38;
1223 				break;
1224 			}
1225 		}
1226 	}
1227 
1228 	/* an irq and one dma channel is required to use dma */
1229 	if (dev->irq & it->options[2])
1230 		das1800_init_dma(dev, it);
1231 
1232 	devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
1233 					  sizeof(*devpriv->fifo_buf),
1234 					  GFP_KERNEL);
1235 	if (!devpriv->fifo_buf)
1236 		return -ENOMEM;
1237 
1238 	dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1239 				      I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1240 	if (!dev->pacer)
1241 		return -ENOMEM;
1242 
1243 	ret = comedi_alloc_subdevices(dev, 4);
1244 	if (ret)
1245 		return ret;
1246 
1247 	/*
1248 	 * Analog Input subdevice
1249 	 *
1250 	 * The "hc" type boards have 64 analog input channels and a 64
1251 	 * entry QRAM fifo.
1252 	 *
1253 	 * All the other board types have 16 on-board channels. Each channel
1254 	 * can be expanded to 16 channels with the addition of an EXP-1800
1255 	 * expansion board for a total of 256 channels. The QRAM fifo on
1256 	 * these boards has 256 entries.
1257 	 *
1258 	 * From the datasheets it's not clear what the comedi channel to
1259 	 * actual physical channel mapping is when EXP-1800 boards are used.
1260 	 */
1261 	s = &dev->subdevices[0];
1262 	s->type		= COMEDI_SUBD_AI;
1263 	s->subdev_flags	= SDF_READABLE | SDF_DIFF | SDF_GROUND;
1264 	if (board->id != DAS1800_ID_HC)
1265 		s->subdev_flags	|= SDF_COMMON;
1266 	s->n_chan	= (board->id == DAS1800_ID_HC) ? 64 : 256;
1267 	s->maxdata	= is_16bit ? 0xffff : 0x0fff;
1268 	s->range_table	= board->is_01_series ? &das1801_ai_range
1269 					      : &das1802_ai_range;
1270 	s->insn_read	= das1800_ai_insn_read;
1271 	if (dev->irq) {
1272 		dev->read_subdev = s;
1273 		s->subdev_flags	|= SDF_CMD_READ;
1274 		s->len_chanlist	= s->n_chan;
1275 		s->do_cmd	= das1800_ai_cmd;
1276 		s->do_cmdtest	= das1800_ai_cmdtest;
1277 		s->poll		= das1800_ai_poll;
1278 		s->cancel	= das1800_ai_cancel;
1279 		s->munge	= das1800_ai_munge;
1280 	}
1281 
1282 	/* Analog Output subdevice */
1283 	s = &dev->subdevices[1];
1284 	if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
1285 		s->type		= COMEDI_SUBD_AO;
1286 		s->subdev_flags	= SDF_WRITABLE;
1287 		s->n_chan	= (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
1288 		s->maxdata	= is_16bit ? 0xffff : 0x0fff;
1289 		s->range_table	= &range_bipolar10;
1290 		s->insn_write	= das1800_ao_insn_write;
1291 
1292 		ret = comedi_alloc_subdev_readback(s);
1293 		if (ret)
1294 			return ret;
1295 
1296 		/* initialize all channels to 0V */
1297 		for (i = 0; i < s->n_chan; i++) {
1298 			/* spinlock is not necessary during the attach */
1299 			outb(DAC(i), dev->iobase + DAS1800_SELECT);
1300 			outw(0, dev->iobase + DAS1800_DAC);
1301 		}
1302 	} else if (board->id == DAS1800_ID_AO) {
1303 		/*
1304 		 * 'ao' boards have waveform analog outputs that are not
1305 		 * currently supported.
1306 		 */
1307 		s->type		= COMEDI_SUBD_UNUSED;
1308 	} else {
1309 		s->type		= COMEDI_SUBD_UNUSED;
1310 	}
1311 
1312 	/* Digital Input subdevice */
1313 	s = &dev->subdevices[2];
1314 	s->type		= COMEDI_SUBD_DI;
1315 	s->subdev_flags	= SDF_READABLE;
1316 	s->n_chan	= 4;
1317 	s->maxdata	= 1;
1318 	s->range_table	= &range_digital;
1319 	s->insn_bits	= das1800_di_insn_bits;
1320 
1321 	/* Digital Output subdevice */
1322 	s = &dev->subdevices[3];
1323 	s->type		= COMEDI_SUBD_DO;
1324 	s->subdev_flags	= SDF_WRITABLE;
1325 	s->n_chan	= (board->id == DAS1800_ID_HC) ? 8 : 4;
1326 	s->maxdata	= 1;
1327 	s->range_table	= &range_digital;
1328 	s->insn_bits	= das1800_do_insn_bits;
1329 
1330 	das1800_ai_cancel(dev, dev->read_subdev);
1331 
1332 	/*  initialize digital out channels */
1333 	outb(0, dev->iobase + DAS1800_DIGITAL);
1334 
1335 	return 0;
1336 };
1337 
das1800_detach(struct comedi_device * dev)1338 static void das1800_detach(struct comedi_device *dev)
1339 {
1340 	struct das1800_private *devpriv = dev->private;
1341 
1342 	das1800_free_dma(dev);
1343 	if (devpriv) {
1344 		kfree(devpriv->fifo_buf);
1345 		if (devpriv->iobase2)
1346 			release_region(devpriv->iobase2, DAS1800_SIZE);
1347 	}
1348 	comedi_legacy_detach(dev);
1349 }
1350 
1351 static struct comedi_driver das1800_driver = {
1352 	.driver_name	= "das1800",
1353 	.module		= THIS_MODULE,
1354 	.attach		= das1800_attach,
1355 	.detach		= das1800_detach,
1356 	.num_names	= ARRAY_SIZE(das1800_boards),
1357 	.board_name	= &das1800_boards[0].name,
1358 	.offset		= sizeof(struct das1800_board),
1359 };
1360 module_comedi_driver(das1800_driver);
1361 
1362 MODULE_AUTHOR("Comedi https://www.comedi.org");
1363 MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards");
1364 MODULE_LICENSE("GPL");
1365