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