Staging: comedi: remove comedi-specific wrappers
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / comedi / drivers / das16.c
blobc0fbb85167306688268bbc44a44196328772f750
1 /*
2 comedi/drivers/das16.c
3 DAS16 driver
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>
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.
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.
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.
24 ************************************************************************
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
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.
64 Passing a zero for an option is the same as leaving it unspecified.
69 Testing and debugging help provided by Daniel Koch.
71 Keithley Manuals:
72 2309.PDF (das16)
73 4919.PDF (das1400, 1600)
74 4922.PDF (das-1400)
75 4923.PDF (das1200, 1400, 1600)
77 Computer boards manuals also available from their website www.measurementcomputing.com
81 #include <linux/pci.h>
82 #include <asm/dma.h>
83 #include "../comedidev.h"
85 #include "8253.h"
86 #include "8255.h"
87 #include "comedi_fc.h"
89 #undef DEBUG
90 /* #define DEBUG */
92 #ifdef DEBUG
93 #define DEBUG_PRINT(format, args...) printk("das16: " format, ## args)
94 #else
95 #define DEBUG_PRINT(format, args...)
96 #endif
98 #define DAS16_SIZE 20 /* number of ioports */
99 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
102 cio-das16.pdf
104 "das16"
105 "das16/f"
107 0 a/d bits 0-3 start 12 bit
108 1 a/d bits 4-11 unused
109 2 mux read mux set
110 3 di 4 bit do 4 bit
111 4 unused ao0_lsb
112 5 unused ao0_msb
113 6 unused ao1_lsb
114 7 unused ao1_msb
115 8 status eoc uni/bip interrupt reset
116 9 dma, int, trig ctrl set dma, int
117 a pacer control unused
118 b reserved reserved
119 cdef 8254
120 0123 8255
125 cio-das16jr.pdf
127 "das16jr"
129 0 a/d bits 0-3 start 12 bit
130 1 a/d bits 4-11 unused
131 2 mux read mux set
132 3 di 4 bit do 4 bit
133 4567 unused unused
134 8 status eoc uni/bip interrupt reset
135 9 dma, int, trig ctrl set dma, int
136 a pacer control unused
137 b gain status gain control
138 cdef 8254
143 cio-das16jr_16.pdf
145 "das16jr_16"
147 0 a/d bits 0-7 start 16 bit
148 1 a/d bits 8-15 unused
149 2 mux read mux set
150 3 di 4 bit do 4 bit
151 4567 unused unused
152 8 status eoc uni/bip interrupt reset
153 9 dma, int, trig ctrl set dma, int
154 a pacer control unused
155 b gain status gain control
156 cdef 8254
160 cio-das160x-1x.pdf
162 "das1601/12"
163 "das1602/12"
164 "das1602/16"
166 0 a/d bits 0-3 start 12 bit
167 1 a/d bits 4-11 unused
168 2 mux read mux set
169 3 di 4 bit do 4 bit
170 4 unused ao0_lsb
171 5 unused ao0_msb
172 6 unused ao1_lsb
173 7 unused ao1_msb
174 8 status eoc uni/bip interrupt reset
175 9 dma, int, trig ctrl set dma, int
176 a pacer control unused
177 b gain status gain control
178 cdef 8254
179 400 8255
180 404 unused conversion enable
181 405 unused burst enable
182 406 unused das1600 enable
183 407 status
187 static const int sample_size = 2; /* size in bytes of a sample from board */
189 #define DAS16_TRIG 0
190 #define DAS16_AI_LSB 0
191 #define DAS16_AI_MSB 1
192 #define DAS16_MUX 2
193 #define DAS16_DIO 3
194 #define DAS16_AO_LSB(x) ((x)?6:4)
195 #define DAS16_AO_MSB(x) ((x)?7:5)
196 #define DAS16_STATUS 8
197 #define BUSY (1<<7)
198 #define UNIPOLAR (1<<6)
199 #define DAS16_MUXBIT (1<<5)
200 #define DAS16_INT (1<<4)
201 #define DAS16_CONTROL 9
202 #define DAS16_INTE (1<<7)
203 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
204 #define DMA_ENABLE (1<<2)
205 #define PACING_MASK 0x3
206 #define INT_PACER 0x03
207 #define EXT_PACER 0x02
208 #define DAS16_SOFT 0x00
209 #define DAS16_PACER 0x0A
210 #define DAS16_CTR0 (1<<1)
211 #define DAS16_TRIG0 (1<<0)
212 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
213 #define DAS16_GAIN 0x0B
214 #define DAS16_CNTR0_DATA 0x0C
215 #define DAS16_CNTR1_DATA 0x0D
216 #define DAS16_CNTR2_DATA 0x0E
217 #define DAS16_CNTR_CONTROL 0x0F
218 #define DAS16_TERM_CNT 0x00
219 #define DAS16_ONE_SHOT 0x02
220 #define DAS16_RATE_GEN 0x04
221 #define DAS16_CNTR_LSB_MSB 0x30
222 #define DAS16_CNTR0 0x00
223 #define DAS16_CNTR1 0x40
224 #define DAS16_CNTR2 0x80
226 #define DAS1600_CONV 0x404
227 #define DAS1600_CONV_DISABLE 0x40
228 #define DAS1600_BURST 0x405
229 #define DAS1600_BURST_VAL 0x40
230 #define DAS1600_ENABLE 0x406
231 #define DAS1600_ENABLE_VAL 0x40
232 #define DAS1600_STATUS_B 0x407
233 #define DAS1600_BME 0x40
234 #define DAS1600_ME 0x20
235 #define DAS1600_CD 0x10
236 #define DAS1600_WS 0x02
237 #define DAS1600_CLK_10MHZ 0x01
239 static const struct comedi_lrange range_das1x01_bip = { 4, {
240 BIP_RANGE(10),
241 BIP_RANGE(1),
242 BIP_RANGE(0.1),
243 BIP_RANGE(0.01),
246 static const struct comedi_lrange range_das1x01_unip = { 4, {
247 UNI_RANGE(10),
248 UNI_RANGE(1),
249 UNI_RANGE(0.1),
250 UNI_RANGE(0.01),
253 static const struct comedi_lrange range_das1x02_bip = { 4, {
254 BIP_RANGE(10),
255 BIP_RANGE(5),
256 BIP_RANGE(2.5),
257 BIP_RANGE(1.25),
260 static const struct comedi_lrange range_das1x02_unip = { 4, {
261 UNI_RANGE(10),
262 UNI_RANGE(5),
263 UNI_RANGE(2.5),
264 UNI_RANGE(1.25),
267 static const struct comedi_lrange range_das16jr = { 9, {
268 /* also used by 16/330 */
269 BIP_RANGE(10),
270 BIP_RANGE(5),
271 BIP_RANGE(2.5),
272 BIP_RANGE(1.25),
273 BIP_RANGE(0.625),
274 UNI_RANGE(10),
275 UNI_RANGE(5),
276 UNI_RANGE(2.5),
277 UNI_RANGE(1.25),
280 static const struct comedi_lrange range_das16jr_16 = { 8, {
281 BIP_RANGE(10),
282 BIP_RANGE(5),
283 BIP_RANGE(2.5),
284 BIP_RANGE(1.25),
285 UNI_RANGE(10),
286 UNI_RANGE(5),
287 UNI_RANGE(2.5),
288 UNI_RANGE(1.25),
292 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
293 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
294 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
295 enum {
296 das16_pg_none = 0,
297 das16_pg_16jr,
298 das16_pg_16jr_16,
299 das16_pg_1601,
300 das16_pg_1602,
302 static const int *const das16_gainlists[] = {
303 NULL,
304 das16jr_gainlist,
305 das16jr_16_gainlist,
306 das1600_gainlist,
307 das1600_gainlist,
309 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
310 &range_unknown,
311 &range_das16jr,
312 &range_das16jr_16,
313 &range_das1x01_unip,
314 &range_das1x02_unip,
316 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
317 &range_unknown,
318 &range_das16jr,
319 &range_das16jr_16,
320 &range_das1x01_bip,
321 &range_das1x02_bip,
324 struct munge_info {
325 uint8_t byte;
326 unsigned have_byte:1;
329 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
330 struct comedi_insn *insn, unsigned int *data);
331 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
332 struct comedi_insn *insn, unsigned int *data);
333 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
334 struct comedi_insn *insn, unsigned int *data);
335 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
336 struct comedi_insn *insn, unsigned int *data);
338 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
339 struct comedi_cmd *cmd);
340 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s);
341 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
342 static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
343 void *array, unsigned int num_bytes, unsigned int start_chan_index);
345 static void das16_reset(struct comedi_device *dev);
346 static irqreturn_t das16_dma_interrupt(int irq, void *d);
347 static void das16_timer_interrupt(unsigned long arg);
348 static void das16_interrupt(struct comedi_device *dev);
350 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
351 int flags);
352 static int das1600_mode_detect(struct comedi_device *dev);
353 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
354 struct comedi_cmd cmd);
356 static void reg_dump(struct comedi_device *dev);
358 struct das16_board {
359 const char *name;
360 void *ai;
361 unsigned int ai_nbits;
362 unsigned int ai_speed; /* max conversion speed in nanosec */
363 unsigned int ai_pg;
364 void *ao;
365 unsigned int ao_nbits;
366 void *di;
367 void *do_;
369 unsigned int i8255_offset;
370 unsigned int i8254_offset;
372 unsigned int size;
373 unsigned int id;
376 static const struct das16_board das16_boards[] = {
378 .name = "das-16",
379 .ai = das16_ai_rinsn,
380 .ai_nbits = 12,
381 .ai_speed = 15000,
382 .ai_pg = das16_pg_none,
383 .ao = das16_ao_winsn,
384 .ao_nbits = 12,
385 .di = das16_di_rbits,
386 .do_ = das16_do_wbits,
387 .i8255_offset = 0x10,
388 .i8254_offset = 0x0c,
389 .size = 0x14,
390 .id = 0x00,
393 .name = "das-16g",
394 .ai = das16_ai_rinsn,
395 .ai_nbits = 12,
396 .ai_speed = 15000,
397 .ai_pg = das16_pg_none,
398 .ao = das16_ao_winsn,
399 .ao_nbits = 12,
400 .di = das16_di_rbits,
401 .do_ = das16_do_wbits,
402 .i8255_offset = 0x10,
403 .i8254_offset = 0x0c,
404 .size = 0x14,
405 .id = 0x00,
408 .name = "das-16f",
409 .ai = das16_ai_rinsn,
410 .ai_nbits = 12,
411 .ai_speed = 8500,
412 .ai_pg = das16_pg_none,
413 .ao = das16_ao_winsn,
414 .ao_nbits = 12,
415 .di = das16_di_rbits,
416 .do_ = das16_do_wbits,
417 .i8255_offset = 0x10,
418 .i8254_offset = 0x0c,
419 .size = 0x14,
420 .id = 0x00,
423 .name = "cio-das16", /* cio-das16.pdf */
424 .ai = das16_ai_rinsn,
425 .ai_nbits = 12,
426 .ai_speed = 20000,
427 .ai_pg = das16_pg_none,
428 .ao = das16_ao_winsn,
429 .ao_nbits = 12,
430 .di = das16_di_rbits,
431 .do_ = das16_do_wbits,
432 .i8255_offset = 0x10,
433 .i8254_offset = 0x0c,
434 .size = 0x14,
435 .id = 0x80,
438 .name = "cio-das16/f", /* das16.pdf */
439 .ai = das16_ai_rinsn,
440 .ai_nbits = 12,
441 .ai_speed = 10000,
442 .ai_pg = das16_pg_none,
443 .ao = das16_ao_winsn,
444 .ao_nbits = 12,
445 .di = das16_di_rbits,
446 .do_ = das16_do_wbits,
447 .i8255_offset = 0x10,
448 .i8254_offset = 0x0c,
449 .size = 0x14,
450 .id = 0x80,
453 .name = "cio-das16/jr", /* cio-das16jr.pdf */
454 .ai = das16_ai_rinsn,
455 .ai_nbits = 12,
456 .ai_speed = 7692,
457 .ai_pg = das16_pg_16jr,
458 .ao = NULL,
459 .di = das16_di_rbits,
460 .do_ = das16_do_wbits,
461 .i8255_offset = 0,
462 .i8254_offset = 0x0c,
463 .size = 0x10,
464 .id = 0x00,
467 .name = "pc104-das16jr", /* pc104-das16jr_xx.pdf */
468 .ai = das16_ai_rinsn,
469 .ai_nbits = 12,
470 .ai_speed = 3300,
471 .ai_pg = das16_pg_16jr,
472 .ao = NULL,
473 .di = das16_di_rbits,
474 .do_ = das16_do_wbits,
475 .i8255_offset = 0,
476 .i8254_offset = 0x0c,
477 .size = 0x10,
478 .id = 0x00,
481 .name = "cio-das16jr/16", /* cio-das16jr_16.pdf */
482 .ai = das16_ai_rinsn,
483 .ai_nbits = 16,
484 .ai_speed = 10000,
485 .ai_pg = das16_pg_16jr_16,
486 .ao = NULL,
487 .di = das16_di_rbits,
488 .do_ = das16_do_wbits,
489 .i8255_offset = 0,
490 .i8254_offset = 0x0c,
491 .size = 0x10,
492 .id = 0x00,
495 .name = "pc104-das16jr/16", /* pc104-das16jr_xx.pdf */
496 .ai = das16_ai_rinsn,
497 .ai_nbits = 16,
498 .ai_speed = 10000,
499 .ai_pg = das16_pg_16jr_16,
500 .ao = NULL,
501 .di = das16_di_rbits,
502 .do_ = das16_do_wbits,
503 .i8255_offset = 0,
504 .i8254_offset = 0x0c,
505 .size = 0x10,
506 .id = 0x00,
509 .name = "das-1201", /* 4924.pdf (keithley user's manual) */
510 .ai = das16_ai_rinsn,
511 .ai_nbits = 12,
512 .ai_speed = 20000,
513 .ai_pg = das16_pg_none,
514 .ao = NULL,
515 .di = das16_di_rbits,
516 .do_ = das16_do_wbits,
517 .i8255_offset = 0x400,
518 .i8254_offset = 0x0c,
519 .size = 0x408,
520 .id = 0x20,
523 .name = "das-1202", /* 4924.pdf (keithley user's manual) */
524 .ai = das16_ai_rinsn,
525 .ai_nbits = 12,
526 .ai_speed = 10000,
527 .ai_pg = das16_pg_none,
528 .ao = NULL,
529 .di = das16_di_rbits,
530 .do_ = das16_do_wbits,
531 .i8255_offset = 0x400,
532 .i8254_offset = 0x0c,
533 .size = 0x408,
534 .id = 0x20,
537 .name = "das-1401", /* 4919.pdf and 4922.pdf (keithley user's manual) */
538 .ai = das16_ai_rinsn,
539 .ai_nbits = 12,
540 .ai_speed = 10000,
541 .ai_pg = das16_pg_1601,
542 .ao = NULL,
543 .di = das16_di_rbits,
544 .do_ = das16_do_wbits,
545 .i8255_offset = 0x0,
546 .i8254_offset = 0x0c,
547 .size = 0x408,
548 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
551 .name = "das-1402", /* 4919.pdf and 4922.pdf (keithley user's manual) */
552 .ai = das16_ai_rinsn,
553 .ai_nbits = 12,
554 .ai_speed = 10000,
555 .ai_pg = das16_pg_1602,
556 .ao = NULL,
557 .di = das16_di_rbits,
558 .do_ = das16_do_wbits,
559 .i8255_offset = 0x0,
560 .i8254_offset = 0x0c,
561 .size = 0x408,
562 .id = 0xc0 /* 4919.pdf says id bits are 0xe0, 4922.pdf says 0xc0 */
565 .name = "das-1601", /* 4919.pdf */
566 .ai = das16_ai_rinsn,
567 .ai_nbits = 12,
568 .ai_speed = 10000,
569 .ai_pg = das16_pg_1601,
570 .ao = das16_ao_winsn,
571 .ao_nbits = 12,
572 .di = das16_di_rbits,
573 .do_ = das16_do_wbits,
574 .i8255_offset = 0x400,
575 .i8254_offset = 0x0c,
576 .size = 0x408,
577 .id = 0xc0},
579 .name = "das-1602", /* 4919.pdf */
580 .ai = das16_ai_rinsn,
581 .ai_nbits = 12,
582 .ai_speed = 10000,
583 .ai_pg = das16_pg_1602,
584 .ao = das16_ao_winsn,
585 .ao_nbits = 12,
586 .di = das16_di_rbits,
587 .do_ = das16_do_wbits,
588 .i8255_offset = 0x400,
589 .i8254_offset = 0x0c,
590 .size = 0x408,
591 .id = 0xc0},
593 .name = "cio-das1401/12", /* cio-das1400_series.pdf */
594 .ai = das16_ai_rinsn,
595 .ai_nbits = 12,
596 .ai_speed = 6250,
597 .ai_pg = das16_pg_1601,
598 .ao = NULL,
599 .di = das16_di_rbits,
600 .do_ = das16_do_wbits,
601 .i8255_offset = 0,
602 .i8254_offset = 0x0c,
603 .size = 0x408,
604 .id = 0xc0},
606 .name = "cio-das1402/12", /* cio-das1400_series.pdf */
607 .ai = das16_ai_rinsn,
608 .ai_nbits = 12,
609 .ai_speed = 6250,
610 .ai_pg = das16_pg_1602,
611 .ao = NULL,
612 .di = das16_di_rbits,
613 .do_ = das16_do_wbits,
614 .i8255_offset = 0,
615 .i8254_offset = 0x0c,
616 .size = 0x408,
617 .id = 0xc0},
619 .name = "cio-das1402/16", /* cio-das1400_series.pdf */
620 .ai = das16_ai_rinsn,
621 .ai_nbits = 16,
622 .ai_speed = 10000,
623 .ai_pg = das16_pg_1602,
624 .ao = NULL,
625 .di = das16_di_rbits,
626 .do_ = das16_do_wbits,
627 .i8255_offset = 0,
628 .i8254_offset = 0x0c,
629 .size = 0x408,
630 .id = 0xc0},
632 .name = "cio-das1601/12", /* cio-das160x-1x.pdf */
633 .ai = das16_ai_rinsn,
634 .ai_nbits = 12,
635 .ai_speed = 6250,
636 .ai_pg = das16_pg_1601,
637 .ao = das16_ao_winsn,
638 .ao_nbits = 12,
639 .di = das16_di_rbits,
640 .do_ = das16_do_wbits,
641 .i8255_offset = 0x400,
642 .i8254_offset = 0x0c,
643 .size = 0x408,
644 .id = 0xc0},
646 .name = "cio-das1602/12", /* cio-das160x-1x.pdf */
647 .ai = das16_ai_rinsn,
648 .ai_nbits = 12,
649 .ai_speed = 10000,
650 .ai_pg = das16_pg_1602,
651 .ao = das16_ao_winsn,
652 .ao_nbits = 12,
653 .di = das16_di_rbits,
654 .do_ = das16_do_wbits,
655 .i8255_offset = 0x400,
656 .i8254_offset = 0x0c,
657 .size = 0x408,
658 .id = 0xc0},
660 .name = "cio-das1602/16", /* cio-das160x-1x.pdf */
661 .ai = das16_ai_rinsn,
662 .ai_nbits = 16,
663 .ai_speed = 10000,
664 .ai_pg = das16_pg_1602,
665 .ao = das16_ao_winsn,
666 .ao_nbits = 12,
667 .di = das16_di_rbits,
668 .do_ = das16_do_wbits,
669 .i8255_offset = 0x400,
670 .i8254_offset = 0x0c,
671 .size = 0x408,
672 .id = 0xc0},
674 .name = "cio-das16/330", /* ? */
675 .ai = das16_ai_rinsn,
676 .ai_nbits = 12,
677 .ai_speed = 3030,
678 .ai_pg = das16_pg_16jr,
679 .ao = NULL,
680 .di = das16_di_rbits,
681 .do_ = das16_do_wbits,
682 .i8255_offset = 0,
683 .i8254_offset = 0x0c,
684 .size = 0x14,
685 .id = 0xf0},
686 #if 0
688 .name = "das16/330i", /* ? */
691 .name = "das16/jr/ctr5", /* ? */
694 .name = "cio-das16/m1/16", /* cio-das16_m1_16.pdf, this board is a bit quirky, no dma */
696 #endif
699 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it);
700 static int das16_detach(struct comedi_device *dev);
701 static struct comedi_driver driver_das16 = {
702 .driver_name = "das16",
703 .module = THIS_MODULE,
704 .attach = das16_attach,
705 .detach = das16_detach,
706 .board_name = &das16_boards[0].name,
707 .num_names = ARRAY_SIZE(das16_boards),
708 .offset = sizeof(das16_boards[0]),
711 #define DAS16_TIMEOUT 1000
713 /* Period for timer interrupt in jiffies. It's a function
714 * to deal with possibility of dynamic HZ patches */
715 static inline int timer_period(void)
717 return HZ / 20;
719 struct das16_private_struct {
720 unsigned int ai_unipolar; /* unipolar flag */
721 unsigned int ai_singleended; /* single ended flag */
722 unsigned int clockbase; /* master clock speed in ns */
723 volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
724 volatile unsigned long adc_byte_count; /* number of bytes remaining */
725 unsigned int divisor1; /* divisor dividing master clock to get conversion frequency */
726 unsigned int divisor2; /* divisor dividing master clock to get conversion frequency */
727 unsigned int dma_chan; /* dma channel */
728 uint16_t *dma_buffer[2];
729 dma_addr_t dma_buffer_addr[2];
730 unsigned int current_buffer;
731 volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
732 /* user-defined analog input and output ranges defined from config options */
733 struct comedi_lrange *user_ai_range_table;
734 struct comedi_lrange *user_ao_range_table;
736 struct timer_list timer; /* for timed interrupt */
737 volatile short timer_running;
738 volatile short timer_mode; /* true if using timer mode */
740 #define devpriv ((struct das16_private_struct *)(dev->private))
741 #define thisboard ((struct das16_board *)(dev->board_ptr))
743 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
744 struct comedi_cmd *cmd)
746 int err = 0, tmp;
747 int gain, start_chan, i;
748 int mask;
750 /* make sure triggers are valid */
751 tmp = cmd->start_src;
752 cmd->start_src &= TRIG_NOW;
753 if (!cmd->start_src || tmp != cmd->start_src)
754 err++;
756 tmp = cmd->scan_begin_src;
757 mask = TRIG_FOLLOW;
758 /* if board supports burst mode */
759 if (thisboard->size > 0x400)
760 mask |= TRIG_TIMER | TRIG_EXT;
761 cmd->scan_begin_src &= mask;
762 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
763 err++;
765 tmp = cmd->convert_src;
766 mask = TRIG_TIMER | TRIG_EXT;
767 /* if board supports burst mode */
768 if (thisboard->size > 0x400)
769 mask |= TRIG_NOW;
770 cmd->convert_src &= mask;
771 if (!cmd->convert_src || tmp != cmd->convert_src)
772 err++;
774 tmp = cmd->scan_end_src;
775 cmd->scan_end_src &= TRIG_COUNT;
776 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
777 err++;
779 tmp = cmd->stop_src;
780 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
781 if (!cmd->stop_src || tmp != cmd->stop_src)
782 err++;
784 if (err)
785 return 1;
787 /* step 2: make sure trigger sources are unique and mutually compatible */
788 if (cmd->scan_begin_src != TRIG_TIMER &&
789 cmd->scan_begin_src != TRIG_EXT &&
790 cmd->scan_begin_src != TRIG_FOLLOW)
791 err++;
792 if (cmd->convert_src != TRIG_TIMER &&
793 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW)
794 err++;
795 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
796 err++;
798 /* make sure scan_begin_src and convert_src dont conflict */
799 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
800 err++;
801 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
802 err++;
804 if (err)
805 return 2;
807 /* step 3: make sure arguments are trivially compatible */
808 if (cmd->start_arg != 0) {
809 cmd->start_arg = 0;
810 err++;
813 if (cmd->scan_begin_src == TRIG_FOLLOW) {
814 /* internal trigger */
815 if (cmd->scan_begin_arg != 0) {
816 cmd->scan_begin_arg = 0;
817 err++;
821 if (cmd->scan_end_arg != cmd->chanlist_len) {
822 cmd->scan_end_arg = cmd->chanlist_len;
823 err++;
825 /* check against maximum frequency */
826 if (cmd->scan_begin_src == TRIG_TIMER) {
827 if (cmd->scan_begin_arg <
828 thisboard->ai_speed * cmd->chanlist_len) {
829 cmd->scan_begin_arg =
830 thisboard->ai_speed * cmd->chanlist_len;
831 err++;
834 if (cmd->convert_src == TRIG_TIMER) {
835 if (cmd->convert_arg < thisboard->ai_speed) {
836 cmd->convert_arg = thisboard->ai_speed;
837 err++;
841 if (cmd->stop_src == TRIG_NONE) {
842 if (cmd->stop_arg != 0) {
843 cmd->stop_arg = 0;
844 err++;
847 if (err)
848 return 3;
850 /* step 4: fix up arguments */
851 if (cmd->scan_begin_src == TRIG_TIMER) {
852 unsigned int tmp = cmd->scan_begin_arg;
853 /* set divisors, correct timing arguments */
854 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
855 &(devpriv->divisor1), &(devpriv->divisor2),
856 &(cmd->scan_begin_arg), cmd->flags & TRIG_ROUND_MASK);
857 err += (tmp != cmd->scan_begin_arg);
859 if (cmd->convert_src == TRIG_TIMER) {
860 unsigned int tmp = cmd->convert_arg;
861 /* set divisors, correct timing arguments */
862 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
863 &(devpriv->divisor1), &(devpriv->divisor2),
864 &(cmd->convert_arg), cmd->flags & TRIG_ROUND_MASK);
865 err += (tmp != cmd->convert_arg);
867 if (err)
868 return 4;
870 /* check channel/gain list against card's limitations */
871 if (cmd->chanlist) {
872 gain = CR_RANGE(cmd->chanlist[0]);
873 start_chan = CR_CHAN(cmd->chanlist[0]);
874 for (i = 1; i < cmd->chanlist_len; i++) {
875 if (CR_CHAN(cmd->chanlist[i]) !=
876 (start_chan + i) % s->n_chan) {
877 comedi_error(dev,
878 "entries in chanlist must be consecutive channels, counting upwards\n");
879 err++;
881 if (CR_RANGE(cmd->chanlist[i]) != gain) {
882 comedi_error(dev,
883 "entries in chanlist must all have the same gain\n");
884 err++;
888 if (err)
889 return 5;
891 return 0;
894 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
896 struct comedi_async *async = s->async;
897 struct comedi_cmd *cmd = &async->cmd;
898 unsigned int byte;
899 unsigned long flags;
900 int range;
902 if (devpriv->dma_chan == 0 || (dev->irq == 0
903 && devpriv->timer_mode == 0)) {
904 comedi_error(dev,
905 "irq (or use of 'timer mode') dma required to execute comedi_cmd");
906 return -1;
908 if (cmd->flags & TRIG_RT) {
909 comedi_error(dev,
910 "isa dma transfers cannot be performed with TRIG_RT, aborting");
911 return -1;
914 devpriv->adc_byte_count =
915 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
917 /* disable conversions for das1600 mode */
918 if (thisboard->size > 0x400) {
919 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
921 /* set scan limits */
922 byte = CR_CHAN(cmd->chanlist[0]);
923 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
924 outb(byte, dev->iobase + DAS16_MUX);
926 /* set gain (this is also burst rate register but according to
927 * computer boards manual, burst rate does nothing, even on keithley cards) */
928 if (thisboard->ai_pg != das16_pg_none) {
929 range = CR_RANGE(cmd->chanlist[0]);
930 outb((das16_gainlists[thisboard->ai_pg])[range],
931 dev->iobase + DAS16_GAIN);
934 /* set counter mode and counts */
935 cmd->convert_arg =
936 das16_set_pacer(dev, cmd->convert_arg,
937 cmd->flags & TRIG_ROUND_MASK);
938 DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
940 /* enable counters */
941 byte = 0;
942 /* Enable burst mode if appropriate. */
943 if (thisboard->size > 0x400) {
944 if (cmd->convert_src == TRIG_NOW) {
945 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
946 /* set burst length */
947 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
948 } else {
949 outb(0, dev->iobase + DAS1600_BURST);
952 outb(byte, dev->iobase + DAS16_PACER);
954 /* set up dma transfer */
955 flags = claim_dma_lock();
956 disable_dma(devpriv->dma_chan);
957 /* clear flip-flop to make sure 2-byte registers for
958 * count and address get set correctly */
959 clear_dma_ff(devpriv->dma_chan);
960 devpriv->current_buffer = 0;
961 set_dma_addr(devpriv->dma_chan,
962 devpriv->dma_buffer_addr[devpriv->current_buffer]);
963 /* set appropriate size of transfer */
964 devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, *cmd);
965 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
966 enable_dma(devpriv->dma_chan);
967 release_dma_lock(flags);
969 /* set up interrupt */
970 if (devpriv->timer_mode) {
971 devpriv->timer_running = 1;
972 devpriv->timer.expires = jiffies + timer_period();
973 add_timer(&devpriv->timer);
974 devpriv->control_state &= ~DAS16_INTE;
975 } else {
976 /* clear interrupt bit */
977 outb(0x00, dev->iobase + DAS16_STATUS);
978 /* enable interrupts */
979 devpriv->control_state |= DAS16_INTE;
981 devpriv->control_state |= DMA_ENABLE;
982 devpriv->control_state &= ~PACING_MASK;
983 if (cmd->convert_src == TRIG_EXT)
984 devpriv->control_state |= EXT_PACER;
985 else
986 devpriv->control_state |= INT_PACER;
987 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
989 /* Enable conversions if using das1600 mode */
990 if (thisboard->size > 0x400) {
991 outb(0, dev->iobase + DAS1600_CONV);
994 return 0;
997 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
999 unsigned long flags;
1001 spin_lock_irqsave(&dev->spinlock, flags);
1002 /* disable interrupts, dma and pacer clocked conversions */
1003 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
1004 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1005 if (devpriv->dma_chan)
1006 disable_dma(devpriv->dma_chan);
1008 /* disable SW timer */
1009 if (devpriv->timer_mode && devpriv->timer_running) {
1010 devpriv->timer_running = 0;
1011 del_timer(&devpriv->timer);
1014 /* disable burst mode */
1015 if (thisboard->size > 0x400) {
1016 outb(0, dev->iobase + DAS1600_BURST);
1019 spin_unlock_irqrestore(&dev->spinlock, flags);
1021 return 0;
1024 static void das16_reset(struct comedi_device *dev)
1026 outb(0, dev->iobase + DAS16_STATUS);
1027 outb(0, dev->iobase + DAS16_CONTROL);
1028 outb(0, dev->iobase + DAS16_PACER);
1029 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
1032 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1033 struct comedi_insn *insn, unsigned int *data)
1035 int i, n;
1036 int range;
1037 int chan;
1038 int msb, lsb;
1040 /* disable interrupts and pacing */
1041 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
1042 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1044 /* set multiplexer */
1045 chan = CR_CHAN(insn->chanspec);
1046 chan |= CR_CHAN(insn->chanspec) << 4;
1047 outb(chan, dev->iobase + DAS16_MUX);
1049 /* set gain */
1050 if (thisboard->ai_pg != das16_pg_none) {
1051 range = CR_RANGE(insn->chanspec);
1052 outb((das16_gainlists[thisboard->ai_pg])[range],
1053 dev->iobase + DAS16_GAIN);
1056 for (n = 0; n < insn->n; n++) {
1057 /* trigger conversion */
1058 outb_p(0, dev->iobase + DAS16_TRIG);
1060 for (i = 0; i < DAS16_TIMEOUT; i++) {
1061 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
1062 break;
1064 if (i == DAS16_TIMEOUT) {
1065 printk("das16: timeout\n");
1066 return -ETIME;
1068 msb = inb(dev->iobase + DAS16_AI_MSB);
1069 lsb = inb(dev->iobase + DAS16_AI_LSB);
1070 if (thisboard->ai_nbits == 12) {
1071 data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
1072 } else {
1073 data[n] = lsb | (msb << 8);
1077 return n;
1080 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
1081 struct comedi_insn *insn, unsigned int *data)
1083 unsigned int bits;
1085 bits = inb(dev->iobase + DAS16_DIO) & 0xf;
1086 data[1] = bits;
1087 data[0] = 0;
1089 return 2;
1092 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
1093 struct comedi_insn *insn, unsigned int *data)
1095 unsigned int wbits;
1097 /* only set bits that have been masked */
1098 data[0] &= 0xf;
1099 wbits = s->state;
1100 /* zero bits that have been masked */
1101 wbits &= ~data[0];
1102 /* set masked bits */
1103 wbits |= data[0] & data[1];
1104 s->state = wbits;
1105 data[1] = wbits;
1107 outb(s->state, dev->iobase + DAS16_DIO);
1109 return 2;
1112 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
1113 struct comedi_insn *insn, unsigned int *data)
1115 int i;
1116 int lsb, msb;
1117 int chan;
1119 chan = CR_CHAN(insn->chanspec);
1121 for (i = 0; i < insn->n; i++) {
1122 if (thisboard->ao_nbits == 12) {
1123 lsb = (data[i] << 4) & 0xff;
1124 msb = (data[i] >> 4) & 0xff;
1125 } else {
1126 lsb = data[i] & 0xff;
1127 msb = (data[i] >> 8) & 0xff;
1129 outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
1130 outb(msb, dev->iobase + DAS16_AO_MSB(chan));
1133 return i;
1136 static irqreturn_t das16_dma_interrupt(int irq, void *d)
1138 int status;
1139 struct comedi_device *dev = d;
1141 status = inb(dev->iobase + DAS16_STATUS);
1143 if ((status & DAS16_INT) == 0) {
1144 DEBUG_PRINT("spurious interrupt\n");
1145 return IRQ_NONE;
1148 /* clear interrupt */
1149 outb(0x00, dev->iobase + DAS16_STATUS);
1150 das16_interrupt(dev);
1151 return IRQ_HANDLED;
1154 static void das16_timer_interrupt(unsigned long arg)
1156 struct comedi_device *dev = (struct comedi_device *) arg;
1158 das16_interrupt(dev);
1160 if (devpriv->timer_running)
1161 mod_timer(&devpriv->timer, jiffies + timer_period());
1164 /* the pc104-das16jr (at least) has problems if the dma
1165 transfer is interrupted in the middle of transferring
1166 a 16 bit sample, so this function takes care to get
1167 an even transfer count after disabling dma
1168 channel.
1170 static int disable_dma_on_even(struct comedi_device *dev)
1172 int residue;
1173 int i;
1174 static const int disable_limit = 100;
1175 static const int enable_timeout = 100;
1176 disable_dma(devpriv->dma_chan);
1177 residue = get_dma_residue(devpriv->dma_chan);
1178 for (i = 0; i < disable_limit && (residue % 2); ++i) {
1179 int j;
1180 enable_dma(devpriv->dma_chan);
1181 for (j = 0; j < enable_timeout; ++j) {
1182 int new_residue;
1183 udelay(2);
1184 new_residue = get_dma_residue(devpriv->dma_chan);
1185 if (new_residue != residue)
1186 break;
1188 disable_dma(devpriv->dma_chan);
1189 residue = get_dma_residue(devpriv->dma_chan);
1191 if (i == disable_limit) {
1192 comedi_error(dev,
1193 "failed to get an even dma transfer, could be trouble.");
1195 return residue;
1198 static void das16_interrupt(struct comedi_device *dev)
1200 unsigned long dma_flags, spin_flags;
1201 struct comedi_subdevice *s = dev->read_subdev;
1202 struct comedi_async *async;
1203 struct comedi_cmd *cmd;
1204 int num_bytes, residue;
1205 int buffer_index;
1207 if (dev->attached == 0) {
1208 comedi_error(dev, "premature interrupt");
1209 return;
1211 /* initialize async here to make sure it is not NULL */
1212 async = s->async;
1213 cmd = &async->cmd;
1215 if (devpriv->dma_chan == 0) {
1216 comedi_error(dev, "interrupt with no dma channel?");
1217 return;
1220 spin_lock_irqsave(&dev->spinlock, spin_flags);
1221 if ((devpriv->control_state & DMA_ENABLE) == 0) {
1222 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
1223 DEBUG_PRINT("interrupt while dma disabled?\n");
1224 return;
1227 dma_flags = claim_dma_lock();
1228 clear_dma_ff(devpriv->dma_chan);
1229 residue = disable_dma_on_even(dev);
1231 /* figure out how many points to read */
1232 if (residue > devpriv->dma_transfer_size) {
1233 comedi_error(dev, "residue > transfer size!\n");
1234 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
1235 num_bytes = 0;
1236 } else
1237 num_bytes = devpriv->dma_transfer_size - residue;
1239 if (cmd->stop_src == TRIG_COUNT && num_bytes >= devpriv->adc_byte_count) {
1240 num_bytes = devpriv->adc_byte_count;
1241 async->events |= COMEDI_CB_EOA;
1244 buffer_index = devpriv->current_buffer;
1245 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
1246 devpriv->adc_byte_count -= num_bytes;
1248 /* figure out how many bytes for next transfer */
1249 if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
1250 devpriv->dma_transfer_size > devpriv->adc_byte_count)
1251 devpriv->dma_transfer_size = devpriv->adc_byte_count;
1253 /* re-enable dma */
1254 if ((async->events & COMEDI_CB_EOA) == 0) {
1255 set_dma_addr(devpriv->dma_chan,
1256 devpriv->dma_buffer_addr[devpriv->current_buffer]);
1257 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
1258 enable_dma(devpriv->dma_chan);
1259 /* reenable conversions for das1600 mode, (stupid hardware) */
1260 if (thisboard->size > 0x400 && devpriv->timer_mode == 0) {
1261 outb(0x00, dev->iobase + DAS1600_CONV);
1264 release_dma_lock(dma_flags);
1266 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
1268 cfc_write_array_to_buffer(s,
1269 devpriv->dma_buffer[buffer_index], num_bytes);
1271 cfc_handle_events(dev, s);
1274 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
1275 int rounding_flags)
1277 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
1278 &(devpriv->divisor2), &ns, rounding_flags & TRIG_ROUND_MASK);
1280 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
1281 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
1282 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
1284 return ns;
1287 static void reg_dump(struct comedi_device *dev)
1289 DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
1290 DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
1291 DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
1292 DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
1293 DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
1294 DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
1295 DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
1296 DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
1297 inb(dev->iobase + DAS16_CNTR_CONTROL));
1298 DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
1299 DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
1300 DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
1301 DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
1302 inb(dev->iobase + DAS1600_STATUS_B));
1305 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
1307 int status;
1308 int diobits;
1310 /* status is available on all boards */
1312 status = inb(dev->iobase + DAS16_STATUS);
1314 if ((status & UNIPOLAR)) {
1315 devpriv->ai_unipolar = 1;
1316 } else {
1317 devpriv->ai_unipolar = 0;
1320 if ((status & DAS16_MUXBIT)) {
1321 devpriv->ai_singleended = 1;
1322 } else {
1323 devpriv->ai_singleended = 0;
1326 /* diobits indicates boards */
1328 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
1330 printk(" id bits are 0x%02x\n", diobits);
1331 if (thisboard->id != diobits) {
1332 printk(" requested board's id bits are 0x%x (ignore)\n",
1333 thisboard->id);
1336 return 0;
1339 static int das1600_mode_detect(struct comedi_device *dev)
1341 int status = 0;
1343 status = inb(dev->iobase + DAS1600_STATUS_B);
1345 if (status & DAS1600_CLK_10MHZ) {
1346 devpriv->clockbase = 100;
1347 printk(" 10MHz pacer clock\n");
1348 } else {
1349 devpriv->clockbase = 1000;
1350 printk(" 1MHz pacer clock\n");
1353 reg_dump(dev);
1355 return 0;
1360 * Options list:
1361 * 0 I/O base
1362 * 1 IRQ
1363 * 2 DMA
1364 * 3 Clock speed (in MHz)
1367 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1369 struct comedi_subdevice *s;
1370 int ret;
1371 unsigned int irq;
1372 unsigned long iobase;
1373 unsigned int dma_chan;
1374 int timer_mode;
1375 unsigned long flags;
1376 struct comedi_krange *user_ai_range, *user_ao_range;
1378 iobase = it->options[0];
1379 #if 0
1380 irq = it->options[1];
1381 timer_mode = it->options[8];
1382 #endif
1383 /* always use time_mode since using irq can drop samples while
1384 * waiting for dma done interrupt (due to hardware limitations) */
1385 irq = 0;
1386 timer_mode = 1;
1387 if (timer_mode)
1388 irq = 0;
1390 printk("comedi%d: das16:", dev->minor);
1392 /* check that clock setting is valid */
1393 if (it->options[3]) {
1394 if (it->options[3] != 0 &&
1395 it->options[3] != 1 && it->options[3] != 10) {
1396 printk("\n Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1397 return -EINVAL;
1401 ret = alloc_private(dev, sizeof(struct das16_private_struct));
1402 if (ret < 0)
1403 return ret;
1405 if (thisboard->size < 0x400) {
1406 printk(" 0x%04lx-0x%04lx\n", iobase, iobase + thisboard->size);
1407 if (!request_region(iobase, thisboard->size, "das16")) {
1408 printk(" I/O port conflict\n");
1409 return -EIO;
1411 } else {
1412 printk(" 0x%04lx-0x%04lx 0x%04lx-0x%04lx\n",
1413 iobase, iobase + 0x0f,
1414 iobase + 0x400,
1415 iobase + 0x400 + (thisboard->size & 0x3ff));
1416 if (!request_region(iobase, 0x10, "das16")) {
1417 printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
1418 iobase, iobase + 0x0f);
1419 return -EIO;
1421 if (!request_region(iobase + 0x400, thisboard->size & 0x3ff,
1422 "das16")) {
1423 release_region(iobase, 0x10);
1424 printk(" I/O port conflict: 0x%04lx-0x%04lx\n",
1425 iobase + 0x400,
1426 iobase + 0x400 + (thisboard->size & 0x3ff));
1427 return -EIO;
1431 dev->iobase = iobase;
1433 /* probe id bits to make sure they are consistent */
1434 if (das16_probe(dev, it)) {
1435 printk(" id bits do not match selected board, aborting\n");
1436 return -EINVAL;
1438 dev->board_name = thisboard->name;
1440 /* get master clock speed */
1441 if (thisboard->size < 0x400) {
1442 if (it->options[3])
1443 devpriv->clockbase = 1000 / it->options[3];
1444 else
1445 devpriv->clockbase = 1000; /* 1 MHz default */
1446 } else {
1447 das1600_mode_detect(dev);
1450 /* now for the irq */
1451 if (irq > 1 && irq < 8) {
1452 ret = request_irq(irq, das16_dma_interrupt, 0, "das16", dev);
1454 if (ret < 0)
1455 return ret;
1456 dev->irq = irq;
1457 printk(" ( irq = %u )", irq);
1458 } else if (irq == 0) {
1459 printk(" ( no irq )");
1460 } else {
1461 printk(" invalid irq\n");
1462 return -EINVAL;
1465 /* initialize dma */
1466 dma_chan = it->options[2];
1467 if (dma_chan == 1 || dma_chan == 3) {
1468 /* allocate dma buffers */
1469 int i;
1470 for (i = 0; i < 2; i++) {
1471 devpriv->dma_buffer[i] = pci_alloc_consistent(NULL,
1472 DAS16_DMA_SIZE, &devpriv->dma_buffer_addr[i]);
1473 if (devpriv->dma_buffer[i] == NULL)
1474 return -ENOMEM;
1476 if (request_dma(dma_chan, "das16")) {
1477 printk(" failed to allocate dma channel %i\n",
1478 dma_chan);
1479 return -EINVAL;
1481 devpriv->dma_chan = dma_chan;
1482 flags = claim_dma_lock();
1483 disable_dma(devpriv->dma_chan);
1484 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1485 release_dma_lock(flags);
1486 printk(" ( dma = %u)\n", dma_chan);
1487 } else if (dma_chan == 0) {
1488 printk(" ( no dma )\n");
1489 } else {
1490 printk(" invalid dma channel\n");
1491 return -EINVAL;
1494 /* get any user-defined input range */
1495 if (thisboard->ai_pg == das16_pg_none &&
1496 (it->options[4] || it->options[5])) {
1497 /* allocate single-range range table */
1498 devpriv->user_ai_range_table =
1499 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
1500 GFP_KERNEL);
1501 /* initialize ai range */
1502 devpriv->user_ai_range_table->length = 1;
1503 user_ai_range = devpriv->user_ai_range_table->range;
1504 user_ai_range->min = it->options[4];
1505 user_ai_range->max = it->options[5];
1506 user_ai_range->flags = UNIT_volt;
1508 /* get any user-defined output range */
1509 if (it->options[6] || it->options[7]) {
1510 /* allocate single-range range table */
1511 devpriv->user_ao_range_table =
1512 kmalloc(sizeof(struct comedi_lrange) + sizeof(struct comedi_krange),
1513 GFP_KERNEL);
1514 /* initialize ao range */
1515 devpriv->user_ao_range_table->length = 1;
1516 user_ao_range = devpriv->user_ao_range_table->range;
1517 user_ao_range->min = it->options[6];
1518 user_ao_range->max = it->options[7];
1519 user_ao_range->flags = UNIT_volt;
1522 if (timer_mode) {
1523 init_timer(&(devpriv->timer));
1524 devpriv->timer.function = das16_timer_interrupt;
1525 devpriv->timer.data = (unsigned long)dev;
1527 devpriv->timer_mode = timer_mode ? 1 : 0;
1529 ret = alloc_subdevices(dev, 5);
1530 if (ret < 0)
1531 return ret;
1533 s = dev->subdevices + 0;
1534 dev->read_subdev = s;
1535 /* ai */
1536 if (thisboard->ai) {
1537 s->type = COMEDI_SUBD_AI;
1538 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1539 if (devpriv->ai_singleended) {
1540 s->n_chan = 16;
1541 s->len_chanlist = 16;
1542 s->subdev_flags |= SDF_GROUND;
1543 } else {
1544 s->n_chan = 8;
1545 s->len_chanlist = 8;
1546 s->subdev_flags |= SDF_DIFF;
1548 s->maxdata = (1 << thisboard->ai_nbits) - 1;
1549 if (devpriv->user_ai_range_table) { /* user defined ai range */
1550 s->range_table = devpriv->user_ai_range_table;
1551 } else if (devpriv->ai_unipolar) {
1552 s->range_table = das16_ai_uni_lranges[thisboard->ai_pg];
1553 } else {
1554 s->range_table = das16_ai_bip_lranges[thisboard->ai_pg];
1556 s->insn_read = thisboard->ai;
1557 s->do_cmdtest = das16_cmd_test;
1558 s->do_cmd = das16_cmd_exec;
1559 s->cancel = das16_cancel;
1560 s->munge = das16_ai_munge;
1561 } else {
1562 s->type = COMEDI_SUBD_UNUSED;
1565 s = dev->subdevices + 1;
1566 /* ao */
1567 if (thisboard->ao) {
1568 s->type = COMEDI_SUBD_AO;
1569 s->subdev_flags = SDF_WRITABLE;
1570 s->n_chan = 2;
1571 s->maxdata = (1 << thisboard->ao_nbits) - 1;
1572 if (devpriv->user_ao_range_table) { /* user defined ao range */
1573 s->range_table = devpriv->user_ao_range_table;
1574 } else {
1575 s->range_table = &range_unknown;
1577 s->insn_write = thisboard->ao;
1578 } else {
1579 s->type = COMEDI_SUBD_UNUSED;
1582 s = dev->subdevices + 2;
1583 /* di */
1584 if (thisboard->di) {
1585 s->type = COMEDI_SUBD_DI;
1586 s->subdev_flags = SDF_READABLE;
1587 s->n_chan = 4;
1588 s->maxdata = 1;
1589 s->range_table = &range_digital;
1590 s->insn_bits = thisboard->di;
1591 } else {
1592 s->type = COMEDI_SUBD_UNUSED;
1595 s = dev->subdevices + 3;
1596 /* do */
1597 if (thisboard->do_) {
1598 s->type = COMEDI_SUBD_DO;
1599 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1600 s->n_chan = 4;
1601 s->maxdata = 1;
1602 s->range_table = &range_digital;
1603 s->insn_bits = thisboard->do_;
1604 /* initialize digital output lines */
1605 outb(s->state, dev->iobase + DAS16_DIO);
1606 } else {
1607 s->type = COMEDI_SUBD_UNUSED;
1610 s = dev->subdevices + 4;
1611 /* 8255 */
1612 if (thisboard->i8255_offset != 0) {
1613 subdev_8255_init(dev, s, NULL, (dev->iobase +
1614 thisboard->i8255_offset));
1615 } else {
1616 s->type = COMEDI_SUBD_UNUSED;
1619 das16_reset(dev);
1620 /* set the interrupt level */
1621 devpriv->control_state = DAS16_IRQ(dev->irq);
1622 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1624 /* turn on das1600 mode if available */
1625 if (thisboard->size > 0x400) {
1626 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1627 outb(0, dev->iobase + DAS1600_CONV);
1628 outb(0, dev->iobase + DAS1600_BURST);
1631 return 0;
1634 static int das16_detach(struct comedi_device *dev)
1636 printk("comedi%d: das16: remove\n", dev->minor);
1638 das16_reset(dev);
1640 if (dev->subdevices)
1641 subdev_8255_cleanup(dev, dev->subdevices + 4);
1643 if (devpriv) {
1644 int i;
1645 for (i = 0; i < 2; i++) {
1646 if (devpriv->dma_buffer[i])
1647 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1648 devpriv->dma_buffer[i],
1649 devpriv->dma_buffer_addr[i]);
1651 if (devpriv->dma_chan)
1652 free_dma(devpriv->dma_chan);
1653 if (devpriv->user_ai_range_table)
1654 kfree(devpriv->user_ai_range_table);
1655 if (devpriv->user_ao_range_table)
1656 kfree(devpriv->user_ao_range_table);
1659 if (dev->irq)
1660 free_irq(dev->irq, dev);
1662 if (dev->iobase) {
1663 if (thisboard->size < 0x400) {
1664 release_region(dev->iobase, thisboard->size);
1665 } else {
1666 release_region(dev->iobase, 0x10);
1667 release_region(dev->iobase + 0x400,
1668 thisboard->size & 0x3ff);
1672 return 0;
1675 COMEDI_INITCLEANUP(driver_das16);
1677 /* utility function that suggests a dma transfer size in bytes */
1678 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
1679 struct comedi_cmd cmd)
1681 unsigned int size;
1682 unsigned int freq;
1684 /* if we are using timer interrupt, we don't care how long it
1685 * will take to complete transfer since it will be interrupted
1686 * by timer interrupt */
1687 if (devpriv->timer_mode)
1688 return DAS16_DMA_SIZE;
1690 /* otherwise, we are relying on dma terminal count interrupt,
1691 * so pick a reasonable size */
1692 if (cmd.convert_src == TRIG_TIMER)
1693 freq = 1000000000 / cmd.convert_arg;
1694 else if (cmd.scan_begin_src == TRIG_TIMER)
1695 freq = (1000000000 / cmd.scan_begin_arg) * cmd.chanlist_len;
1696 /* return some default value */
1697 else
1698 freq = 0xffffffff;
1700 if (cmd.flags & TRIG_WAKE_EOS) {
1701 size = sample_size * cmd.chanlist_len;
1702 } else {
1703 /* make buffer fill in no more than 1/3 second */
1704 size = (freq / 3) * sample_size;
1707 /* set a minimum and maximum size allowed */
1708 if (size > DAS16_DMA_SIZE)
1709 size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
1710 else if (size < sample_size)
1711 size = sample_size;
1713 if (cmd.stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
1714 size = devpriv->adc_byte_count;
1716 return size;
1719 static void das16_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
1720 void *array, unsigned int num_bytes, unsigned int start_chan_index)
1722 unsigned int i, num_samples = num_bytes / sizeof(short);
1723 short *data = array;
1725 for (i = 0; i < num_samples; i++) {
1726 data[i] = le16_to_cpu(data[i]);
1727 if (thisboard->ai_nbits == 12) {
1728 data[i] = (data[i] >> 4) & 0xfff;