1 /*
2 comedi/drivers/das16.c
3 DAS16 driver
4
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
8 Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
9
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
24 ************************************************************************
25 */
26 /*
27 Driver: das16
28 Description: DAS16 compatible boards
29 Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
30 Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
31 DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
32 DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
33 DAS-1602 (das-1602),
34 [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
35 PC104-DAS16JR/16 (pc104-das16jr/16),
36 CIO-DAS16JR/16 (cio-das16jr/16),
37 CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
38 CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
39 CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
40 CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
41 Status: works
42 Updated: 2003-10-12
43
44 A rewrite of the das16 and das1600 drivers.
45 Options:
46 [0] - base io address
47 [1] - irq (does nothing, irq is not used anymore)
48 [2] - dma (optional, required for comedi_command support)
49 [3] - master clock speed in MHz (optional, 1 or 10, ignored if
50 board can probe clock, defaults to 1)
51 [4] - analog input range lowest voltage in microvolts (optional,
52 only useful if your board does not have software
53 programmable gain)
54 [5] - analog input range highest voltage in microvolts (optional,
55 only useful if board does not have software programmable
56 gain)
57 [6] - analog output range lowest voltage in microvolts (optional)
58 [7] - analog output range highest voltage in microvolts (optional)
59 [8] - use timer mode for DMA. Timer mode is needed e.g. for
60 buggy DMA controllers in NS CS5530A (Geode Companion), and for
61 'jr' cards that lack a hardware fifo. This option is no
62 longer needed, since timer mode is _always_ used.
63
64 Passing a zero for an option is the same as leaving it unspecified.
65
66 */
67 /*
68
69 Testing and debugging help provided by Daniel Koch.
70
71 Keithley Manuals:
72 2309.PDF (das16)
73 4919.PDF (das1400, 1600)
74 4922.PDF (das-1400)
75 4923.PDF (das1200, 1400, 1600)
76
77 Computer boards manuals also available from their website www.measurementcomputing.com
78
79 */
80
81 #include <linux/pci.h>
82 #include <linux/interrupt.h>
83 #include <asm/dma.h>
84 #include "../comedidev.h"
85
86 #include "8253.h"
87 #include "8255.h"
88 #include "comedi_fc.h"
89
90 #undef DEBUG
91 /* #define DEBUG */
92
93 #ifdef DEBUG
94 #define DEBUG_PRINT(format, args...) printk("das16: " format, ## args)
95 #else
96 #define DEBUG_PRINT(format, args...)
97 #endif
98
99 #define DAS16_SIZE 20 /* number of ioports */
100 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
101
102 /*
103 cio-das16.pdf
104
105 "das16"
106 "das16/f"
107
108 0 a/d bits 0-3 start 12 bit
109 1 a/d bits 4-11 unused
110 2 mux read mux set
111 3 di 4 bit do 4 bit
112 4 unused ao0_lsb
113 5 unused ao0_msb
114 6 unused ao1_lsb
115 7 unused ao1_msb
116 8 status eoc uni/bip interrupt reset
117 9 dma, int, trig ctrl set dma, int
118 a pacer control unused
119 b reserved reserved
120 cdef 8254
121 0123 8255
122
123 */
124
125 /*
126 cio-das16jr.pdf
127
128 "das16jr"
129
130 0 a/d bits 0-3 start 12 bit
131 1 a/d bits 4-11 unused
132 2 mux read mux set
133 3 di 4 bit do 4 bit
134 4567 unused unused
135 8 status eoc uni/bip interrupt reset
136 9 dma, int, trig ctrl set dma, int
137 a pacer control unused
138 b gain status gain control
139 cdef 8254
140
141 */
142
143 /*
144 cio-das16jr_16.pdf
145
146 "das16jr_16"
147
148 0 a/d bits 0-7 start 16 bit
149 1 a/d bits 8-15 unused
150 2 mux read mux set
151 3 di 4 bit do 4 bit
152 4567 unused unused
153 8 status eoc uni/bip interrupt reset
154 9 dma, int, trig ctrl set dma, int
155 a pacer control unused
156 b gain status gain control
157 cdef 8254
158
159 */
160 /*
161 cio-das160x-1x.pdf
162
163 "das1601/12"
164 "das1602/12"
165 "das1602/16"
166
167 0 a/d bits 0-3 start 12 bit
168 1 a/d bits 4-11 unused
169 2 mux read mux set
170 3 di 4 bit do 4 bit
171 4 unused ao0_lsb
172 5 unused ao0_msb
173 6 unused ao1_lsb
174 7 unused ao1_msb
175 8 status eoc uni/bip interrupt reset
176 9 dma, int, trig ctrl set dma, int
177 a pacer control unused
178 b gain status gain control
179 cdef 8254
180 400 8255
181 404 unused conversion enable
182 405 unused burst enable
183 406 unused das1600 enable
184 407 status
185
186 */
187
188 static const int sample_size = 2; /* size in bytes of a sample from board */
189
190 #define DAS16_TRIG 0
191 #define DAS16_AI_LSB 0
192 #define DAS16_AI_MSB 1
193 #define DAS16_MUX 2
194 #define DAS16_DIO 3
195 #define DAS16_AO_LSB(x) ((x)?6:4)
196 #define DAS16_AO_MSB(x) ((x)?7:5)
197 #define DAS16_STATUS 8
198 #define BUSY (1<<7)
199 #define UNIPOLAR (1<<6)
200 #define DAS16_MUXBIT (1<<5)
201 #define DAS16_INT (1<<4)
202 #define DAS16_CONTROL 9
203 #define DAS16_INTE (1<<7)
204 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
205 #define DMA_ENABLE (1<<2)
206 #define PACING_MASK 0x3
207 #define INT_PACER 0x03
208 #define EXT_PACER 0x02
209 #define DAS16_SOFT 0x00
210 #define DAS16_PACER 0x0A
211 #define DAS16_CTR0 (1<<1)
212 #define DAS16_TRIG0 (1<<0)
213 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
214 #define DAS16_GAIN 0x0B
215 #define DAS16_CNTR0_DATA 0x0C
216 #define DAS16_CNTR1_DATA 0x0D
217 #define DAS16_CNTR2_DATA 0x0E
218 #define DAS16_CNTR_CONTROL 0x0F
219 #define DAS16_TERM_CNT 0x00
220 #define DAS16_ONE_SHOT 0x02
221 #define DAS16_RATE_GEN 0x04
222 #define DAS16_CNTR_LSB_MSB 0x30
223 #define DAS16_CNTR0 0x00
224 #define DAS16_CNTR1 0x40
225 #define DAS16_CNTR2 0x80
226
227 #define DAS1600_CONV 0x404
228 #define DAS1600_CONV_DISABLE 0x40
229 #define DAS1600_BURST 0x405
230 #define DAS1600_BURST_VAL 0x40
231 #define DAS1600_ENABLE 0x406
232 #define DAS1600_ENABLE_VAL 0x40
233 #define DAS1600_STATUS_B 0x407
234 #define DAS1600_BME 0x40
235 #define DAS1600_ME 0x20
236 #define DAS1600_CD 0x10
237 #define DAS1600_WS 0x02
238 #define DAS1600_CLK_10MHZ 0x01
239
240 static const struct comedi_lrange range_das1x01_bip = { 4, {
241 BIP_RANGE(10),
242 BIP_RANGE(1),
243 BIP_RANGE(0.1),
244 BIP_RANGE(0.01),
245 }
246 };
247 static const struct comedi_lrange range_das1x01_unip = { 4, {
248 UNI_RANGE(10),
249 UNI_RANGE(1),
250 UNI_RANGE(0.1),
251 UNI_RANGE(0.01),
252 }
253 };
254 static const struct comedi_lrange range_das1x02_bip = { 4, {
255 BIP_RANGE(10),
256 BIP_RANGE(5),
257 BIP_RANGE(2.5),
258 BIP_RANGE(1.25),
259 }
260 };
261 static const struct comedi_lrange range_das1x02_unip = { 4, {
262 UNI_RANGE(10),
263 UNI_RANGE(5),
264 UNI_RANGE(2.5),
265 UNI_RANGE(1.25),
266 }
267 };
268 static const struct comedi_lrange range_das16jr = { 9, {
269 /* also used by 16/330 */
270 BIP_RANGE(10),
271 BIP_RANGE(5),
272 BIP_RANGE(2.5),
273 BIP_RANGE(1.25),
274 BIP_RANGE(0.625),
275 UNI_RANGE(10),
276 UNI_RANGE(5),
277 UNI_RANGE(2.5),
278 UNI_RANGE(1.25),
279 }
280 };
281 static const struct comedi_lrange range_das16jr_16 = { 8, {
282 BIP_RANGE(10),
283 BIP_RANGE(5),
284 BIP_RANGE(2.5),
285 BIP_RANGE(1.25),
286 UNI_RANGE(10),
287 UNI_RANGE(5),
288 UNI_RANGE(2.5),
289 UNI_RANGE(1.25),
290 }
291 };
292
293 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
294 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
295 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
296 enum {
297 das16_pg_none = 0,
298 das16_pg_16jr,
299 das16_pg_16jr_16,
300 das16_pg_1601,
301 das16_pg_1602,
302 };
303 static const int *const das16_gainlists[] = {
304 NULL,
305 das16jr_gainlist,
306 das16jr_16_gainlist,
307 das1600_gainlist,
308 das1600_gainlist,
309 };
310 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
311 &range_unknown,
312 &range_das16jr,
313 &range_das16jr_16,
314 &range_das1x01_unip,
315 &range_das1x02_unip,
316 };
317 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
318 &range_unknown,
319 &range_das16jr,
320 &range_das16jr_16,
321 &range_das1x01_bip,
322 &range_das1x02_bip,
323 };
324
325 struct munge_info {
326 uint8_t byte;
327 unsigned have_byte:1;
328 };
329
330 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
331 struct comedi_insn *insn, unsigned int *data);
332 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
333 struct comedi_insn *insn, unsigned int *data);
334 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
335 struct comedi_insn *insn, unsigned int *data);
336 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
337 struct comedi_insn *insn, unsigned int *data);
338
339 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
340 struct comedi_cmd *cmd);
341 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s);
342 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
343 static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
344 void *array, unsigned int num_bytes, unsigned int start_chan_index);
345
346 static void das16_reset(struct comedi_device *dev);
347 static irqreturn_t das16_dma_interrupt(int irq, void *d);
348 static void das16_timer_interrupt(unsigned long arg);
349 static void das16_interrupt(struct comedi_device *dev);
350
351 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
352 int flags);
353 static int das1600_mode_detect(struct comedi_device *dev);
354 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
355 struct comedi_cmd cmd);
356
357 static void reg_dump(struct comedi_device *dev);
358
359 struct das16_board {
360 const char *name;
361 void *ai;
362 unsigned int ai_nbits;
363 unsigned int ai_speed; /* max conversion speed in nanosec */
364 unsigned int ai_pg;
365 void *ao;
366 unsigned int ao_nbits;
367 void *di;
368 void *do_;
369
370 unsigned int i8255_offset;
371 unsigned int i8254_offset;
372
373 unsigned int size;
374 unsigned int id;
375 };
376
377 static const struct das16_board das16_boards[] = {
378 {
379 .name = "das-16",
380 .ai = das16_ai_rinsn,
381 .ai_nbits = 12,
382 .ai_speed = 15000,
383 .ai_pg = das16_pg_none,
384 .ao = das16_ao_winsn,
385 .ao_nbits = 12,
386 .di = das16_di_rbits,
387 .do_ = das16_do_wbits,
388 .i8255_offset = 0x10,
389 .i8254_offset = 0x0c,
390 .size = 0x14,
391 .id = 0x00,
392 },
393 {
394 .name = "das-16g",
395 .ai = das16_ai_rinsn,
396 .ai_nbits = 12,
397 .ai_speed = 15000,
398 .ai_pg = das16_pg_none,
399 .ao = das16_ao_winsn,
400 .ao_nbits = 12,
401 .di = das16_di_rbits,
402 .do_ = das16_do_wbits,
403 .i8255_offset = 0x10,
404 .i8254_offset = 0x0c,
405 .size = 0x14,
406 .id = 0x00,
407 },
408 {
409 .name = "das-16f",
410 .ai = das16_ai_rinsn,
411 .ai_nbits = 12,
412 .ai_speed = 8500,
413 .ai_pg = das16_pg_none,
414 .ao = das16_ao_winsn,
415 .ao_nbits = 12,
416 .di = das16_di_rbits,
417 .do_ = das16_do_wbits,
418 .i8255_offset = 0x10,
419 .i8254_offset = 0x0c,
420 .size = 0x14,
421 .id = 0x00,
422 },
423 {
424 .name = "cio-das16", /* cio-das16.pdf */
425 .ai = das16_ai_rinsn,
426 .ai_nbits = 12,
427 .ai_speed = 20000,
428 .ai_pg = das16_pg_none,
429 .ao = das16_ao_winsn,
430 .ao_nbits = 12,
431 .di = das16_di_rbits,
432 .do_ = das16_do_wbits,
433 .i8255_offset = 0x10,
434 .i8254_offset = 0x0c,
435 .size = 0x14,
436 .id = 0x80,
437 },
438 {
439 .name = "cio-das16/f", /* das16.pdf */
440 .ai = das16_ai_rinsn,
441 .ai_nbits = 12,
442 .ai_speed = 10000,
443 .ai_pg = das16_pg_none,
444 .ao = das16_ao_winsn,
445 .ao_nbits = 12,
446 .di = das16_di_rbits,
447 .do_ = das16_do_wbits,
448 .i8255_offset = 0x10,
449 .i8254_offset = 0x0c,
450 .size = 0x14,
451 .id = 0x80,
452 },
453 {
454 .name = "cio-das16/jr", /* cio-das16jr.pdf */
455 .ai = das16_ai_rinsn,
456 .ai_nbits = 12,
457 .ai_speed = 7692,
458 .ai_pg = das16_pg_16jr,
459 .ao = NULL,
460 .di = das16_di_rbits,
461 .do_ = das16_do_wbits,
462 .i8255_offset = 0,
463 .i8254_offset = 0x0c,
464 .size = 0x10,
465 .id = 0x00,
466 },
467 {
468 .name = "pc104-das16jr", /* pc104-das16jr_xx.pdf */
469 .ai = das16_ai_rinsn,
470 .ai_nbits = 12,
471 .ai_speed = 3300,
472 .ai_pg = das16_pg_16jr,
473 .ao = NULL,
474 .di = das16_di_rbits,
475 .do_ = das16_do_wbits,
476 .i8255_offset = 0,
477 .i8254_offset = 0x0c,
478 .size = 0x10,
479 .id = 0x00,
480 },
481 {
482 .name = "cio-das16jr/16", /* cio-das16jr_16.pdf */
483 .ai = das16_ai_rinsn,
484 .ai_nbits = 16,
485 .ai_speed = 10000,
486 .ai_pg = das16_pg_16jr_16,
487 .ao = NULL,
488 .di = das16_di_rbits,
489 .do_ = das16_do_wbits,
490 .i8255_offset = 0,
491 .i8254_offset = 0x0c,
492 .size = 0x10,
493 .id = 0x00,
494 },
495 {
496 .name = "pc104-das16jr/16", /* pc104-das16jr_xx.pdf */
497 .ai = das16_ai_rinsn,
498 .ai_nbits = 16,
499 .ai_speed = 10000,
500 .ai_pg = das16_pg_16jr_16,
501 .ao = NULL,
502 .di = das16_di_rbits,
503 .do_ = das16_do_wbits,
504 .i8255_offset = 0,
505 .i8254_offset = 0x0c,
506 .size = 0x10,
507 .id = 0x00,
508 },
509 {
510 .name = "das-1201", /* 4924.pdf (keithley user's manual) */
511 .ai = das16_ai_rinsn,
512 .ai_nbits = 12,
513 .ai_speed = 20000,
514 .ai_pg = das16_pg_none,
515 .ao = NULL,
516 .di = das16_di_rbits,
517 .do_ = das16_do_wbits,
518 .i8255_offset = 0x400,
519 .i8254_offset = 0x0c,
520 .size = 0x408,
521 .id = 0x20,
522 },
523 {
524 .name = "das-1202", /* 4924.pdf (keithley user's manual) */
525 .ai = das16_ai_rinsn,
526 .ai_nbits = 12,
527 .ai_speed = 10000,
528 .ai_pg = das16_pg_none,
529 .ao = NULL,
530 .di = das16_di_rbits,
531 .do_ = das16_do_wbits,
532 .i8255_offset = 0x400,
533 .i8254_offset = 0x0c,
534 .size = 0x408,
535 .id = 0x20,
536 },
537 {
538 .name = "das-1401", /* 4919.pdf and 4922.pdf (keithley user's manual) */
539 .ai = das16_ai_rinsn,
540 .ai_nbits = 12,
541 .ai_speed = 10000,
542 .ai_pg = das16_pg_1601,
543 .ao = NULL,
544 .di = das16_di_rbits,
545 .do_ = das16_do_wbits,
546 .i8255_offset = 0x0,
547 .i8254_offset = 0x0c,
548 .size = 0x408,
549 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
550 },
551 {
552 .name = "das-1402", /* 4919.pdf and 4922.pdf (keithley user's manual) */
553 .ai = das16_ai_rinsn,
554 .ai_nbits = 12,
555 .ai_speed = 10000,
556 .ai_pg = das16_pg_1602,
557 .ao = NULL,
558 .di = das16_di_rbits,
559 .do_ = das16_do_wbits,
560 .i8255_offset = 0x0,
561 .i8254_offset = 0x0c,
562 .size = 0x408,
563 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
564 },
565 {
566 .name = "das-1601", /* 4919.pdf */
567 .ai = das16_ai_rinsn,
568 .ai_nbits = 12,
569 .ai_speed = 10000,
570 .ai_pg = das16_pg_1601,
571 .ao = das16_ao_winsn,
572 .ao_nbits = 12,
573 .di = das16_di_rbits,
574 .do_ = das16_do_wbits,
575 .i8255_offset = 0x400,
576 .i8254_offset = 0x0c,
577 .size = 0x408,
578 .id = 0xc0},
579 {
580 .name = "das-1602", /* 4919.pdf */
581 .ai = das16_ai_rinsn,
582 .ai_nbits = 12,
583 .ai_speed = 10000,
584 .ai_pg = das16_pg_1602,
585 .ao = das16_ao_winsn,
586 .ao_nbits = 12,
587 .di = das16_di_rbits,
588 .do_ = das16_do_wbits,
589 .i8255_offset = 0x400,
590 .i8254_offset = 0x0c,
591 .size = 0x408,
592 .id = 0xc0},
593 {
594 .name = "cio-das1401/12", /* cio-das1400_series.pdf */
595 .ai = das16_ai_rinsn,
596 .ai_nbits = 12,
597 .ai_speed = 6250,
598 .ai_pg = das16_pg_1601,
599 .ao = NULL,
600 .di = das16_di_rbits,
601 .do_ = das16_do_wbits,
602 .i8255_offset = 0,
603 .i8254_offset = 0x0c,
604 .size = 0x408,
605 .id = 0xc0},
606 {
607 .name = "cio-das1402/12", /* cio-das1400_series.pdf */
608 .ai = das16_ai_rinsn,
609 .ai_nbits = 12,
610 .ai_speed = 6250,
611 .ai_pg = das16_pg_1602,
612 .ao = NULL,
613 .di = das16_di_rbits,
614 .do_ = das16_do_wbits,
615 .i8255_offset = 0,
616 .i8254_offset = 0x0c,
617 .size = 0x408,
618 .id = 0xc0},
619 {
620 .name = "cio-das1402/16", /* cio-das1400_series.pdf */
621 .ai = das16_ai_rinsn,
622 .ai_nbits = 16,
623 .ai_speed = 10000,
624 .ai_pg = das16_pg_1602,
625 .ao = NULL,
626 .di = das16_di_rbits,
627 .do_ = das16_do_wbits,
628 .i8255_offset = 0,
629 .i8254_offset = 0x0c,
630 .size = 0x408,
631 .id = 0xc0},
632 {
633 .name = "cio-das1601/12", /* cio-das160x-1x.pdf */
634 .ai = das16_ai_rinsn,
635 .ai_nbits = 12,
636 .ai_speed = 6250,
637 .ai_pg = das16_pg_1601,
638 .ao = das16_ao_winsn,
639 .ao_nbits = 12,
640 .di = das16_di_rbits,
641 .do_ = das16_do_wbits,
642 .i8255_offset = 0x400,
643 .i8254_offset = 0x0c,
644 .size = 0x408,
645 .id = 0xc0},
646 {
647 .name = "cio-das1602/12", /* cio-das160x-1x.pdf */
648 .ai = das16_ai_rinsn,
649 .ai_nbits = 12,
650 .ai_speed = 10000,
651 .ai_pg = das16_pg_1602,
652 .ao = das16_ao_winsn,
653 .ao_nbits = 12,
654 .di = das16_di_rbits,
655 .do_ = das16_do_wbits,
656 .i8255_offset = 0x400,
657 .i8254_offset = 0x0c,
658 .size = 0x408,
659 .id = 0xc0},
660 {
661 .name = "cio-das1602/16", /* cio-das160x-1x.pdf */
662 .ai = das16_ai_rinsn,
663 .ai_nbits = 16,
664 .ai_speed = 10000,
665 .ai_pg = das16_pg_1602,
666 .ao = das16_ao_winsn,
667 .ao_nbits = 12,
668 .di = das16_di_rbits,
669 .do_ = das16_do_wbits,
670 .i8255_offset = 0x400,
671 .i8254_offset = 0x0c,
672 .size = 0x408,
673 .id = 0xc0},
674 {
675 .name = "cio-das16/330", /* ? */
676 .ai = das16_ai_rinsn,
677 .ai_nbits = 12,
678 .ai_speed = 3030,
679 .ai_pg = das16_pg_16jr,
680 .ao = NULL,
681 .di = das16_di_rbits,
682 .do_ = das16_do_wbits,
683 .i8255_offset = 0,
684 .i8254_offset = 0x0c,
685 .size = 0x14,
686 .id = 0xf0},
687 #if 0
688 {
689 .name = "das16/330i", /* ? */
690 },
691 {
692 .name = "das16/jr/ctr5", /* ? */
693 },
694 {
695 .name = "cio-das16/m1/16", /* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
696 },
697 #endif
698 };
699
700 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
701 static int das16_detach(struct comedi_device *dev);
702 static struct comedi_driver driver_das16 = {
703 .driver_name = "das16",
704 .module = THIS_MODULE,
705 .attach = das16_attach,
706 .detach = das16_detach,
707 .board_name = &das16_boards[0].name,
708 .num_names = ARRAY_SIZE(das16_boards),
709 .offset = sizeof(das16_boards[0]),
710 };
711
712 #define DAS16_TIMEOUT 1000
713
714 /* Period for timer interrupt in jiffies. It's a function
715 * to deal with possibility of dynamic HZ patches */
716 static inline int timer_period(void)
717 {
718 return HZ / 20;
719 }
720 struct das16_private_struct {
721 unsigned int ai_unipolar; /* unipolar flag */
722 unsigned int ai_singleended; /* single ended flag */
723 unsigned int clockbase; /* master clock speed in ns */
724 volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
725 volatile unsigned long adc_byte_count; /* number of bytes remaining */
726 unsigned int divisor1; /* divisor dividing master clock to get conversion frequency */
727 unsigned int divisor2; /* divisor dividing master clock to get conversion frequency */
728 unsigned int dma_chan; /* dma channel */
729 uint16_t *dma_buffer[2];
730 dma_addr_t dma_buffer_addr[2];
731 unsigned int current_buffer;
732 volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
733 /* user-defined analog input and output ranges defined from config options */
734 struct comedi_lrange *user_ai_range_table;
735 struct comedi_lrange *user_ao_range_table;
736
737 struct timer_list timer; /* for timed interrupt */
738 volatile short timer_running;
739 volatile short timer_mode; /* true if using timer mode */
740 };
741 #define devpriv ((struct das16_private_struct *)(dev->private))
742 #define thisboard ((struct das16_board *)(dev->board_ptr))
743
744 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
745 struct comedi_cmd *cmd)
746 {
747 int err = 0, tmp;
748 int gain, start_chan, i;
749 int mask;
750
751 /* make sure triggers are valid */
752 tmp = cmd->start_src;
753 cmd->start_src &= TRIG_NOW;
754 if (!cmd->start_src || tmp != cmd->start_src)
755 err++;
756
757 tmp = cmd->scan_begin_src;
758 mask = TRIG_FOLLOW;
759 /* if board supports burst mode */
760 if (thisboard->size > 0x400)
761 mask |= TRIG_TIMER | TRIG_EXT;
762 cmd->scan_begin_src &= mask;
763 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
764 err++;
765
766 tmp = cmd->convert_src;
767 mask = TRIG_TIMER | TRIG_EXT;
768 /* if board supports burst mode */
769 if (thisboard->size > 0x400)
770 mask |= TRIG_NOW;
771 cmd->convert_src &= mask;
772 if (!cmd->convert_src || tmp != cmd->convert_src)
773 err++;
774
775 tmp = cmd->scan_end_src;
776 cmd->scan_end_src &= TRIG_COUNT;
777 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
778 err++;
779
780 tmp = cmd->stop_src;
781 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
782 if (!cmd->stop_src || tmp != cmd->stop_src)
783 err++;
784
785 if (err)
786 return 1;
787
788 /* step 2: make sure trigger sources are unique and mutually compatible */
789 if (cmd->scan_begin_src != TRIG_TIMER &&
790 cmd->scan_begin_src != TRIG_EXT &&
791 cmd->scan_begin_src != TRIG_FOLLOW)
792 err++;
793 if (cmd->convert_src != TRIG_TIMER &&
794 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
795 err++;
796 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
797 err++;
798
799 /* make sure scan_begin_src and convert_src dont conflict */
800 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
801 err++;
802 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
803 err++;
804
805 if (err)
806 return 2;
807
808 /* step 3: make sure arguments are trivially compatible */
809 if (cmd->start_arg != 0) {
810 cmd->start_arg = 0;
811 err++;
812 }
813
814 if (cmd->scan_begin_src == TRIG_FOLLOW) {
815 /* internal trigger */
816 if (cmd->scan_begin_arg != 0) {
817 cmd->scan_begin_arg = 0;
818 err++;
819 }
820 }
821
822 if (cmd->scan_end_arg != cmd->chanlist_len) {
823 cmd->scan_end_arg = cmd->chanlist_len;
824 err++;
825 }
826 /* check against maximum frequency */
827 if (cmd->scan_begin_src == TRIG_TIMER) {
828 if (cmd->scan_begin_arg <
829 thisboard->ai_speed * cmd->chanlist_len) {
830 cmd->scan_begin_arg =
831 thisboard->ai_speed * cmd->chanlist_len;
832 err++;
833 }
834 }
835 if (cmd->convert_src == TRIG_TIMER) {
836 if (cmd->convert_arg < thisboard->ai_speed) {
837 cmd->convert_arg = thisboard->ai_speed;
838 err++;
839 }
840 }
841
842 if (cmd->stop_src == TRIG_NONE) {
843 if (cmd->stop_arg != 0) {
844 cmd->stop_arg = 0;
845 err++;
846 }
847 }
848 if (err)
849 return 3;
850
851 /* step 4: fix up arguments */
852 if (cmd->scan_begin_src == TRIG_TIMER) {
853 unsigned int tmp = cmd->scan_begin_arg;
854 /* set divisors, correct timing arguments */
855 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
856 &(devpriv->divisor1), &(devpriv->divisor2),
857 &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
858 err += (tmp != cmd->scan_begin_arg);
859 }
860 if (cmd->convert_src == TRIG_TIMER) {
861 unsigned int tmp = cmd->convert_arg;
862 /* set divisors, correct timing arguments */
863 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
864 &(devpriv->divisor1), &(devpriv->divisor2),
865 &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
866 err += (tmp != cmd->convert_arg);
867 }
868 if (err)
869 return 4;
870
871 /* check channel/gain list against card's limitations */
872 if (cmd->chanlist) {
873 gain = CR_RANGE(cmd->chanlist[0]);
874 start_chan = CR_CHAN(cmd->chanlist[0]);
875 for (i = 1; i < cmd->chanlist_len; i++) {
876 if (CR_CHAN(cmd->chanlist[i]) !=
877 (start_chan + i) % s->n_chan) {
878 comedi_error(dev,
879 "entries in chanlist must be consecutive channels, counting upwards\n");
880 err++;
881 }
882 if (CR_RANGE(cmd->chanlist[i]) != gain) {
883 comedi_error(dev,
884 "entries in chanlist must all have the same gain\n");
885 err++;
886 }
887 }
888 }
889 if (err)
890 return 5;
891
892 return 0;
893 }
894
895 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
896 {
897 struct comedi_async *async = s->async;
898 struct comedi_cmd *cmd = &async->cmd;
899 unsigned int byte;
900 unsigned long flags;
901 int range;
902
903 if (devpriv->dma_chan == 0 || (dev->irq == 0
904 && devpriv->timer_mode == 0)) {
905 comedi_error(dev,
906 "irq (or use of 'timer mode') dma required to execute comedi_cmd");
907 return -1;
908 }
909 if (cmd->flags & TRIG_RT) {
910 comedi_error(dev,
911 "isa dma transfers cannot be performed with TRIG_RT, aborting");
912 return -1;
913 }
914
915 devpriv->adc_byte_count =
916 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
917
918 /* disable conversions for das1600 mode */
919 if (thisboard->size > 0x400) {
920 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
921 }
922 /* set scan limits */
923 byte = CR_CHAN(cmd->chanlist[0]);
924 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
925 outb(byte, dev->iobase + DAS16_MUX);
926
927 /* set gain (this is also burst rate register but according to
928 * computer boards manual, burst rate does nothing, even on keithley cards) */
929 if (thisboard->ai_pg != das16_pg_none) {
930 range = CR_RANGE(cmd->chanlist[0]);
931 outb((das16_gainlists[thisboard->ai_pg])[range],
932 dev->iobase + DAS16_GAIN);
933 }
934
935 /* set counter mode and counts */
936 cmd->convert_arg =
937 das16_set_pacer(dev, cmd->convert_arg,
938 cmd->flags & TRIG_ROUND_MASK);
939 DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
940
941 /* enable counters */
942 byte = 0;
943 /* Enable burst mode if appropriate. */
944 if (thisboard->size > 0x400) {
945 if (cmd->convert_src == TRIG_NOW) {
946 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
947 /* set burst length */
948 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
949 } else {
950 outb(0, dev->iobase + DAS1600_BURST);
951 }
952 }
953 outb(byte, dev->iobase + DAS16_PACER);
954
955 /* set up dma transfer */
956 flags = claim_dma_lock();
957 disable_dma(devpriv->dma_chan);
958 /* clear flip-flop to make sure 2-byte registers for
959 * count and address get set correctly */
960 clear_dma_ff(devpriv->dma_chan);
961 devpriv->current_buffer = 0;
962 set_dma_addr(devpriv->dma_chan,
963 devpriv->dma_buffer_addr[devpriv->current_buffer]);
964 /* set appropriate size of transfer */
965 devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd);
966 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
967 enable_dma(devpriv->dma_chan);
968 release_dma_lock(flags);
969
970 /* set up interrupt */
971 if (devpriv->timer_mode) {
972 devpriv->timer_running = 1;
973 devpriv->timer.expires = jiffies + timer_period();
974 add_timer(&devpriv->timer);
975 devpriv->control_state &= ~DAS16_INTE;
976 } else {
977 /* clear interrupt bit */
978 outb(0x00, dev->iobase + DAS16_STATUS);
979 /* enable interrupts */
980 devpriv->control_state |= DAS16_INTE;
981 }
982 devpriv->control_state |= DMA_ENABLE;
983 devpriv->control_state &= ~PACING_MASK;
984 if (cmd->convert_src == TRIG_EXT)
985 devpriv->control_state |= EXT_PACER;
986 else
987 devpriv->control_state |= INT_PACER;
988 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
989
990 /* Enable conversions if using das1600 mode */
991 if (thisboard->size > 0x400) {
992 outb(0, dev->iobase + DAS1600_CONV);
993 }
994
995 return 0;
996 }
997
998 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
999 {
1000 unsigned long flags;
1001
1002 spin_lock_irqsave(&dev->spinlock, flags);
1003 /* disable interrupts, dma and pacer clocked conversions */
1004 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
1005 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1006 if (devpriv->dma_chan)
1007 disable_dma(devpriv->dma_chan);
1008
1009 /* disable SW timer */
1010 if (devpriv->timer_mode && devpriv->timer_running) {
1011 devpriv->timer_running = 0;
1012 del_timer(&devpriv->timer);
1013 }
1014
1015 /* disable burst mode */
1016 if (thisboard->size > 0x400) {
1017 outb(0, dev->iobase + DAS1600_BURST);
1018 }
1019
1020 spin_unlock_irqrestore(&dev->spinlock, flags);
1021
1022 return 0;
1023 }
1024
1025 static void das16_reset(struct comedi_device *dev)
1026 {
1027 outb(0, dev->iobase + DAS16_STATUS);
1028 outb(0, dev->iobase + DAS16_CONTROL);
1029 outb(0, dev->iobase + DAS16_PACER);
1030 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
1031 }
1032
1033 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1034 struct comedi_insn *insn, unsigned int *data)
1035 {
1036 int i, n;
1037 int range;
1038 int chan;
1039 int msb, lsb;
1040
1041 /* disable interrupts and pacing */
1042 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
1043 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1044
1045 /* set multiplexer */
1046 chan = CR_CHAN(insn->chanspec);
1047 chan |= CR_CHAN(insn->chanspec) << 4;
1048 outb(chan, dev->iobase + DAS16_MUX);
1049
1050 /* set gain */
1051 if (thisboard->ai_pg != das16_pg_none) {
1052 range = CR_RANGE(insn->chanspec);
1053 outb((das16_gainlists[thisboard->ai_pg])[range],
1054 dev->iobase + DAS16_GAIN);
1055 }
1056
1057 for (n = 0; n < insn->n; n++) {
1058 /* trigger conversion */
1059 outb_p(0, dev->iobase + DAS16_TRIG);
1060
1061 for (i = 0; i < DAS16_TIMEOUT; i++) {
1062 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
1063 break;
1064 }
1065 if (i == DAS16_TIMEOUT) {
1066 printk("das16: timeout\n");
1067 return -ETIME;
1068 }
1069 msb = inb(dev->iobase + DAS16_AI_MSB);
1070 lsb = inb(dev->iobase + DAS16_AI_LSB);
1071 if (thisboard->ai_nbits == 12) {
1072 data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
1073 } else {
1074 data[n] = lsb | (msb << 8);
1075 }
1076 }
1077
1078 return n;
1079 }
1080
1081 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
1082 struct comedi_insn *insn, unsigned int *data)
1083 {
1084 unsigned int bits;
1085
1086 bits = inb(dev->iobase + DAS16_DIO) & 0xf;
1087 data[1] = bits;
1088 data[0] = 0;
1089
1090 return 2;
1091 }
1092
1093 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
1094 struct comedi_insn *insn, unsigned int *data)
1095 {
1096 unsigned int wbits;
1097
1098 /* only set bits that have been masked */
1099 data[0] &= 0xf;
1100 wbits = s->state;
1101 /* zero bits that have been masked */
1102 wbits &= ~data[0];
1103 /* set masked bits */
1104 wbits |= data[0] & data[1];
1105 s->state = wbits;
1106 data[1] = wbits;
1107
1108 outb(s->state, dev->iobase + DAS16_DIO);
1109
1110 return 2;
1111 }
1112
1113 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
1114 struct comedi_insn *insn, unsigned int *data)
1115 {
1116 int i;
1117 int lsb, msb;
1118 int chan;
1119
1120 chan = CR_CHAN(insn->chanspec);
1121
1122 for (i = 0; i < insn->n; i++) {
1123 if (thisboard->ao_nbits == 12) {
1124 lsb = (data[i] << 4) & 0xff;
1125 msb = (data[i] >> 4) & 0xff;
1126 } else {
1127 lsb = data[i] & 0xff;
1128 msb = (data[i] >> 8) & 0xff;
1129 }
1130 outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
1131 outb(msb, dev->iobase + DAS16_AO_MSB(chan));
1132 }
1133
1134 return i;
1135 }
1136
1137 static irqreturn_t das16_dma_interrupt(int irq, void *d)
1138 {
1139 int status;
1140 struct comedi_device *dev = d;
1141
1142 status = inb(dev->iobase + DAS16_STATUS);
1143
1144 if ((status & DAS16_INT) == 0) {
1145 DEBUG_PRINT("spurious interrupt\n");
1146 return IRQ_NONE;
1147 }
1148
1149 /* clear interrupt */
1150 outb(0x00, dev->iobase + DAS16_STATUS);
1151 das16_interrupt(dev);
1152 return IRQ_HANDLED;
1153 }
1154
1155 static void das16_timer_interrupt(unsigned long arg)
1156 {
1157 struct comedi_device *dev = (struct comedi_device *) arg;
1158
1159 das16_interrupt(dev);
1160
1161 if (devpriv->timer_running)
1162 mod_timer(&devpriv->timer, jiffies + timer_period());
1163 }
1164
1165 /* the pc104-das16jr (at least) has problems if the dma
1166 transfer is interrupted in the middle of transferring
1167 a 16 bit sample, so this function takes care to get
1168 an even transfer count after disabling dma
1169 channel.
1170 */
1171 static int disable_dma_on_even(struct comedi_device *dev)
1172 {
1173 int residue;
1174 int i;
1175 static const int disable_limit = 100;
1176 static const int enable_timeout = 100;
1177 disable_dma(devpriv->dma_chan);
1178 residue = get_dma_residue(devpriv->dma_chan);
1179 for (i = 0; i < disable_limit && (residue % 2); ++i) {
1180 int j;
1181 enable_dma(devpriv->dma_chan);
1182 for (j = 0; j < enable_timeout; ++j) {
1183 int new_residue;
1184 udelay(2);
1185 new_residue = get_dma_residue(devpriv->dma_chan);
1186 if (new_residue != residue)
1187 break;
1188 }
1189 disable_dma(devpriv->dma_chan);
1190 residue = get_dma_residue(devpriv->dma_chan);
1191 }
1192 if (i == disable_limit) {
1193 comedi_error(dev,
1194 "failed to get an even dma transfer, could be trouble.");
1195 }
1196 return residue;
1197 }
1198
1199 static void das16_interrupt(struct comedi_device *dev)
1200 {
1201 unsigned long dma_flags, spin_flags;
1202 struct comedi_subdevice *s = dev->read_subdev;
1203 struct comedi_async *async;
1204 struct comedi_cmd *cmd;
1205 int num_bytes, residue;
1206 int buffer_index;
1207
1208 if (dev->attached == 0) {
1209 comedi_error(dev, "premature interrupt");
1210 return;
1211 }
1212 /* initialize async here to make sure it is not NULL */
1213 async = s->async;
1214 cmd = &async->cmd;
1215
1216 if (devpriv->dma_chan == 0) {
1217 comedi_error(dev, "interrupt with no dma channel?");
1218 return;
1219 }
1220
1221 spin_lock_irqsave(&dev->spinlock, spin_flags);
1222 if ((devpriv->control_state & DMA_ENABLE) == 0) {
1223 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
1224 DEBUG_PRINT("interrupt while dma disabled?\n");
1225 return;
1226 }
1227
1228 dma_flags = claim_dma_lock();
1229 clear_dma_ff(devpriv->dma_chan);
1230 residue = disable_dma_on_even(dev);
1231
1232 /* figure out how many points to read */
1233 if (residue > devpriv->dma_transfer_size) {
1234 comedi_error(dev, "residue > transfer size!\n");
1235 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1236 num_bytes = 0;
1237 } else
1238 num_bytes = devpriv->dma_transfer_size - residue;
1239
1240 if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) {
1241 num_bytes = devpriv->adc_byte_count;
1242 async->events |= COMEDI_CB_EOA;
1243 }
1244
1245 buffer_index = devpriv->current_buffer;
1246 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
1247 devpriv->adc_byte_count -= num_bytes;
1248
1249 /* figure out how many bytes for next transfer */
1250 if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
1251 devpriv->dma_transfer_size > devpriv->adc_byte_count)
1252 devpriv->dma_transfer_size = devpriv->adc_byte_count;
1253
1254 /* re-enable dma */
1255 if ((async->events & COMEDI_CB_EOA) == 0) {
1256 set_dma_addr(devpriv->dma_chan,
1257 devpriv->dma_buffer_addr[devpriv->current_buffer]);
1258 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
1259 enable_dma(devpriv->dma_chan);
1260 /* reenable conversions for das1600 mode, (stupid hardware) */
1261 if (thisboard->size > 0x400 && devpriv->timer_mode == 0) {
1262 outb(0x00, dev->iobase + DAS1600_CONV);
1263 }
1264 }
1265 release_dma_lock(dma_flags);
1266
1267 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
1268
1269 cfc_write_array_to_buffer(s,
1270 devpriv->dma_buffer[buffer_index], num_bytes);
1271
1272 cfc_handle_events(dev, s);
1273 }
1274
1275 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
1276 int rounding_flags)
1277 {
1278 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
1279 &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK);
1280
1281 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1282 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
1283 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
1284
1285 return ns;
1286 }
1287
1288 static void reg_dump(struct comedi_device *dev)
1289 {
1290 DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
1291 DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
1292 DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
1293 DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
1294 DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
1295 DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
1296 DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
1297 DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
1298 inb(dev->iobase + DAS16_CNTR_CONTROL));
1299 DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
1300 DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
1301 DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
1302 DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
1303 inb(dev->iobase + DAS1600_STATUS_B));
1304 }
1305
1306 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
1307 {
1308 int status;
1309 int diobits;
1310
1311 /* status is available on all boards */
1312
1313 status = inb(dev->iobase + DAS16_STATUS);
1314
1315 if ((status & UNIPOLAR)) {
1316 devpriv->ai_unipolar = 1;
1317 } else {
1318 devpriv->ai_unipolar = 0;
1319 }
1320
1321 if ((status & DAS16_MUXBIT)) {
1322 devpriv->ai_singleended = 1;
1323 } else {
1324 devpriv->ai_singleended = 0;
1325 }
1326
1327 /* diobits indicates boards */
1328
1329 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
1330
1331 printk(" id bits are 0x%02x\n", diobits);
1332 if (thisboard->id != diobits) {
1333 printk(" requested board's id bits are 0x%x (ignore)\n",
1334 thisboard->id);
1335 }
1336
1337 return 0;
1338 }
1339
1340 static int das1600_mode_detect(struct comedi_device *dev)
1341 {
1342 int status = 0;
1343
1344 status = inb(dev->iobase + DAS1600_STATUS_B);
1345
1346 if (status & DAS1600_CLK_10MHZ) {
1347 devpriv->clockbase = 100;
1348 printk(" 10MHz pacer clock\n");
1349 } else {
1350 devpriv->clockbase = 1000;
1351 printk(" 1MHz pacer clock\n");
1352 }
1353
1354 reg_dump(dev);
1355
1356 return 0;
1357 }
1358
1359 /*
1360 *
1361 * Options list:
1362 * 0 I/O base
1363 * 1 IRQ
1364 * 2 DMA
1365 * 3 Clock speed (in MHz)
1366 */
1367
1368 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1369 {
1370 struct comedi_subdevice *s;
1371 int ret;
1372 unsigned int irq;
1373 unsigned long iobase;
1374 unsigned int dma_chan;
1375 int timer_mode;
1376 unsigned long flags;
1377 struct comedi_krange *user_ai_range, *user_ao_range;
1378
1379 iobase = it->options[0];
1380 #if 0
1381 irq = it->options[1];
1382 timer_mode = it->options[8];
1383 #endif
1384 /* always use time_mode since using irq can drop samples while
1385 * waiting for dma done interrupt (due to hardware limitations) */
1386 irq = 0;
1387 timer_mode = 1;
1388 if (timer_mode)
1389 irq = 0;
1390
1391 printk("comedi%d: das16:", dev->minor);
1392
1393 /* check that clock setting is valid */
1394 if (it->options[3]) {
1395 if (it->options[3] != 0 &&
1396 it->options[3] != 1 && it->options[3] != 10) {
1397 printk("\n Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1398 return -EINVAL;
1399 }
1400 }
1401
1402 ret = alloc_private(dev, sizeof(struct das16_private_struct));
1403 if (ret < 0)
1404 return ret;
1405
1406 if (thisboard->size < 0x400) {
1407 printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size);
1408 if (!request_region(iobase, thisboard->size, "das16")) {
1409 printk(" I/O port conflict\n");
1410 return -EIO;
1411 }
1412 } else {
1413 printk(" 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
1414 iobase, iobase + 0x0f,
1415 iobase + 0x400,
1416 iobase + 0x400 + (thisboard->size & 0x3ff));
1417 if (!request_region(iobase, 0x10, "das16")) {
1418 printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
1419 iobase, iobase + 0x0f);
1420 return -EIO;
1421 }
1422 if (!request_region(iobase + 0x400, thisboard->size & 0x3ff,
1423 "das16")) {
1424 release_region(iobase, 0x10);
1425 printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
1426 iobase + 0x400,
1427 iobase + 0x400 + (thisboard->size & 0x3ff));
1428 return -EIO;
1429 }
1430 }
1431
1432 dev->iobase = iobase;
1433
1434 /* probe id bits to make sure they are consistent */
1435 if (das16_probe(dev, it)) {
1436 printk(" id bits do not match selected board, aborting\n");
1437 return -EINVAL;
1438 }
1439 dev->board_name = thisboard->name;
1440
1441 /* get master clock speed */
1442 if (thisboard->size < 0x400) {
1443 if (it->options[3])
1444 devpriv->clockbase = 1000 / it->options[3];
1445 else
1446 devpriv->clockbase = 1000; /* 1 MHz default */
1447 } else {
1448 das1600_mode_detect(dev);
1449 }
1450
1451 /* now for the irq */
1452 if (irq > 1 && irq < 8) {
1453 ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev);
1454
1455 if (ret < 0)
1456 return ret;
1457 dev->irq = irq;
1458 printk(" ( irq = %u )", irq);
1459 } else if (irq == 0) {
1460 printk(" ( no irq )");
1461 } else {
1462 printk(" invalid irq\n");
1463 return -EINVAL;
1464 }
1465
1466 /* initialize dma */
1467 dma_chan = it->options[2];
1468 if (dma_chan == 1 || dma_chan == 3) {
1469 /* allocate dma buffers */
1470 int i;
1471 for (i = 0; i < 2; i++) {
1472 devpriv->dma_buffer[i] = pci_alloc_consistent(NULL,
1473 DAS16_DMA_SIZE, &devpriv->dma_buffer_addr[i]);
1474 if (devpriv->dma_buffer[i] == NULL)
1475 return -ENOMEM;
1476 }
1477 if (request_dma(dma_chan, "das16")) {
1478 printk(" failed to allocate dma channel %i\n",
1479 dma_chan);
1480 return -EINVAL;
1481 }
1482 devpriv->dma_chan = dma_chan;
1483 flags = claim_dma_lock();
1484 disable_dma(devpriv->dma_chan);
1485 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1486 release_dma_lock(flags);
1487 printk(" ( dma = %u)\n", dma_chan);
1488 } else if (dma_chan == 0) {
1489 printk(" ( no dma )\n");
1490 } else {
1491 printk(" invalid dma channel\n");
1492 return -EINVAL;
1493 }
1494
1495 /* get any user-defined input range */
1496 if (thisboard->ai_pg == das16_pg_none &&
1497 (it->options[4] || it->options[5])) {
1498 /* allocate single-range range table */
1499 devpriv->user_ai_range_table =
1500 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
1501 GFP_KERNEL);
1502 /* initialize ai range */
1503 devpriv->user_ai_range_table->length = 1;
1504 user_ai_range = devpriv->user_ai_range_table->range;
1505 user_ai_range->min = it->options[4];
1506 user_ai_range->max = it->options[5];
1507 user_ai_range->flags = UNIT_volt;
1508 }
1509 /* get any user-defined output range */
1510 if (it->options[6] || it->options[7]) {
1511 /* allocate single-range range table */
1512 devpriv->user_ao_range_table =
1513 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
1514 GFP_KERNEL);
1515 /* initialize ao range */
1516 devpriv->user_ao_range_table->length = 1;
1517 user_ao_range = devpriv->user_ao_range_table->range;
1518 user_ao_range->min = it->options[6];
1519 user_ao_range->max = it->options[7];
1520 user_ao_range->flags = UNIT_volt;
1521 }
1522
1523 if (timer_mode) {
1524 init_timer(&(devpriv->timer));
1525 devpriv->timer.function = das16_timer_interrupt;
1526 devpriv->timer.data = (unsigned long)dev;
1527 }
1528 devpriv->timer_mode = timer_mode ? 1 : 0;
1529
1530 ret = alloc_subdevices(dev, 5);
1531 if (ret < 0)
1532 return ret;
1533
1534 s = dev->subdevices + 0;
1535 dev->read_subdev = s;
1536 /* ai */
1537 if (thisboard->ai) {
1538 s->type = COMEDI_SUBD_AI;
1539 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1540 if (devpriv->ai_singleended) {
1541 s->n_chan = 16;
1542 s->len_chanlist = 16;
1543 s->subdev_flags |= SDF_GROUND;
1544 } else {
1545 s->n_chan = 8;
1546 s->len_chanlist = 8;
1547 s->subdev_flags |= SDF_DIFF;
1548 }
1549 s->maxdata = (1 << thisboard->ai_nbits) - 1;
1550 if (devpriv->user_ai_range_table) { /* user defined ai range */
1551 s->range_table = devpriv->user_ai_range_table;
1552 } else if (devpriv->ai_unipolar) {
1553 s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];
1554 } else {
1555 s->range_table = das16_ai_bip_lranges[thisboard->ai_pg];
1556 }
1557 s->insn_read = thisboard->ai;
1558 s->do_cmdtest = das16_cmd_test;
1559 s->do_cmd = das16_cmd_exec;
1560 s->cancel = das16_cancel;
1561 s->munge = das16_ai_munge;
1562 } else {
1563 s->type = COMEDI_SUBD_UNUSED;
1564 }
1565
1566 s = dev->subdevices + 1;
1567 /* ao */
1568 if (thisboard->ao) {
1569 s->type = COMEDI_SUBD_AO;
1570 s->subdev_flags = SDF_WRITABLE;
1571 s->n_chan = 2;
1572 s->maxdata = (1 << thisboard->ao_nbits) - 1;
1573 if (devpriv->user_ao_range_table) { /* user defined ao range */
1574 s->range_table = devpriv->user_ao_range_table;
1575 } else {
1576 s->range_table = &range_unknown;
1577 }
1578 s->insn_write = thisboard->ao;
1579 } else {
1580 s->type = COMEDI_SUBD_UNUSED;
1581 }
1582
1583 s = dev->subdevices + 2;
1584 /* di */
1585 if (thisboard->di) {
1586 s->type = COMEDI_SUBD_DI;
1587 s->subdev_flags = SDF_READABLE;
1588 s->n_chan = 4;
1589 s->maxdata = 1;
1590 s->range_table = &range_digital;
1591 s->insn_bits = thisboard->di;
1592 } else {
1593 s->type = COMEDI_SUBD_UNUSED;
1594 }
1595
1596 s = dev->subdevices + 3;
1597 /* do */
1598 if (thisboard->do_) {
1599 s->type = COMEDI_SUBD_DO;
1600 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1601 s->n_chan = 4;
1602 s->maxdata = 1;
1603 s->range_table = &range_digital;
1604 s->insn_bits = thisboard->do_;
1605 /* initialize digital output lines */
1606 outb(s->state, dev->iobase + DAS16_DIO);
1607 } else {
1608 s->type = COMEDI_SUBD_UNUSED;
1609 }
1610
1611 s = dev->subdevices + 4;
1612 /* 8255 */
1613 if (thisboard->i8255_offset != 0) {
1614 subdev_8255_init(dev, s, NULL, (dev->iobase +
1615 thisboard->i8255_offset));
1616 } else {
1617 s->type = COMEDI_SUBD_UNUSED;
1618 }
1619
1620 das16_reset(dev);
1621 /* set the interrupt level */
1622 devpriv->control_state = DAS16_IRQ(dev->irq);
1623 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1624
1625 /* turn on das1600 mode if available */
1626 if (thisboard->size > 0x400) {
1627 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1628 outb(0, dev->iobase + DAS1600_CONV);
1629 outb(0, dev->iobase + DAS1600_BURST);
1630 }
1631
1632 return 0;
1633 }
1634
1635 static int das16_detach(struct comedi_device *dev)
1636 {
1637 printk("comedi%d: das16: remove\n", dev->minor);
1638
1639 das16_reset(dev);
1640
1641 if (dev->subdevices)
1642 subdev_8255_cleanup(dev, dev->subdevices + 4);
1643
1644 if (devpriv) {
1645 int i;
1646 for (i = 0; i < 2; i++) {
1647 if (devpriv->dma_buffer[i])
1648 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1649 devpriv->dma_buffer[i],
1650 devpriv->dma_buffer_addr[i]);
1651 }
1652 if (devpriv->dma_chan)
1653 free_dma(devpriv->dma_chan);
1654 if (devpriv->user_ai_range_table)
1655 kfree(devpriv->user_ai_range_table);
1656 if (devpriv->user_ao_range_table)
1657 kfree(devpriv->user_ao_range_table);
1658 }
1659
1660 if (dev->irq)
1661 free_irq(dev->irq, dev);
1662
1663 if (dev->iobase) {
1664 if (thisboard->size < 0x400) {
1665 release_region(dev->iobase, thisboard->size);
1666 } else {
1667 release_region(dev->iobase, 0x10);
1668 release_region(dev->iobase + 0x400,
1669 thisboard->size & 0x3ff);
1670 }
1671 }
1672
1673 return 0;
1674 }
1675
1676 COMEDI_INITCLEANUP(driver_das16);
1677
1678 /* utility function that suggests a dma transfer size in bytes */
1679 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
1680 struct comedi_cmd cmd)
1681 {
1682 unsigned int size;
1683 unsigned int freq;
1684
1685 /* if we are using timer interrupt, we don't care how long it
1686 * will take to complete transfer since it will be interrupted
1687 * by timer interrupt */
1688 if (devpriv->timer_mode)
1689 return DAS16_DMA_SIZE;
1690
1691 /* otherwise, we are relying on dma terminal count interrupt,
1692 * so pick a reasonable size */
1693 if (cmd.convert_src == TRIG_TIMER)
1694 freq = 1000000000 / cmd.convert_arg;
1695 else if (cmd.scan_begin_src == TRIG_TIMER)
1696 freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
1697 /* return some default value */
1698 else
1699 freq = 0xffffffff;
1700
1701 if (cmd.flags & TRIG_WAKE_EOS) {
1702 size = sample_size * cmd.chanlist_len;
1703 } else {
1704 /* make buffer fill in no more than 1/3 second */
1705 size = (freq / 3) * sample_size;
1706 }
1707
1708 /* set a minimum and maximum size allowed */
1709 if (size > DAS16_DMA_SIZE)
1710 size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
1711 else if (size < sample_size)
1712 size = sample_size;
1713
1714 if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
1715 size = devpriv->adc_byte_count;
1716
1717 return size;
1718 }
1719
1720 static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
1721 void *array, unsigned int num_bytes, unsigned int start_chan_index)
1722 {
1723 unsigned int i, num_samples = num_bytes / sizeof(short);
1724 short *data = array;
1725
1726 for (i = 0; i < num_samples; i++) {
1727 data[i] = le16_to_cpu(data[i]);
1728 if (thisboard->ai_nbits == 12) {
1729 data[i] = (data[i] >> 4) & 0xfff;
1730 }
1731 }
1732 }
1733
|
This page was automatically generated by the
LXR engine.
|