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