• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * das16.c
4  * DAS16 driver
5  *
6  * COMEDI - Linux Control and Measurement Device Interface
7  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8  * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
9  * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10  */
11 
12 /*
13  * Driver: das16
14  * Description: DAS16 compatible boards
15  * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
16  * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
17  *   DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
18  *   DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
19  *   DAS-1602 (das-1602),
20  *   [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
21  *   PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16),
22  *   CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr),
23  *   CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12),
24  *   CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
25  *   CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
26  *   CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
27  * Status: works
28  * Updated: 2003-10-12
29  *
30  * A rewrite of the das16 and das1600 drivers.
31  *
32  * Options:
33  *	[0] - base io address
34  *	[1] - irq (does nothing, irq is not used anymore)
35  *	[2] - dma channel (optional, required for comedi_command support)
36  *	[3] - master clock speed in MHz (optional, 1 or 10, ignored if
37  *		board can probe clock, defaults to 1)
38  *	[4] - analog input range lowest voltage in microvolts (optional,
39  *		only useful if your board does not have software
40  *		programmable gain)
41  *	[5] - analog input range highest voltage in microvolts (optional,
42  *		only useful if board does not have software programmable
43  *		gain)
44  *	[6] - analog output range lowest voltage in microvolts (optional)
45  *	[7] - analog output range highest voltage in microvolts (optional)
46  *
47  * Passing a zero for an option is the same as leaving it unspecified.
48  */
49 
50 /*
51  * Testing and debugging help provided by Daniel Koch.
52  *
53  * Keithley Manuals:
54  *	2309.PDF (das16)
55  *	4919.PDF (das1400, 1600)
56  *	4922.PDF (das-1400)
57  *	4923.PDF (das1200, 1400, 1600)
58  *
59  * Computer boards manuals also available from their website
60  * www.measurementcomputing.com
61  */
62 
63 #include <linux/module.h>
64 #include <linux/slab.h>
65 #include <linux/interrupt.h>
66 
67 #include "../comedidev.h"
68 
69 #include "comedi_isadma.h"
70 #include "comedi_8254.h"
71 #include "8255.h"
72 
73 #define DAS16_DMA_SIZE 0xff00	/*  size in bytes of allocated dma buffer */
74 
75 /*
76  * Register I/O map
77  */
78 #define DAS16_TRIG_REG			0x00
79 #define DAS16_AI_LSB_REG		0x00
80 #define DAS16_AI_MSB_REG		0x01
81 #define DAS16_MUX_REG			0x02
82 #define DAS16_DIO_REG			0x03
83 #define DAS16_AO_LSB_REG(x)		((x) ? 0x06 : 0x04)
84 #define DAS16_AO_MSB_REG(x)		((x) ? 0x07 : 0x05)
85 #define DAS16_STATUS_REG		0x08
86 #define DAS16_STATUS_BUSY		BIT(7)
87 #define DAS16_STATUS_UNIPOLAR		BIT(6)
88 #define DAS16_STATUS_MUXBIT		BIT(5)
89 #define DAS16_STATUS_INT		BIT(4)
90 #define DAS16_CTRL_REG			0x09
91 #define DAS16_CTRL_INTE			BIT(7)
92 #define DAS16_CTRL_IRQ(x)		(((x) & 0x7) << 4)
93 #define DAS16_CTRL_DMAE			BIT(2)
94 #define DAS16_CTRL_PACING_MASK		(3 << 0)
95 #define DAS16_CTRL_INT_PACER		(3 << 0)
96 #define DAS16_CTRL_EXT_PACER		(2 << 0)
97 #define DAS16_CTRL_SOFT_PACER		(0 << 0)
98 #define DAS16_PACER_REG			0x0a
99 #define DAS16_PACER_BURST_LEN(x)	(((x) & 0xf) << 4)
100 #define DAS16_PACER_CTR0		BIT(1)
101 #define DAS16_PACER_TRIG0		BIT(0)
102 #define DAS16_GAIN_REG			0x0b
103 #define DAS16_TIMER_BASE_REG		0x0c	/* to 0x0f */
104 
105 #define DAS1600_CONV_REG		0x404
106 #define DAS1600_CONV_DISABLE		BIT(6)
107 #define DAS1600_BURST_REG		0x405
108 #define DAS1600_BURST_VAL		BIT(6)
109 #define DAS1600_ENABLE_REG		0x406
110 #define DAS1600_ENABLE_VAL		BIT(6)
111 #define DAS1600_STATUS_REG		0x407
112 #define DAS1600_STATUS_BME		BIT(6)
113 #define DAS1600_STATUS_ME		BIT(5)
114 #define DAS1600_STATUS_CD		BIT(4)
115 #define DAS1600_STATUS_WS		BIT(1)
116 #define DAS1600_STATUS_CLK_10MHZ	BIT(0)
117 
118 static const struct comedi_lrange range_das1x01_bip = {
119 	4, {
120 		BIP_RANGE(10),
121 		BIP_RANGE(1),
122 		BIP_RANGE(0.1),
123 		BIP_RANGE(0.01)
124 	}
125 };
126 
127 static const struct comedi_lrange range_das1x01_unip = {
128 	4, {
129 		UNI_RANGE(10),
130 		UNI_RANGE(1),
131 		UNI_RANGE(0.1),
132 		UNI_RANGE(0.01)
133 	}
134 };
135 
136 static const struct comedi_lrange range_das1x02_bip = {
137 	4, {
138 		BIP_RANGE(10),
139 		BIP_RANGE(5),
140 		BIP_RANGE(2.5),
141 		BIP_RANGE(1.25)
142 	}
143 };
144 
145 static const struct comedi_lrange range_das1x02_unip = {
146 	4, {
147 		UNI_RANGE(10),
148 		UNI_RANGE(5),
149 		UNI_RANGE(2.5),
150 		UNI_RANGE(1.25)
151 	}
152 };
153 
154 static const struct comedi_lrange range_das16jr = {
155 	9, {
156 		BIP_RANGE(10),
157 		BIP_RANGE(5),
158 		BIP_RANGE(2.5),
159 		BIP_RANGE(1.25),
160 		BIP_RANGE(0.625),
161 		UNI_RANGE(10),
162 		UNI_RANGE(5),
163 		UNI_RANGE(2.5),
164 		UNI_RANGE(1.25)
165 	}
166 };
167 
168 static const struct comedi_lrange range_das16jr_16 = {
169 	8, {
170 		BIP_RANGE(10),
171 		BIP_RANGE(5),
172 		BIP_RANGE(2.5),
173 		BIP_RANGE(1.25),
174 		UNI_RANGE(10),
175 		UNI_RANGE(5),
176 		UNI_RANGE(2.5),
177 		UNI_RANGE(1.25)
178 	}
179 };
180 
181 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
182 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
183 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
184 
185 enum {
186 	das16_pg_none = 0,
187 	das16_pg_16jr,
188 	das16_pg_16jr_16,
189 	das16_pg_1601,
190 	das16_pg_1602,
191 };
192 
193 static const int *const das16_gainlists[] = {
194 	NULL,
195 	das16jr_gainlist,
196 	das16jr_16_gainlist,
197 	das1600_gainlist,
198 	das1600_gainlist,
199 };
200 
201 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
202 	&range_unknown,
203 	&range_das16jr,
204 	&range_das16jr_16,
205 	&range_das1x01_unip,
206 	&range_das1x02_unip,
207 };
208 
209 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
210 	&range_unknown,
211 	&range_das16jr,
212 	&range_das16jr_16,
213 	&range_das1x01_bip,
214 	&range_das1x02_bip,
215 };
216 
217 struct das16_board {
218 	const char *name;
219 	unsigned int ai_maxdata;
220 	unsigned int ai_speed;	/*  max conversion speed in nanosec */
221 	unsigned int ai_pg;
222 	unsigned int has_ao:1;
223 	unsigned int has_8255:1;
224 
225 	unsigned int i8255_offset;
226 
227 	unsigned int size;
228 	unsigned int id;
229 };
230 
231 static const struct das16_board das16_boards[] = {
232 	{
233 		.name		= "das-16",
234 		.ai_maxdata	= 0x0fff,
235 		.ai_speed	= 15000,
236 		.ai_pg		= das16_pg_none,
237 		.has_ao		= 1,
238 		.has_8255	= 1,
239 		.i8255_offset	= 0x10,
240 		.size		= 0x14,
241 		.id		= 0x00,
242 	}, {
243 		.name		= "das-16g",
244 		.ai_maxdata	= 0x0fff,
245 		.ai_speed	= 15000,
246 		.ai_pg		= das16_pg_none,
247 		.has_ao		= 1,
248 		.has_8255	= 1,
249 		.i8255_offset	= 0x10,
250 		.size		= 0x14,
251 		.id		= 0x00,
252 	}, {
253 		.name		= "das-16f",
254 		.ai_maxdata	= 0x0fff,
255 		.ai_speed	= 8500,
256 		.ai_pg		= das16_pg_none,
257 		.has_ao		= 1,
258 		.has_8255	= 1,
259 		.i8255_offset	= 0x10,
260 		.size		= 0x14,
261 		.id		= 0x00,
262 	}, {
263 		.name		= "cio-das16",
264 		.ai_maxdata	= 0x0fff,
265 		.ai_speed	= 20000,
266 		.ai_pg		= das16_pg_none,
267 		.has_ao		= 1,
268 		.has_8255	= 1,
269 		.i8255_offset	= 0x10,
270 		.size		= 0x14,
271 		.id		= 0x80,
272 	}, {
273 		.name		= "cio-das16/f",
274 		.ai_maxdata	= 0x0fff,
275 		.ai_speed	= 10000,
276 		.ai_pg		= das16_pg_none,
277 		.has_ao		= 1,
278 		.has_8255	= 1,
279 		.i8255_offset	= 0x10,
280 		.size		= 0x14,
281 		.id		= 0x80,
282 	}, {
283 		.name		= "cio-das16/jr",
284 		.ai_maxdata	= 0x0fff,
285 		.ai_speed	= 7692,
286 		.ai_pg		= das16_pg_16jr,
287 		.size		= 0x10,
288 		.id		= 0x00,
289 	}, {
290 		.name		= "pc104-das16jr",
291 		.ai_maxdata	= 0x0fff,
292 		.ai_speed	= 3300,
293 		.ai_pg		= das16_pg_16jr,
294 		.size		= 0x10,
295 		.id		= 0x00,
296 	}, {
297 		.name		= "cio-das16jr/16",
298 		.ai_maxdata	= 0xffff,
299 		.ai_speed	= 10000,
300 		.ai_pg		= das16_pg_16jr_16,
301 		.size		= 0x10,
302 		.id		= 0x00,
303 	}, {
304 		.name		= "pc104-das16jr/16",
305 		.ai_maxdata	= 0xffff,
306 		.ai_speed	= 10000,
307 		.ai_pg		= das16_pg_16jr_16,
308 		.size		= 0x10,
309 		.id		= 0x00,
310 	}, {
311 		.name		= "das-1201",
312 		.ai_maxdata	= 0x0fff,
313 		.ai_speed	= 20000,
314 		.ai_pg		= das16_pg_none,
315 		.has_8255	= 1,
316 		.i8255_offset	= 0x400,
317 		.size		= 0x408,
318 		.id		= 0x20,
319 	}, {
320 		.name		= "das-1202",
321 		.ai_maxdata	= 0x0fff,
322 		.ai_speed	= 10000,
323 		.ai_pg		= das16_pg_none,
324 		.has_8255	= 1,
325 		.i8255_offset	= 0x400,
326 		.size		= 0x408,
327 		.id		= 0x20,
328 	}, {
329 		.name		= "das-1401",
330 		.ai_maxdata	= 0x0fff,
331 		.ai_speed	= 10000,
332 		.ai_pg		= das16_pg_1601,
333 		.size		= 0x408,
334 		.id		= 0xc0,
335 	}, {
336 		.name		= "das-1402",
337 		.ai_maxdata	= 0x0fff,
338 		.ai_speed	= 10000,
339 		.ai_pg		= das16_pg_1602,
340 		.size		= 0x408,
341 		.id		= 0xc0,
342 	}, {
343 		.name		= "das-1601",
344 		.ai_maxdata	= 0x0fff,
345 		.ai_speed	= 10000,
346 		.ai_pg		= das16_pg_1601,
347 		.has_ao		= 1,
348 		.has_8255	= 1,
349 		.i8255_offset	= 0x400,
350 		.size		= 0x408,
351 		.id		= 0xc0,
352 	}, {
353 		.name		= "das-1602",
354 		.ai_maxdata	= 0x0fff,
355 		.ai_speed	= 10000,
356 		.ai_pg		= das16_pg_1602,
357 		.has_ao		= 1,
358 		.has_8255	= 1,
359 		.i8255_offset	= 0x400,
360 		.size		= 0x408,
361 		.id		= 0xc0,
362 	}, {
363 		.name		= "cio-das1401/12",
364 		.ai_maxdata	= 0x0fff,
365 		.ai_speed	= 6250,
366 		.ai_pg		= das16_pg_1601,
367 		.size		= 0x408,
368 		.id		= 0xc0,
369 	}, {
370 		.name		= "cio-das1402/12",
371 		.ai_maxdata	= 0x0fff,
372 		.ai_speed	= 6250,
373 		.ai_pg		= das16_pg_1602,
374 		.size		= 0x408,
375 		.id		= 0xc0,
376 	}, {
377 		.name		= "cio-das1402/16",
378 		.ai_maxdata	= 0xffff,
379 		.ai_speed	= 10000,
380 		.ai_pg		= das16_pg_1602,
381 		.size		= 0x408,
382 		.id		= 0xc0,
383 	}, {
384 		.name		= "cio-das1601/12",
385 		.ai_maxdata	= 0x0fff,
386 		.ai_speed	= 6250,
387 		.ai_pg		= das16_pg_1601,
388 		.has_ao		= 1,
389 		.has_8255	= 1,
390 		.i8255_offset	= 0x400,
391 		.size		= 0x408,
392 		.id		= 0xc0,
393 	}, {
394 		.name		= "cio-das1602/12",
395 		.ai_maxdata	= 0x0fff,
396 		.ai_speed	= 10000,
397 		.ai_pg		= das16_pg_1602,
398 		.has_ao		= 1,
399 		.has_8255	= 1,
400 		.i8255_offset	= 0x400,
401 		.size		= 0x408,
402 		.id		= 0xc0,
403 	}, {
404 		.name		= "cio-das1602/16",
405 		.ai_maxdata	= 0xffff,
406 		.ai_speed	= 10000,
407 		.ai_pg		= das16_pg_1602,
408 		.has_ao		= 1,
409 		.has_8255	= 1,
410 		.i8255_offset	= 0x400,
411 		.size		= 0x408,
412 		.id		= 0xc0,
413 	}, {
414 		.name		= "cio-das16/330",
415 		.ai_maxdata	= 0x0fff,
416 		.ai_speed	= 3030,
417 		.ai_pg		= das16_pg_16jr,
418 		.size		= 0x14,
419 		.id		= 0xf0,
420 	},
421 };
422 
423 /*
424  * Period for timer interrupt in jiffies.  It's a function
425  * to deal with possibility of dynamic HZ patches
426  */
timer_period(void)427 static inline int timer_period(void)
428 {
429 	return HZ / 20;
430 }
431 
432 struct das16_private_struct {
433 	struct comedi_isadma	*dma;
434 	struct comedi_device	*dev;
435 	unsigned int		clockbase;
436 	unsigned int		ctrl_reg;
437 	unsigned int		divisor1;
438 	unsigned int		divisor2;
439 	struct timer_list	timer;
440 	unsigned long		extra_iobase;
441 	unsigned int		can_burst:1;
442 	unsigned int		timer_running:1;
443 };
444 
das16_ai_setup_dma(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int unread_samples)445 static void das16_ai_setup_dma(struct comedi_device *dev,
446 			       struct comedi_subdevice *s,
447 			       unsigned int unread_samples)
448 {
449 	struct das16_private_struct *devpriv = dev->private;
450 	struct comedi_isadma *dma = devpriv->dma;
451 	struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
452 	unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize);
453 	unsigned int nsamples;
454 
455 	/*
456 	 * Determine dma size based on the buffer size plus the number of
457 	 * unread samples and the number of samples remaining in the command.
458 	 */
459 	nsamples = comedi_nsamples_left(s, max_samples + unread_samples);
460 	if (nsamples > unread_samples) {
461 		nsamples -= unread_samples;
462 		desc->size = comedi_samples_to_bytes(s, nsamples);
463 		comedi_isadma_program(desc);
464 	}
465 }
466 
das16_interrupt(struct comedi_device * dev)467 static void das16_interrupt(struct comedi_device *dev)
468 {
469 	struct das16_private_struct *devpriv = dev->private;
470 	struct comedi_subdevice *s = dev->read_subdev;
471 	struct comedi_async *async = s->async;
472 	struct comedi_cmd *cmd = &async->cmd;
473 	struct comedi_isadma *dma = devpriv->dma;
474 	struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
475 	unsigned long spin_flags;
476 	unsigned int residue;
477 	unsigned int nbytes;
478 	unsigned int nsamples;
479 
480 	spin_lock_irqsave(&dev->spinlock, spin_flags);
481 	if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
482 		spin_unlock_irqrestore(&dev->spinlock, spin_flags);
483 		return;
484 	}
485 
486 	/*
487 	 * The pc104-das16jr (at least) has problems if the dma
488 	 * transfer is interrupted in the middle of transferring
489 	 * a 16 bit sample.
490 	 */
491 	residue = comedi_isadma_disable_on_sample(desc->chan,
492 						  comedi_bytes_per_sample(s));
493 
494 	/* figure out how many samples to read */
495 	if (residue > desc->size) {
496 		dev_err(dev->class_dev, "residue > transfer size!\n");
497 		async->events |= COMEDI_CB_ERROR;
498 		nbytes = 0;
499 	} else {
500 		nbytes = desc->size - residue;
501 	}
502 	nsamples = comedi_bytes_to_samples(s, nbytes);
503 
504 	/* restart DMA if more samples are needed */
505 	if (nsamples) {
506 		dma->cur_dma = 1 - dma->cur_dma;
507 		das16_ai_setup_dma(dev, s, nsamples);
508 	}
509 
510 	spin_unlock_irqrestore(&dev->spinlock, spin_flags);
511 
512 	comedi_buf_write_samples(s, desc->virt_addr, nsamples);
513 
514 	if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
515 		async->events |= COMEDI_CB_EOA;
516 
517 	comedi_handle_events(dev, s);
518 }
519 
das16_timer_interrupt(struct timer_list * t)520 static void das16_timer_interrupt(struct timer_list *t)
521 {
522 	struct das16_private_struct *devpriv = from_timer(devpriv, t, timer);
523 	struct comedi_device *dev = devpriv->dev;
524 	unsigned long flags;
525 
526 	das16_interrupt(dev);
527 
528 	spin_lock_irqsave(&dev->spinlock, flags);
529 	if (devpriv->timer_running)
530 		mod_timer(&devpriv->timer, jiffies + timer_period());
531 	spin_unlock_irqrestore(&dev->spinlock, flags);
532 }
533 
das16_ai_set_mux_range(struct comedi_device * dev,unsigned int first_chan,unsigned int last_chan,unsigned int range)534 static void das16_ai_set_mux_range(struct comedi_device *dev,
535 				   unsigned int first_chan,
536 				   unsigned int last_chan,
537 				   unsigned int range)
538 {
539 	const struct das16_board *board = dev->board_ptr;
540 
541 	/* set multiplexer */
542 	outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG);
543 
544 	/* some boards do not have programmable gain */
545 	if (board->ai_pg == das16_pg_none)
546 		return;
547 
548 	/*
549 	 * Set gain (this is also burst rate register but according to
550 	 * computer boards manual, burst rate does nothing, even on
551 	 * keithley cards).
552 	 */
553 	outb((das16_gainlists[board->ai_pg])[range],
554 	     dev->iobase + DAS16_GAIN_REG);
555 }
556 
das16_ai_check_chanlist(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)557 static int das16_ai_check_chanlist(struct comedi_device *dev,
558 				   struct comedi_subdevice *s,
559 				   struct comedi_cmd *cmd)
560 {
561 	unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
562 	unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
563 	int i;
564 
565 	for (i = 1; i < cmd->chanlist_len; i++) {
566 		unsigned int chan = CR_CHAN(cmd->chanlist[i]);
567 		unsigned int range = CR_RANGE(cmd->chanlist[i]);
568 
569 		if (chan != ((chan0 + i) % s->n_chan)) {
570 			dev_dbg(dev->class_dev,
571 				"entries in chanlist must be consecutive channels, counting upwards\n");
572 			return -EINVAL;
573 		}
574 
575 		if (range != range0) {
576 			dev_dbg(dev->class_dev,
577 				"entries in chanlist must all have the same gain\n");
578 			return -EINVAL;
579 		}
580 	}
581 
582 	return 0;
583 }
584 
das16_cmd_test(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)585 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
586 			  struct comedi_cmd *cmd)
587 {
588 	const struct das16_board *board = dev->board_ptr;
589 	struct das16_private_struct *devpriv = dev->private;
590 	int err = 0;
591 	unsigned int trig_mask;
592 	unsigned int arg;
593 
594 	/* Step 1 : check if triggers are trivially valid */
595 
596 	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
597 
598 	trig_mask = TRIG_FOLLOW;
599 	if (devpriv->can_burst)
600 		trig_mask |= TRIG_TIMER | TRIG_EXT;
601 	err |= comedi_check_trigger_src(&cmd->scan_begin_src, trig_mask);
602 
603 	trig_mask = TRIG_TIMER | TRIG_EXT;
604 	if (devpriv->can_burst)
605 		trig_mask |= TRIG_NOW;
606 	err |= comedi_check_trigger_src(&cmd->convert_src, trig_mask);
607 
608 	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
609 	err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
610 
611 	if (err)
612 		return 1;
613 
614 	/* Step 2a : make sure trigger sources are unique */
615 
616 	err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
617 	err |= comedi_check_trigger_is_unique(cmd->convert_src);
618 	err |= comedi_check_trigger_is_unique(cmd->stop_src);
619 
620 	/* Step 2b : and mutually compatible */
621 
622 	/*  make sure scan_begin_src and convert_src don't conflict */
623 	if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
624 		err |= -EINVAL;
625 	if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
626 		err |= -EINVAL;
627 
628 	if (err)
629 		return 2;
630 
631 	/* Step 3: check if arguments are trivially valid */
632 
633 	err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
634 
635 	if (cmd->scan_begin_src == TRIG_FOLLOW)	/* internal trigger */
636 		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
637 
638 	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
639 					   cmd->chanlist_len);
640 
641 	/* check against maximum frequency */
642 	if (cmd->scan_begin_src == TRIG_TIMER) {
643 		err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
644 						    board->ai_speed *
645 						    cmd->chanlist_len);
646 	}
647 
648 	if (cmd->convert_src == TRIG_TIMER) {
649 		err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
650 						    board->ai_speed);
651 	}
652 
653 	if (cmd->stop_src == TRIG_COUNT)
654 		err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
655 	else	/* TRIG_NONE */
656 		err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
657 
658 	if (err)
659 		return 3;
660 
661 	/*  step 4: fix up arguments */
662 	if (cmd->scan_begin_src == TRIG_TIMER) {
663 		arg = cmd->scan_begin_arg;
664 		comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
665 		err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
666 	}
667 	if (cmd->convert_src == TRIG_TIMER) {
668 		arg = cmd->convert_arg;
669 		comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
670 		err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
671 	}
672 	if (err)
673 		return 4;
674 
675 	/* Step 5: check channel list if it exists */
676 	if (cmd->chanlist && cmd->chanlist_len > 0)
677 		err |= das16_ai_check_chanlist(dev, s, cmd);
678 
679 	if (err)
680 		return 5;
681 
682 	return 0;
683 }
684 
das16_set_pacer(struct comedi_device * dev,unsigned int ns,unsigned int flags)685 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
686 				    unsigned int flags)
687 {
688 	comedi_8254_cascade_ns_to_timer(dev->pacer, &ns, flags);
689 	comedi_8254_update_divisors(dev->pacer);
690 	comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
691 
692 	return ns;
693 }
694 
das16_cmd_exec(struct comedi_device * dev,struct comedi_subdevice * s)695 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
696 {
697 	struct das16_private_struct *devpriv = dev->private;
698 	struct comedi_isadma *dma = devpriv->dma;
699 	struct comedi_async *async = s->async;
700 	struct comedi_cmd *cmd = &async->cmd;
701 	unsigned int first_chan = CR_CHAN(cmd->chanlist[0]);
702 	unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
703 	unsigned int range = CR_RANGE(cmd->chanlist[0]);
704 	unsigned int byte;
705 	unsigned long flags;
706 
707 	if (cmd->flags & CMDF_PRIORITY) {
708 		dev_err(dev->class_dev,
709 			"isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
710 		return -1;
711 	}
712 
713 	if (devpriv->can_burst)
714 		outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
715 
716 	/* set mux and range for chanlist scan */
717 	das16_ai_set_mux_range(dev, first_chan, last_chan, range);
718 
719 	/* set counter mode and counts */
720 	cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
721 
722 	/* enable counters */
723 	byte = 0;
724 	if (devpriv->can_burst) {
725 		if (cmd->convert_src == TRIG_NOW) {
726 			outb(DAS1600_BURST_VAL,
727 			     dev->iobase + DAS1600_BURST_REG);
728 			/*  set burst length */
729 			byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
730 		} else {
731 			outb(0, dev->iobase + DAS1600_BURST_REG);
732 		}
733 	}
734 	outb(byte, dev->iobase + DAS16_PACER_REG);
735 
736 	/* set up dma transfer */
737 	dma->cur_dma = 0;
738 	das16_ai_setup_dma(dev, s, 0);
739 
740 	/*  set up timer */
741 	spin_lock_irqsave(&dev->spinlock, flags);
742 	devpriv->timer_running = 1;
743 	devpriv->timer.expires = jiffies + timer_period();
744 	add_timer(&devpriv->timer);
745 
746 	/* enable DMA interrupt with external or internal pacing */
747 	devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK);
748 	devpriv->ctrl_reg |= DAS16_CTRL_DMAE;
749 	if (cmd->convert_src == TRIG_EXT)
750 		devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
751 	else
752 		devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
753 	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
754 
755 	if (devpriv->can_burst)
756 		outb(0, dev->iobase + DAS1600_CONV_REG);
757 	spin_unlock_irqrestore(&dev->spinlock, flags);
758 
759 	return 0;
760 }
761 
das16_cancel(struct comedi_device * dev,struct comedi_subdevice * s)762 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
763 {
764 	struct das16_private_struct *devpriv = dev->private;
765 	struct comedi_isadma *dma = devpriv->dma;
766 	unsigned long flags;
767 
768 	spin_lock_irqsave(&dev->spinlock, flags);
769 
770 	/* disable interrupts, dma and pacer clocked conversions */
771 	devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE |
772 			       DAS16_CTRL_PACING_MASK);
773 	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
774 
775 	comedi_isadma_disable(dma->chan);
776 
777 	/*  disable SW timer */
778 	if (devpriv->timer_running) {
779 		devpriv->timer_running = 0;
780 		del_timer(&devpriv->timer);
781 	}
782 
783 	if (devpriv->can_burst)
784 		outb(0, dev->iobase + DAS1600_BURST_REG);
785 
786 	spin_unlock_irqrestore(&dev->spinlock, flags);
787 
788 	return 0;
789 }
790 
das16_ai_munge(struct comedi_device * dev,struct comedi_subdevice * s,void * array,unsigned int num_bytes,unsigned int start_chan_index)791 static void das16_ai_munge(struct comedi_device *dev,
792 			   struct comedi_subdevice *s, void *array,
793 			   unsigned int num_bytes,
794 			   unsigned int start_chan_index)
795 {
796 	unsigned short *data = array;
797 	unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
798 	unsigned int i;
799 	__le16 *buf = array;
800 
801 	for (i = 0; i < num_samples; i++) {
802 		data[i] = le16_to_cpu(buf[i]);
803 		if (s->maxdata == 0x0fff)
804 			data[i] >>= 4;
805 		data[i] &= s->maxdata;
806 	}
807 }
808 
das16_ai_eoc(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned long context)809 static int das16_ai_eoc(struct comedi_device *dev,
810 			struct comedi_subdevice *s,
811 			struct comedi_insn *insn,
812 			unsigned long context)
813 {
814 	unsigned int status;
815 
816 	status = inb(dev->iobase + DAS16_STATUS_REG);
817 	if ((status & DAS16_STATUS_BUSY) == 0)
818 		return 0;
819 	return -EBUSY;
820 }
821 
das16_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)822 static int das16_ai_insn_read(struct comedi_device *dev,
823 			      struct comedi_subdevice *s,
824 			      struct comedi_insn *insn,
825 			      unsigned int *data)
826 {
827 	unsigned int chan = CR_CHAN(insn->chanspec);
828 	unsigned int range = CR_RANGE(insn->chanspec);
829 	unsigned int val;
830 	int ret;
831 	int i;
832 
833 	/* set mux and range for single channel */
834 	das16_ai_set_mux_range(dev, chan, chan, range);
835 
836 	for (i = 0; i < insn->n; i++) {
837 		/* trigger conversion */
838 		outb_p(0, dev->iobase + DAS16_TRIG_REG);
839 
840 		ret = comedi_timeout(dev, s, insn, das16_ai_eoc, 0);
841 		if (ret)
842 			return ret;
843 
844 		val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
845 		val |= inb(dev->iobase + DAS16_AI_LSB_REG);
846 		if (s->maxdata == 0x0fff)
847 			val >>= 4;
848 		val &= s->maxdata;
849 
850 		data[i] = val;
851 	}
852 
853 	return insn->n;
854 }
855 
das16_ao_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)856 static int das16_ao_insn_write(struct comedi_device *dev,
857 			       struct comedi_subdevice *s,
858 			       struct comedi_insn *insn,
859 			       unsigned int *data)
860 {
861 	unsigned int chan = CR_CHAN(insn->chanspec);
862 	int i;
863 
864 	for (i = 0; i < insn->n; i++) {
865 		unsigned int val = data[i];
866 
867 		s->readback[chan] = val;
868 
869 		val <<= 4;
870 
871 		outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
872 		outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
873 	}
874 
875 	return insn->n;
876 }
877 
das16_di_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)878 static int das16_di_insn_bits(struct comedi_device *dev,
879 			      struct comedi_subdevice *s,
880 			      struct comedi_insn *insn,
881 			      unsigned int *data)
882 {
883 	data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
884 
885 	return insn->n;
886 }
887 
das16_do_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)888 static int das16_do_insn_bits(struct comedi_device *dev,
889 			      struct comedi_subdevice *s,
890 			      struct comedi_insn *insn,
891 			      unsigned int *data)
892 {
893 	if (comedi_dio_update_state(s, data))
894 		outb(s->state, dev->iobase + DAS16_DIO_REG);
895 
896 	data[1] = s->state;
897 
898 	return insn->n;
899 }
900 
das16_probe(struct comedi_device * dev,struct comedi_devconfig * it)901 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
902 {
903 	const struct das16_board *board = dev->board_ptr;
904 	int diobits;
905 
906 	/* diobits indicates boards */
907 	diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
908 	if (board->id != diobits) {
909 		dev_err(dev->class_dev,
910 			"requested board's id bits are incorrect (0x%x != 0x%x)\n",
911 			board->id, diobits);
912 		return -EINVAL;
913 	}
914 
915 	return 0;
916 }
917 
das16_reset(struct comedi_device * dev)918 static void das16_reset(struct comedi_device *dev)
919 {
920 	outb(0, dev->iobase + DAS16_STATUS_REG);
921 	outb(0, dev->iobase + DAS16_CTRL_REG);
922 	outb(0, dev->iobase + DAS16_PACER_REG);
923 }
924 
das16_alloc_dma(struct comedi_device * dev,unsigned int dma_chan)925 static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
926 {
927 	struct das16_private_struct *devpriv = dev->private;
928 
929 	timer_setup(&devpriv->timer, das16_timer_interrupt, 0);
930 
931 	/* only DMA channels 3 and 1 are valid */
932 	if (!(dma_chan == 1 || dma_chan == 3))
933 		return;
934 
935 	/* DMA uses two buffers */
936 	devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan,
937 					   DAS16_DMA_SIZE, COMEDI_ISADMA_READ);
938 }
939 
das16_free_dma(struct comedi_device * dev)940 static void das16_free_dma(struct comedi_device *dev)
941 {
942 	struct das16_private_struct *devpriv = dev->private;
943 
944 	if (devpriv) {
945 		del_timer_sync(&devpriv->timer);
946 		comedi_isadma_free(devpriv->dma);
947 	}
948 }
949 
das16_ai_range(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_devconfig * it,unsigned int pg_type,unsigned int status)950 static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev,
951 						  struct comedi_subdevice *s,
952 						  struct comedi_devconfig *it,
953 						  unsigned int pg_type,
954 						  unsigned int status)
955 {
956 	unsigned int min = it->options[4];
957 	unsigned int max = it->options[5];
958 
959 	/* get any user-defined input range */
960 	if (pg_type == das16_pg_none && (min || max)) {
961 		struct comedi_lrange *lrange;
962 		struct comedi_krange *krange;
963 
964 		/* allocate single-range range table */
965 		lrange = comedi_alloc_spriv(s,
966 					    sizeof(*lrange) + sizeof(*krange));
967 		if (!lrange)
968 			return &range_unknown;
969 
970 		/* initialize ai range */
971 		lrange->length = 1;
972 		krange = lrange->range;
973 		krange->min = min;
974 		krange->max = max;
975 		krange->flags = UNIT_volt;
976 
977 		return lrange;
978 	}
979 
980 	/* use software programmable range */
981 	if (status & DAS16_STATUS_UNIPOLAR)
982 		return das16_ai_uni_lranges[pg_type];
983 	return das16_ai_bip_lranges[pg_type];
984 }
985 
das16_ao_range(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_devconfig * it)986 static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev,
987 						  struct comedi_subdevice *s,
988 						  struct comedi_devconfig *it)
989 {
990 	unsigned int min = it->options[6];
991 	unsigned int max = it->options[7];
992 
993 	/* get any user-defined output range */
994 	if (min || max) {
995 		struct comedi_lrange *lrange;
996 		struct comedi_krange *krange;
997 
998 		/* allocate single-range range table */
999 		lrange = comedi_alloc_spriv(s,
1000 					    sizeof(*lrange) + sizeof(*krange));
1001 		if (!lrange)
1002 			return &range_unknown;
1003 
1004 		/* initialize ao range */
1005 		lrange->length = 1;
1006 		krange = lrange->range;
1007 		krange->min = min;
1008 		krange->max = max;
1009 		krange->flags = UNIT_volt;
1010 
1011 		return lrange;
1012 	}
1013 
1014 	return &range_unknown;
1015 }
1016 
das16_attach(struct comedi_device * dev,struct comedi_devconfig * it)1017 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1018 {
1019 	const struct das16_board *board = dev->board_ptr;
1020 	struct das16_private_struct *devpriv;
1021 	struct comedi_subdevice *s;
1022 	unsigned int osc_base;
1023 	unsigned int status;
1024 	int ret;
1025 
1026 	/*  check that clock setting is valid */
1027 	if (it->options[3]) {
1028 		if (it->options[3] != 1 && it->options[3] != 10) {
1029 			dev_err(dev->class_dev,
1030 				"Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1031 			return -EINVAL;
1032 		}
1033 	}
1034 
1035 	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1036 	if (!devpriv)
1037 		return -ENOMEM;
1038 	devpriv->dev = dev;
1039 
1040 	if (board->size < 0x400) {
1041 		ret = comedi_request_region(dev, it->options[0], board->size);
1042 		if (ret)
1043 			return ret;
1044 	} else {
1045 		ret = comedi_request_region(dev, it->options[0], 0x10);
1046 		if (ret)
1047 			return ret;
1048 		/* Request an additional region for the 8255 */
1049 		ret = __comedi_request_region(dev, dev->iobase + 0x400,
1050 					      board->size & 0x3ff);
1051 		if (ret)
1052 			return ret;
1053 		devpriv->extra_iobase = dev->iobase + 0x400;
1054 		devpriv->can_burst = 1;
1055 	}
1056 
1057 	/*  probe id bits to make sure they are consistent */
1058 	if (das16_probe(dev, it))
1059 		return -EINVAL;
1060 
1061 	/*  get master clock speed */
1062 	osc_base = I8254_OSC_BASE_1MHZ;
1063 	if (devpriv->can_burst) {
1064 		status = inb(dev->iobase + DAS1600_STATUS_REG);
1065 		if (status & DAS1600_STATUS_CLK_10MHZ)
1066 			osc_base = I8254_OSC_BASE_10MHZ;
1067 	} else {
1068 		if (it->options[3])
1069 			osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
1070 	}
1071 
1072 	dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
1073 				      osc_base, I8254_IO8, 0);
1074 	if (!dev->pacer)
1075 		return -ENOMEM;
1076 
1077 	das16_alloc_dma(dev, it->options[2]);
1078 
1079 	ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1080 	if (ret)
1081 		return ret;
1082 
1083 	status = inb(dev->iobase + DAS16_STATUS_REG);
1084 
1085 	/* Analog Input subdevice */
1086 	s = &dev->subdevices[0];
1087 	s->type		= COMEDI_SUBD_AI;
1088 	s->subdev_flags	= SDF_READABLE;
1089 	if (status & DAS16_STATUS_MUXBIT) {
1090 		s->subdev_flags	|= SDF_GROUND;
1091 		s->n_chan	= 16;
1092 	} else {
1093 		s->subdev_flags	|= SDF_DIFF;
1094 		s->n_chan	= 8;
1095 	}
1096 	s->len_chanlist	= s->n_chan;
1097 	s->maxdata	= board->ai_maxdata;
1098 	s->range_table	= das16_ai_range(dev, s, it, board->ai_pg, status);
1099 	s->insn_read	= das16_ai_insn_read;
1100 	if (devpriv->dma) {
1101 		dev->read_subdev = s;
1102 		s->subdev_flags	|= SDF_CMD_READ;
1103 		s->do_cmdtest	= das16_cmd_test;
1104 		s->do_cmd	= das16_cmd_exec;
1105 		s->cancel	= das16_cancel;
1106 		s->munge	= das16_ai_munge;
1107 	}
1108 
1109 	/* Analog Output subdevice */
1110 	s = &dev->subdevices[1];
1111 	if (board->has_ao) {
1112 		s->type		= COMEDI_SUBD_AO;
1113 		s->subdev_flags	= SDF_WRITABLE;
1114 		s->n_chan	= 2;
1115 		s->maxdata	= 0x0fff;
1116 		s->range_table	= das16_ao_range(dev, s, it);
1117 		s->insn_write	= das16_ao_insn_write;
1118 
1119 		ret = comedi_alloc_subdev_readback(s);
1120 		if (ret)
1121 			return ret;
1122 	} else {
1123 		s->type		= COMEDI_SUBD_UNUSED;
1124 	}
1125 
1126 	/* Digital Input subdevice */
1127 	s = &dev->subdevices[2];
1128 	s->type		= COMEDI_SUBD_DI;
1129 	s->subdev_flags	= SDF_READABLE;
1130 	s->n_chan	= 4;
1131 	s->maxdata	= 1;
1132 	s->range_table	= &range_digital;
1133 	s->insn_bits	= das16_di_insn_bits;
1134 
1135 	/* Digital Output subdevice */
1136 	s = &dev->subdevices[3];
1137 	s->type		= COMEDI_SUBD_DO;
1138 	s->subdev_flags	= SDF_WRITABLE;
1139 	s->n_chan	= 4;
1140 	s->maxdata	= 1;
1141 	s->range_table	= &range_digital;
1142 	s->insn_bits	= das16_do_insn_bits;
1143 
1144 	/* initialize digital output lines */
1145 	outb(s->state, dev->iobase + DAS16_DIO_REG);
1146 
1147 	/* 8255 Digital I/O subdevice */
1148 	if (board->has_8255) {
1149 		s = &dev->subdevices[4];
1150 		ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
1151 		if (ret)
1152 			return ret;
1153 	}
1154 
1155 	das16_reset(dev);
1156 	/* set the interrupt level */
1157 	devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1158 	outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1159 
1160 	if (devpriv->can_burst) {
1161 		outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1162 		outb(0, dev->iobase + DAS1600_CONV_REG);
1163 		outb(0, dev->iobase + DAS1600_BURST_REG);
1164 	}
1165 
1166 	return 0;
1167 }
1168 
das16_detach(struct comedi_device * dev)1169 static void das16_detach(struct comedi_device *dev)
1170 {
1171 	const struct das16_board *board = dev->board_ptr;
1172 	struct das16_private_struct *devpriv = dev->private;
1173 
1174 	if (devpriv) {
1175 		if (dev->iobase)
1176 			das16_reset(dev);
1177 		das16_free_dma(dev);
1178 
1179 		if (devpriv->extra_iobase)
1180 			release_region(devpriv->extra_iobase,
1181 				       board->size & 0x3ff);
1182 	}
1183 
1184 	comedi_legacy_detach(dev);
1185 }
1186 
1187 static struct comedi_driver das16_driver = {
1188 	.driver_name	= "das16",
1189 	.module		= THIS_MODULE,
1190 	.attach		= das16_attach,
1191 	.detach		= das16_detach,
1192 	.board_name	= &das16_boards[0].name,
1193 	.num_names	= ARRAY_SIZE(das16_boards),
1194 	.offset		= sizeof(das16_boards[0]),
1195 };
1196 module_comedi_driver(das16_driver);
1197 
1198 MODULE_AUTHOR("Comedi https://www.comedi.org");
1199 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1200 MODULE_LICENSE("GPL");
1201