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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103#include <linux/interrupt.h>
104#include "../comedidev.h"
105
106#include <linux/ioport.h>
107#include <asm/dma.h>
108
109#include "8253.h"
110#include "comedi_fc.h"
111
112
113#define DAS1800_SIZE 16
114#define FIFO_SIZE 1024
115#define TIMER_BASE 200
116#define UNIPOLAR 0x4
117#define DMA_BUF_SIZE 0x1ff00
118
119
120#define DAS1800_FIFO 0x0
121#define DAS1800_QRAM 0x0
122#define DAS1800_DAC 0x0
123#define DAS1800_SELECT 0x2
124#define ADC 0x0
125#define QRAM 0x1
126#define DAC(a) (0x2 + a)
127#define DAS1800_DIGITAL 0x3
128#define DAS1800_CONTROL_A 0x4
129#define FFEN 0x1
130#define CGEN 0x4
131#define CGSL 0x8
132#define TGEN 0x10
133#define TGSL 0x20
134#define ATEN 0x80
135#define DAS1800_CONTROL_B 0x5
136#define DMA_CH5 0x1
137#define DMA_CH6 0x2
138#define DMA_CH7 0x3
139#define DMA_CH5_CH6 0x5
140#define DMA_CH6_CH7 0x6
141#define DMA_CH7_CH5 0x7
142#define DMA_ENABLED 0x3
143#define DMA_DUAL 0x4
144#define IRQ3 0x8
145#define IRQ5 0x10
146#define IRQ7 0x18
147#define IRQ10 0x28
148#define IRQ11 0x30
149#define IRQ15 0x38
150#define FIMD 0x40
151#define DAS1800_CONTROL_C 0X6
152#define IPCLK 0x1
153#define XPCLK 0x3
154#define BMDE 0x4
155#define CMEN 0x8
156#define UQEN 0x10
157#define SD 0x40
158#define UB 0x80
159#define DAS1800_STATUS 0x7
160
161#define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
162#define INT 0x1
163#define DMATC 0x2
164#define CT0TC 0x8
165#define OVF 0x10
166#define FHF 0x20
167#define FNE 0x40
168#define CVEN_MASK 0x40
169#define CVEN 0x80
170#define DAS1800_BURST_LENGTH 0x8
171#define DAS1800_BURST_RATE 0x9
172#define DAS1800_QRAM_ADDRESS 0xa
173#define DAS1800_COUNTER 0xc
174
175#define IOBASE2 0x400
176
177enum {
178 das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
179 das1702hr_da,
180 das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
181 das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
182};
183
184static int das1800_attach(struct comedi_device *dev,
185 struct comedi_devconfig *it);
186static int das1800_detach(struct comedi_device *dev);
187static int das1800_probe(struct comedi_device *dev);
188static int das1800_cancel(struct comedi_device *dev,
189 struct comedi_subdevice *s);
190static irqreturn_t das1800_interrupt(int irq, void *d);
191static int das1800_ai_poll(struct comedi_device *dev,
192 struct comedi_subdevice *s);
193static void das1800_ai_handler(struct comedi_device *dev);
194static void das1800_handle_dma(struct comedi_device *dev,
195 struct comedi_subdevice *s, unsigned int status);
196static void das1800_flush_dma(struct comedi_device *dev,
197 struct comedi_subdevice *s);
198static void das1800_flush_dma_channel(struct comedi_device *dev,
199 struct comedi_subdevice *s,
200 unsigned int channel, uint16_t * buffer);
201static void das1800_handle_fifo_half_full(struct comedi_device *dev,
202 struct comedi_subdevice *s);
203static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
204 struct comedi_subdevice *s);
205static int das1800_ai_do_cmdtest(struct comedi_device *dev,
206 struct comedi_subdevice *s,
207 struct comedi_cmd *cmd);
208static int das1800_ai_do_cmd(struct comedi_device *dev,
209 struct comedi_subdevice *s);
210static int das1800_ai_rinsn(struct comedi_device *dev,
211 struct comedi_subdevice *s,
212 struct comedi_insn *insn, unsigned int *data);
213static int das1800_ao_winsn(struct comedi_device *dev,
214 struct comedi_subdevice *s,
215 struct comedi_insn *insn, unsigned int *data);
216static int das1800_di_rbits(struct comedi_device *dev,
217 struct comedi_subdevice *s,
218 struct comedi_insn *insn, unsigned int *data);
219static int das1800_do_wbits(struct comedi_device *dev,
220 struct comedi_subdevice *s,
221 struct comedi_insn *insn, unsigned int *data);
222
223static int das1800_set_frequency(struct comedi_device *dev);
224static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
225static unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
226
227
228static const struct comedi_lrange range_ai_das1801 = {
229 8,
230 {
231 RANGE(-5, 5),
232 RANGE(-1, 1),
233 RANGE(-0.1, 0.1),
234 RANGE(-0.02, 0.02),
235 RANGE(0, 5),
236 RANGE(0, 1),
237 RANGE(0, 0.1),
238 RANGE(0, 0.02),
239 }
240};
241
242static const struct comedi_lrange range_ai_das1802 = {
243 8,
244 {
245 RANGE(-10, 10),
246 RANGE(-5, 5),
247 RANGE(-2.5, 2.5),
248 RANGE(-1.25, 1.25),
249 RANGE(0, 10),
250 RANGE(0, 5),
251 RANGE(0, 2.5),
252 RANGE(0, 1.25),
253 }
254};
255
256struct das1800_board {
257 const char *name;
258 int ai_speed;
259 int resolution;
260 int qram_len;
261 int common;
262 int do_n_chan;
263 int ao_ability;
264 int ao_n_chan;
265 const struct comedi_lrange *range_ai;
266};
267
268
269
270
271
272static const struct das1800_board das1800_boards[] = {
273 {
274 .name = "das-1701st",
275 .ai_speed = 6250,
276 .resolution = 12,
277 .qram_len = 256,
278 .common = 1,
279 .do_n_chan = 4,
280 .ao_ability = 0,
281 .ao_n_chan = 0,
282 .range_ai = &range_ai_das1801,
283 },
284 {
285 .name = "das-1701st-da",
286 .ai_speed = 6250,
287 .resolution = 12,
288 .qram_len = 256,
289 .common = 1,
290 .do_n_chan = 4,
291 .ao_ability = 1,
292 .ao_n_chan = 4,
293 .range_ai = &range_ai_das1801,
294 },
295 {
296 .name = "das-1702st",
297 .ai_speed = 6250,
298 .resolution = 12,
299 .qram_len = 256,
300 .common = 1,
301 .do_n_chan = 4,
302 .ao_ability = 0,
303 .ao_n_chan = 0,
304 .range_ai = &range_ai_das1802,
305 },
306 {
307 .name = "das-1702st-da",
308 .ai_speed = 6250,
309 .resolution = 12,
310 .qram_len = 256,
311 .common = 1,
312 .do_n_chan = 4,
313 .ao_ability = 1,
314 .ao_n_chan = 4,
315 .range_ai = &range_ai_das1802,
316 },
317 {
318 .name = "das-1702hr",
319 .ai_speed = 20000,
320 .resolution = 16,
321 .qram_len = 256,
322 .common = 1,
323 .do_n_chan = 4,
324 .ao_ability = 0,
325 .ao_n_chan = 0,
326 .range_ai = &range_ai_das1802,
327 },
328 {
329 .name = "das-1702hr-da",
330 .ai_speed = 20000,
331 .resolution = 16,
332 .qram_len = 256,
333 .common = 1,
334 .do_n_chan = 4,
335 .ao_ability = 1,
336 .ao_n_chan = 2,
337 .range_ai = &range_ai_das1802,
338 },
339 {
340 .name = "das-1701ao",
341 .ai_speed = 6250,
342 .resolution = 12,
343 .qram_len = 256,
344 .common = 1,
345 .do_n_chan = 4,
346 .ao_ability = 2,
347 .ao_n_chan = 2,
348 .range_ai = &range_ai_das1801,
349 },
350 {
351 .name = "das-1702ao",
352 .ai_speed = 6250,
353 .resolution = 12,
354 .qram_len = 256,
355 .common = 1,
356 .do_n_chan = 4,
357 .ao_ability = 2,
358 .ao_n_chan = 2,
359 .range_ai = &range_ai_das1802,
360 },
361 {
362 .name = "das-1801st",
363 .ai_speed = 3000,
364 .resolution = 12,
365 .qram_len = 256,
366 .common = 1,
367 .do_n_chan = 4,
368 .ao_ability = 0,
369 .ao_n_chan = 0,
370 .range_ai = &range_ai_das1801,
371 },
372 {
373 .name = "das-1801st-da",
374 .ai_speed = 3000,
375 .resolution = 12,
376 .qram_len = 256,
377 .common = 1,
378 .do_n_chan = 4,
379 .ao_ability = 0,
380 .ao_n_chan = 4,
381 .range_ai = &range_ai_das1801,
382 },
383 {
384 .name = "das-1802st",
385 .ai_speed = 3000,
386 .resolution = 12,
387 .qram_len = 256,
388 .common = 1,
389 .do_n_chan = 4,
390 .ao_ability = 0,
391 .ao_n_chan = 0,
392 .range_ai = &range_ai_das1802,
393 },
394 {
395 .name = "das-1802st-da",
396 .ai_speed = 3000,
397 .resolution = 12,
398 .qram_len = 256,
399 .common = 1,
400 .do_n_chan = 4,
401 .ao_ability = 1,
402 .ao_n_chan = 4,
403 .range_ai = &range_ai_das1802,
404 },
405 {
406 .name = "das-1802hr",
407 .ai_speed = 10000,
408 .resolution = 16,
409 .qram_len = 256,
410 .common = 1,
411 .do_n_chan = 4,
412 .ao_ability = 0,
413 .ao_n_chan = 0,
414 .range_ai = &range_ai_das1802,
415 },
416 {
417 .name = "das-1802hr-da",
418 .ai_speed = 10000,
419 .resolution = 16,
420 .qram_len = 256,
421 .common = 1,
422 .do_n_chan = 4,
423 .ao_ability = 1,
424 .ao_n_chan = 2,
425 .range_ai = &range_ai_das1802,
426 },
427 {
428 .name = "das-1801hc",
429 .ai_speed = 3000,
430 .resolution = 12,
431 .qram_len = 64,
432 .common = 0,
433 .do_n_chan = 8,
434 .ao_ability = 1,
435 .ao_n_chan = 2,
436 .range_ai = &range_ai_das1801,
437 },
438 {
439 .name = "das-1802hc",
440 .ai_speed = 3000,
441 .resolution = 12,
442 .qram_len = 64,
443 .common = 0,
444 .do_n_chan = 8,
445 .ao_ability = 1,
446 .ao_n_chan = 2,
447 .range_ai = &range_ai_das1802,
448 },
449 {
450 .name = "das-1801ao",
451 .ai_speed = 3000,
452 .resolution = 12,
453 .qram_len = 256,
454 .common = 1,
455 .do_n_chan = 4,
456 .ao_ability = 2,
457 .ao_n_chan = 2,
458 .range_ai = &range_ai_das1801,
459 },
460 {
461 .name = "das-1802ao",
462 .ai_speed = 3000,
463 .resolution = 12,
464 .qram_len = 256,
465 .common = 1,
466 .do_n_chan = 4,
467 .ao_ability = 2,
468 .ao_n_chan = 2,
469 .range_ai = &range_ai_das1802,
470 },
471};
472
473
474
475
476#define thisboard ((const struct das1800_board *)dev->board_ptr)
477
478struct das1800_private {
479 volatile unsigned int count;
480 unsigned int divisor1;
481 unsigned int divisor2;
482 int do_bits;
483 int irq_dma_bits;
484
485
486 int dma_bits;
487 unsigned int dma0;
488 unsigned int dma1;
489 volatile unsigned int dma_current;
490 uint16_t *ai_buf0;
491 uint16_t *ai_buf1;
492 uint16_t *dma_current_buf;
493 unsigned int dma_transfer_size;
494 unsigned long iobase2;
495 short ao_update_bits;
496};
497
498#define devpriv ((struct das1800_private *)dev->private)
499
500
501static const struct comedi_lrange range_ao_1 = {
502 1,
503 {
504 RANGE(-10, 10),
505 }
506};
507
508
509
510
511
512
513
514
515
516
517
518
519static struct comedi_driver driver_das1800 = {
520 .driver_name = "das1800",
521 .module = THIS_MODULE,
522 .attach = das1800_attach,
523 .detach = das1800_detach,
524 .num_names = ARRAY_SIZE(das1800_boards),
525 .board_name = &das1800_boards[0].name,
526 .offset = sizeof(struct das1800_board),
527};
528
529
530
531
532
533COMEDI_INITCLEANUP(driver_das1800);
534
535static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
536 unsigned int dma1)
537{
538 unsigned long flags;
539
540
541 if (dev->irq && dma0) {
542
543 switch ((dma0 & 0x7) | (dma1 << 4)) {
544 case 0x5:
545 devpriv->dma_bits |= DMA_CH5;
546 break;
547 case 0x6:
548 devpriv->dma_bits |= DMA_CH6;
549 break;
550 case 0x7:
551 devpriv->dma_bits |= DMA_CH7;
552 break;
553 case 0x65:
554 devpriv->dma_bits |= DMA_CH5_CH6;
555 break;
556 case 0x76:
557 devpriv->dma_bits |= DMA_CH6_CH7;
558 break;
559 case 0x57:
560 devpriv->dma_bits |= DMA_CH7_CH5;
561 break;
562 default:
563 printk(" only supports dma channels 5 through 7\n"
564 " Dual dma only allows the following combinations:\n"
565 " dma 5,6 / 6,7 / or 7,5\n");
566 return -EINVAL;
567 break;
568 }
569 if (request_dma(dma0, driver_das1800.driver_name)) {
570 printk(" failed to allocate dma channel %i\n", dma0);
571 return -EINVAL;
572 }
573 devpriv->dma0 = dma0;
574 devpriv->dma_current = dma0;
575 if (dma1) {
576 if (request_dma(dma1, driver_das1800.driver_name)) {
577 printk(" failed to allocate dma channel %i\n",
578 dma1);
579 return -EINVAL;
580 }
581 devpriv->dma1 = dma1;
582 }
583 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
584 if (devpriv->ai_buf0 == NULL)
585 return -ENOMEM;
586 devpriv->dma_current_buf = devpriv->ai_buf0;
587 if (dma1) {
588 devpriv->ai_buf1 =
589 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
590 if (devpriv->ai_buf1 == NULL)
591 return -ENOMEM;
592 }
593 flags = claim_dma_lock();
594 disable_dma(devpriv->dma0);
595 set_dma_mode(devpriv->dma0, DMA_MODE_READ);
596 if (dma1) {
597 disable_dma(devpriv->dma1);
598 set_dma_mode(devpriv->dma1, DMA_MODE_READ);
599 }
600 release_dma_lock(flags);
601 }
602 return 0;
603}
604
605static int das1800_attach(struct comedi_device *dev,
606 struct comedi_devconfig *it)
607{
608 struct comedi_subdevice *s;
609 unsigned long iobase = it->options[0];
610 unsigned int irq = it->options[1];
611 unsigned int dma0 = it->options[2];
612 unsigned int dma1 = it->options[3];
613 unsigned long iobase2;
614 int board;
615 int retval;
616
617
618 if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
619 return -ENOMEM;
620
621 printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
622 iobase);
623 if (irq) {
624 printk(", irq %u", irq);
625 if (dma0) {
626 printk(", dma %u", dma0);
627 if (dma1)
628 printk(" and %u", dma1);
629 }
630 }
631 printk("\n");
632
633 if (iobase == 0) {
634 printk(" io base address required\n");
635 return -EINVAL;
636 }
637
638
639 if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
640 printk
641 (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
642 iobase, iobase + DAS1800_SIZE - 1);
643 return -EIO;
644 }
645 dev->iobase = iobase;
646
647 board = das1800_probe(dev);
648 if (board < 0) {
649 printk(" unable to determine board type\n");
650 return -ENODEV;
651 }
652
653 dev->board_ptr = das1800_boards + board;
654 dev->board_name = thisboard->name;
655
656
657 if (thisboard->ao_ability == 2) {
658 iobase2 = iobase + IOBASE2;
659 if (!request_region(iobase2, DAS1800_SIZE,
660 driver_das1800.driver_name)) {
661 printk
662 (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
663 iobase2, iobase2 + DAS1800_SIZE - 1);
664 return -EIO;
665 }
666 devpriv->iobase2 = iobase2;
667 }
668
669
670 if (irq) {
671 if (request_irq(irq, das1800_interrupt, 0,
672 driver_das1800.driver_name, dev)) {
673 printk(" unable to allocate irq %u\n", irq);
674 return -EINVAL;
675 }
676 }
677 dev->irq = irq;
678
679
680 switch (irq) {
681 case 0:
682 break;
683 case 3:
684 devpriv->irq_dma_bits |= 0x8;
685 break;
686 case 5:
687 devpriv->irq_dma_bits |= 0x10;
688 break;
689 case 7:
690 devpriv->irq_dma_bits |= 0x18;
691 break;
692 case 10:
693 devpriv->irq_dma_bits |= 0x28;
694 break;
695 case 11:
696 devpriv->irq_dma_bits |= 0x30;
697 break;
698 case 15:
699 devpriv->irq_dma_bits |= 0x38;
700 break;
701 default:
702 printk(" irq out of range\n");
703 return -EINVAL;
704 break;
705 }
706
707 retval = das1800_init_dma(dev, dma0, dma1);
708 if (retval < 0)
709 return retval;
710
711 if (devpriv->ai_buf0 == NULL) {
712 devpriv->ai_buf0 =
713 kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
714 if (devpriv->ai_buf0 == NULL)
715 return -ENOMEM;
716 }
717
718 if (alloc_subdevices(dev, 4) < 0)
719 return -ENOMEM;
720
721
722 s = dev->subdevices + 0;
723 dev->read_subdev = s;
724 s->type = COMEDI_SUBD_AI;
725 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
726 if (thisboard->common)
727 s->subdev_flags |= SDF_COMMON;
728 s->n_chan = thisboard->qram_len;
729 s->len_chanlist = thisboard->qram_len;
730 s->maxdata = (1 << thisboard->resolution) - 1;
731 s->range_table = thisboard->range_ai;
732 s->do_cmd = das1800_ai_do_cmd;
733 s->do_cmdtest = das1800_ai_do_cmdtest;
734 s->insn_read = das1800_ai_rinsn;
735 s->poll = das1800_ai_poll;
736 s->cancel = das1800_cancel;
737
738
739 s = dev->subdevices + 1;
740 if (thisboard->ao_ability == 1) {
741 s->type = COMEDI_SUBD_AO;
742 s->subdev_flags = SDF_WRITABLE;
743 s->n_chan = thisboard->ao_n_chan;
744 s->maxdata = (1 << thisboard->resolution) - 1;
745 s->range_table = &range_ao_1;
746 s->insn_write = das1800_ao_winsn;
747 } else {
748 s->type = COMEDI_SUBD_UNUSED;
749 }
750
751
752 s = dev->subdevices + 2;
753 s->type = COMEDI_SUBD_DI;
754 s->subdev_flags = SDF_READABLE;
755 s->n_chan = 4;
756 s->maxdata = 1;
757 s->range_table = &range_digital;
758 s->insn_bits = das1800_di_rbits;
759
760
761 s = dev->subdevices + 3;
762 s->type = COMEDI_SUBD_DO;
763 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
764 s->n_chan = thisboard->do_n_chan;
765 s->maxdata = 1;
766 s->range_table = &range_digital;
767 s->insn_bits = das1800_do_wbits;
768
769 das1800_cancel(dev, dev->read_subdev);
770
771
772 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
773
774
775 if (thisboard->ao_ability == 1) {
776
777 outb(DAC(thisboard->ao_n_chan - 1),
778 dev->iobase + DAS1800_SELECT);
779 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
780 }
781
782 return 0;
783};
784
785static int das1800_detach(struct comedi_device *dev)
786{
787
788 if (dev->iobase)
789 release_region(dev->iobase, DAS1800_SIZE);
790 if (dev->irq)
791 free_irq(dev->irq, dev);
792 if (dev->private) {
793 if (devpriv->iobase2)
794 release_region(devpriv->iobase2, DAS1800_SIZE);
795 if (devpriv->dma0)
796 free_dma(devpriv->dma0);
797 if (devpriv->dma1)
798 free_dma(devpriv->dma1);
799 if (devpriv->ai_buf0)
800 kfree(devpriv->ai_buf0);
801 if (devpriv->ai_buf1)
802 kfree(devpriv->ai_buf1);
803 }
804
805 printk("comedi%d: %s: remove\n", dev->minor,
806 driver_das1800.driver_name);
807
808 return 0;
809};
810
811
812
813static int das1800_probe(struct comedi_device *dev)
814{
815 int id;
816 int board;
817
818 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
819 board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
820
821 switch (id) {
822 case 0x3:
823 if (board == das1801st_da || board == das1802st_da ||
824 board == das1701st_da || board == das1702st_da) {
825 printk(" Board model: %s\n",
826 das1800_boards[board].name);
827 return board;
828 }
829 printk
830 (" Board model (probed, not recommended): das-1800st-da series\n");
831 return das1801st;
832 break;
833 case 0x4:
834 if (board == das1802hr_da || board == das1702hr_da) {
835 printk(" Board model: %s\n",
836 das1800_boards[board].name);
837 return board;
838 }
839 printk
840 (" Board model (probed, not recommended): das-1802hr-da\n");
841 return das1802hr;
842 break;
843 case 0x5:
844 if (board == das1801ao || board == das1802ao ||
845 board == das1701ao || board == das1702ao) {
846 printk(" Board model: %s\n",
847 das1800_boards[board].name);
848 return board;
849 }
850 printk
851 (" Board model (probed, not recommended): das-1800ao series\n");
852 return das1801ao;
853 break;
854 case 0x6:
855 if (board == das1802hr || board == das1702hr) {
856 printk(" Board model: %s\n",
857 das1800_boards[board].name);
858 return board;
859 }
860 printk(" Board model (probed, not recommended): das-1802hr\n");
861 return das1802hr;
862 break;
863 case 0x7:
864 if (board == das1801st || board == das1802st ||
865 board == das1701st || board == das1702st) {
866 printk(" Board model: %s\n",
867 das1800_boards[board].name);
868 return board;
869 }
870 printk
871 (" Board model (probed, not recommended): das-1800st series\n");
872 return das1801st;
873 break;
874 case 0x8:
875 if (board == das1801hc || board == das1802hc) {
876 printk(" Board model: %s\n",
877 das1800_boards[board].name);
878 return board;
879 }
880 printk
881 (" Board model (probed, not recommended): das-1800hc series\n");
882 return das1801hc;
883 break;
884 default:
885 printk
886 (" Board model: probe returned 0x%x (unknown, please report)\n",
887 id);
888 return board;
889 break;
890 }
891 return -1;
892}
893
894static int das1800_ai_poll(struct comedi_device *dev,
895 struct comedi_subdevice *s)
896{
897 unsigned long flags;
898
899
900 spin_lock_irqsave(&dev->spinlock, flags);
901 das1800_ai_handler(dev);
902 spin_unlock_irqrestore(&dev->spinlock, flags);
903
904 return s->async->buf_write_count - s->async->buf_read_count;
905}
906
907static irqreturn_t das1800_interrupt(int irq, void *d)
908{
909 struct comedi_device *dev = d;
910 unsigned int status;
911
912 if (dev->attached == 0) {
913 comedi_error(dev, "premature interrupt");
914 return IRQ_HANDLED;
915 }
916
917
918
919 spin_lock(&dev->spinlock);
920 status = inb(dev->iobase + DAS1800_STATUS);
921
922
923 if (!(status & INT)) {
924 spin_unlock(&dev->spinlock);
925 return IRQ_NONE;
926 }
927
928 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
929
930 das1800_ai_handler(dev);
931
932 spin_unlock(&dev->spinlock);
933 return IRQ_HANDLED;
934}
935
936
937static void das1800_ai_handler(struct comedi_device *dev)
938{
939 struct comedi_subdevice *s = dev->subdevices + 0;
940 struct comedi_async *async = s->async;
941 struct comedi_cmd *cmd = &async->cmd;
942 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
943
944 async->events = 0;
945
946 outb(ADC, dev->iobase + DAS1800_SELECT);
947
948 if (devpriv->irq_dma_bits & DMA_ENABLED) {
949
950 das1800_handle_dma(dev, s, status);
951 } else if (status & FHF) {
952 das1800_handle_fifo_half_full(dev, s);
953 } else if (status & FNE) {
954 das1800_handle_fifo_not_empty(dev, s);
955 }
956
957 async->events |= COMEDI_CB_BLOCK;
958
959 if (status & OVF) {
960
961 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
962 comedi_error(dev, "DAS1800 FIFO overflow");
963 das1800_cancel(dev, s);
964 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
965 comedi_event(dev, s);
966 return;
967 }
968
969
970 if (status & CT0TC) {
971
972 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
973
974 if (devpriv->irq_dma_bits & DMA_ENABLED)
975 das1800_flush_dma(dev, s);
976 else
977 das1800_handle_fifo_not_empty(dev, s);
978 das1800_cancel(dev, s);
979 async->events |= COMEDI_CB_EOA;
980 } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {
981 das1800_cancel(dev, s);
982 async->events |= COMEDI_CB_EOA;
983 }
984
985 comedi_event(dev, s);
986
987 return;
988}
989
990static void das1800_handle_dma(struct comedi_device *dev,
991 struct comedi_subdevice *s, unsigned int status)
992{
993 unsigned long flags;
994 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
995
996 flags = claim_dma_lock();
997 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
998 devpriv->dma_current_buf);
999
1000 set_dma_addr(devpriv->dma_current,
1001 virt_to_bus(devpriv->dma_current_buf));
1002 set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
1003 enable_dma(devpriv->dma_current);
1004 release_dma_lock(flags);
1005
1006 if (status & DMATC) {
1007
1008 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
1009
1010 if (dual_dma) {
1011
1012 if (devpriv->dma_current == devpriv->dma0) {
1013 devpriv->dma_current = devpriv->dma1;
1014 devpriv->dma_current_buf = devpriv->ai_buf1;
1015 } else {
1016 devpriv->dma_current = devpriv->dma0;
1017 devpriv->dma_current_buf = devpriv->ai_buf0;
1018 }
1019 }
1020 }
1021
1022 return;
1023}
1024
1025static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
1026 uint16_t sample)
1027{
1028 sample += 1 << (thisboard->resolution - 1);
1029 return sample;
1030}
1031
1032static void munge_data(struct comedi_device *dev, uint16_t * array,
1033 unsigned int num_elements)
1034{
1035 unsigned int i;
1036 int unipolar;
1037
1038
1039 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1040
1041
1042 if (!unipolar) {
1043 for (i = 0; i < num_elements; i++) {
1044 array[i] = munge_bipolar_sample(dev, array[i]);
1045 }
1046 }
1047}
1048
1049
1050
1051static void das1800_flush_dma_channel(struct comedi_device *dev,
1052 struct comedi_subdevice *s,
1053 unsigned int channel, uint16_t * buffer)
1054{
1055 unsigned int num_bytes, num_samples;
1056 struct comedi_cmd *cmd = &s->async->cmd;
1057
1058 disable_dma(channel);
1059
1060
1061
1062 clear_dma_ff(channel);
1063
1064
1065 num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1066 num_samples = num_bytes / sizeof(short);
1067
1068
1069 if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1070 num_samples = devpriv->count;
1071
1072 munge_data(dev, buffer, num_samples);
1073 cfc_write_array_to_buffer(s, buffer, num_bytes);
1074 if (s->async->cmd.stop_src == TRIG_COUNT)
1075 devpriv->count -= num_samples;
1076
1077 return;
1078}
1079
1080
1081
1082static void das1800_flush_dma(struct comedi_device *dev,
1083 struct comedi_subdevice *s)
1084{
1085 unsigned long flags;
1086 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1087
1088 flags = claim_dma_lock();
1089 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1090 devpriv->dma_current_buf);
1091
1092 if (dual_dma) {
1093
1094 if (devpriv->dma_current == devpriv->dma0) {
1095 devpriv->dma_current = devpriv->dma1;
1096 devpriv->dma_current_buf = devpriv->ai_buf1;
1097 } else {
1098 devpriv->dma_current = devpriv->dma0;
1099 devpriv->dma_current_buf = devpriv->ai_buf0;
1100 }
1101 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1102 devpriv->dma_current_buf);
1103 }
1104
1105 release_dma_lock(flags);
1106
1107
1108 das1800_handle_fifo_not_empty(dev, s);
1109
1110 return;
1111}
1112
1113static void das1800_handle_fifo_half_full(struct comedi_device *dev,
1114 struct comedi_subdevice *s)
1115{
1116 int numPoints = 0;
1117 struct comedi_cmd *cmd = &s->async->cmd;
1118
1119 numPoints = FIFO_SIZE / 2;
1120
1121 if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1122 numPoints = devpriv->count;
1123 insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1124 munge_data(dev, devpriv->ai_buf0, numPoints);
1125 cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1126 numPoints * sizeof(devpriv->ai_buf0[0]));
1127 if (cmd->stop_src == TRIG_COUNT)
1128 devpriv->count -= numPoints;
1129 return;
1130}
1131
1132static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
1133 struct comedi_subdevice *s)
1134{
1135 short dpnt;
1136 int unipolar;
1137 struct comedi_cmd *cmd = &s->async->cmd;
1138
1139 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1140
1141 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1142 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1143 break;
1144 dpnt = inw(dev->iobase + DAS1800_FIFO);
1145
1146 if (!unipolar) ;
1147 dpnt = munge_bipolar_sample(dev, dpnt);
1148 cfc_write_to_buffer(s, dpnt);
1149 if (cmd->stop_src == TRIG_COUNT)
1150 devpriv->count--;
1151 }
1152
1153 return;
1154}
1155
1156static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1157{
1158 outb(0x0, dev->iobase + DAS1800_STATUS);
1159 outb(0x0, dev->iobase + DAS1800_CONTROL_B);
1160 outb(0x0, dev->iobase + DAS1800_CONTROL_A);
1161 if (devpriv->dma0)
1162 disable_dma(devpriv->dma0);
1163 if (devpriv->dma1)
1164 disable_dma(devpriv->dma1);
1165 return 0;
1166}
1167
1168
1169static int das1800_ai_do_cmdtest(struct comedi_device *dev,
1170 struct comedi_subdevice *s,
1171 struct comedi_cmd *cmd)
1172{
1173 int err = 0;
1174 int tmp;
1175 unsigned int tmp_arg;
1176 int i;
1177 int unipolar;
1178
1179
1180
1181 tmp = cmd->start_src;
1182 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1183 if (!cmd->start_src || tmp != cmd->start_src)
1184 err++;
1185
1186 tmp = cmd->scan_begin_src;
1187 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1188 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1189 err++;
1190
1191 tmp = cmd->convert_src;
1192 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1193 if (!cmd->convert_src || tmp != cmd->convert_src)
1194 err++;
1195
1196 tmp = cmd->scan_end_src;
1197 cmd->scan_end_src &= TRIG_COUNT;
1198 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1199 err++;
1200
1201 tmp = cmd->stop_src;
1202 cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1203 if (!cmd->stop_src || tmp != cmd->stop_src)
1204 err++;
1205
1206 if (err)
1207 return 1;
1208
1209
1210
1211
1212 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1213 err++;
1214 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1215 cmd->scan_begin_src != TRIG_TIMER &&
1216 cmd->scan_begin_src != TRIG_EXT)
1217 err++;
1218 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1219 err++;
1220 if (cmd->stop_src != TRIG_COUNT &&
1221 cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1222 err++;
1223
1224 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1225 cmd->convert_src != TRIG_TIMER)
1226 err++;
1227
1228 if (err)
1229 return 2;
1230
1231
1232
1233 if (cmd->start_arg != 0) {
1234 cmd->start_arg = 0;
1235 err++;
1236 }
1237 if (cmd->convert_src == TRIG_TIMER) {
1238 if (cmd->convert_arg < thisboard->ai_speed) {
1239 cmd->convert_arg = thisboard->ai_speed;
1240 err++;
1241 }
1242 }
1243 if (!cmd->chanlist_len) {
1244 cmd->chanlist_len = 1;
1245 err++;
1246 }
1247 if (cmd->scan_end_arg != cmd->chanlist_len) {
1248 cmd->scan_end_arg = cmd->chanlist_len;
1249 err++;
1250 }
1251
1252 switch (cmd->stop_src) {
1253 case TRIG_COUNT:
1254 if (!cmd->stop_arg) {
1255 cmd->stop_arg = 1;
1256 err++;
1257 }
1258 break;
1259 case TRIG_NONE:
1260 if (cmd->stop_arg != 0) {
1261 cmd->stop_arg = 0;
1262 err++;
1263 }
1264 break;
1265 default:
1266 break;
1267 }
1268
1269 if (err)
1270 return 3;
1271
1272
1273
1274 if (cmd->convert_src == TRIG_TIMER) {
1275
1276 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1277 tmp_arg = cmd->convert_arg;
1278
1279 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1280 &(devpriv->divisor1),
1281 &(devpriv->divisor2),
1282 &(cmd->convert_arg),
1283 cmd->
1284 flags & TRIG_ROUND_MASK);
1285 if (tmp_arg != cmd->convert_arg)
1286 err++;
1287 }
1288
1289 else {
1290
1291 tmp_arg = cmd->convert_arg;
1292 cmd->convert_arg =
1293 burst_convert_arg(cmd->convert_arg,
1294 cmd->flags & TRIG_ROUND_MASK);
1295 if (tmp_arg != cmd->convert_arg)
1296 err++;
1297
1298 if (cmd->scan_begin_src == TRIG_TIMER) {
1299
1300 if (cmd->convert_arg * cmd->chanlist_len >
1301 cmd->scan_begin_arg) {
1302 cmd->scan_begin_arg =
1303 cmd->convert_arg *
1304 cmd->chanlist_len;
1305 err++;
1306 }
1307 tmp_arg = cmd->scan_begin_arg;
1308
1309 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1310 &(devpriv->
1311 divisor1),
1312 &(devpriv->
1313 divisor2),
1314 &(cmd->
1315 scan_begin_arg),
1316 cmd->
1317 flags &
1318 TRIG_ROUND_MASK);
1319 if (tmp_arg != cmd->scan_begin_arg)
1320 err++;
1321 }
1322 }
1323 }
1324
1325 if (err)
1326 return 4;
1327
1328
1329 if (cmd->chanlist) {
1330 unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1331 for (i = 1; i < cmd->chanlist_len; i++) {
1332 if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1333 comedi_error(dev,
1334 "unipolar and bipolar ranges cannot be mixed in the chanlist");
1335 err++;
1336 break;
1337 }
1338 }
1339 }
1340
1341 if (err)
1342 return 5;
1343
1344 return 0;
1345}
1346
1347
1348
1349
1350
1351
1352static int control_a_bits(struct comedi_cmd cmd)
1353{
1354 int control_a;
1355
1356 control_a = FFEN;
1357 if (cmd.stop_src == TRIG_EXT) {
1358 control_a |= ATEN;
1359 }
1360 switch (cmd.start_src) {
1361 case TRIG_EXT:
1362 control_a |= TGEN | CGSL;
1363 break;
1364 case TRIG_NOW:
1365 control_a |= CGEN;
1366 break;
1367 default:
1368 break;
1369 }
1370
1371 return control_a;
1372}
1373
1374
1375static int control_c_bits(struct comedi_cmd cmd)
1376{
1377 int control_c;
1378 int aref;
1379
1380
1381
1382
1383 aref = CR_AREF(cmd.chanlist[0]);
1384 control_c = UQEN;
1385 if (aref != AREF_DIFF)
1386 control_c |= SD;
1387 if (aref == AREF_COMMON)
1388 control_c |= CMEN;
1389
1390 if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1391 control_c |= UB;
1392 switch (cmd.scan_begin_src) {
1393 case TRIG_FOLLOW:
1394 switch (cmd.convert_src) {
1395 case TRIG_TIMER:
1396
1397 control_c |= IPCLK;
1398 break;
1399 case TRIG_EXT:
1400
1401 control_c |= XPCLK;
1402 break;
1403 default:
1404 break;
1405 }
1406 break;
1407 case TRIG_TIMER:
1408
1409 control_c |= BMDE | IPCLK;
1410 break;
1411 case TRIG_EXT:
1412
1413 control_c |= BMDE | XPCLK;
1414 break;
1415 default:
1416 break;
1417 }
1418
1419 return control_c;
1420}
1421
1422
1423static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
1424{
1425
1426 switch (cmd.scan_begin_src) {
1427 case TRIG_FOLLOW:
1428 if (cmd.convert_src == TRIG_TIMER) {
1429
1430 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1431 &(devpriv->divisor1),
1432 &(devpriv->divisor2),
1433 &(cmd.convert_arg),
1434 cmd.
1435 flags & TRIG_ROUND_MASK);
1436 if (das1800_set_frequency(dev) < 0) {
1437 return -1;
1438 }
1439 }
1440 break;
1441 case TRIG_TIMER:
1442
1443 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1444 &(devpriv->divisor2),
1445 &(cmd.scan_begin_arg),
1446 cmd.flags & TRIG_ROUND_MASK);
1447 if (das1800_set_frequency(dev) < 0) {
1448 return -1;
1449 }
1450 break;
1451 default:
1452 break;
1453 }
1454
1455
1456 if (cmd.stop_src == TRIG_EXT) {
1457
1458 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1459 }
1460
1461 return 0;
1462}
1463
1464
1465static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
1466{
1467 unsigned long lock_flags;
1468 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1469
1470 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1471 return;
1472
1473
1474 devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1475 lock_flags = claim_dma_lock();
1476 disable_dma(devpriv->dma0);
1477
1478
1479 clear_dma_ff(devpriv->dma0);
1480 set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1481
1482 set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1483 devpriv->dma_current = devpriv->dma0;
1484 devpriv->dma_current_buf = devpriv->ai_buf0;
1485 enable_dma(devpriv->dma0);
1486
1487 if (dual_dma) {
1488 disable_dma(devpriv->dma1);
1489
1490
1491 clear_dma_ff(devpriv->dma1);
1492 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1493
1494 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1495 enable_dma(devpriv->dma1);
1496 }
1497 release_dma_lock(lock_flags);
1498
1499 return;
1500}
1501
1502
1503static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
1504{
1505 int i, n, chan_range;
1506 unsigned long irq_flags;
1507 const int range_mask = 0x3;
1508 const int range_bitshift = 8;
1509
1510 n = cmd.chanlist_len;
1511
1512 spin_lock_irqsave(&dev->spinlock, irq_flags);
1513 outb(QRAM, dev->iobase + DAS1800_SELECT);
1514 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
1515
1516 for (i = 0; i < n; i++) {
1517 chan_range =
1518 CR_CHAN(cmd.
1519 chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) &
1520 range_mask) << range_bitshift);
1521 outw(chan_range, dev->iobase + DAS1800_QRAM);
1522 }
1523 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
1524 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1525
1526 return;
1527}
1528
1529
1530static int das1800_ai_do_cmd(struct comedi_device *dev,
1531 struct comedi_subdevice *s)
1532{
1533 int ret;
1534 int control_a, control_c;
1535 struct comedi_async *async = s->async;
1536 struct comedi_cmd cmd = async->cmd;
1537
1538 if (!dev->irq) {
1539 comedi_error(dev,
1540 "no irq assigned for das-1800, cannot do hardware conversions");
1541 return -1;
1542 }
1543
1544
1545
1546 if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1547 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1548 } else {
1549 devpriv->irq_dma_bits |= devpriv->dma_bits;
1550 }
1551
1552 if (cmd.flags & TRIG_WAKE_EOS) {
1553
1554 devpriv->irq_dma_bits &= ~FIMD;
1555 } else {
1556
1557 devpriv->irq_dma_bits |= FIMD;
1558 }
1559
1560 if (cmd.stop_src == TRIG_COUNT) {
1561 devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1562 }
1563
1564 das1800_cancel(dev, s);
1565
1566
1567 control_a = control_a_bits(cmd);
1568 control_c = control_c_bits(cmd);
1569
1570
1571 program_chanlist(dev, cmd);
1572 ret = setup_counters(dev, cmd);
1573 if (ret < 0) {
1574 comedi_error(dev, "Error setting up counters");
1575 return ret;
1576 }
1577 setup_dma(dev, cmd);
1578 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1579
1580 if (control_c & BMDE) {
1581
1582 outb(cmd.convert_arg / 1000 - 1,
1583 dev->iobase + DAS1800_BURST_RATE);
1584 outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1585 }
1586 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);
1587 outb(control_a, dev->iobase + DAS1800_CONTROL_A);
1588 outb(CVEN, dev->iobase + DAS1800_STATUS);
1589
1590 return 0;
1591}
1592
1593
1594static int das1800_ai_rinsn(struct comedi_device *dev,
1595 struct comedi_subdevice *s,
1596 struct comedi_insn *insn, unsigned int *data)
1597{
1598 int i, n;
1599 int chan, range, aref, chan_range;
1600 int timeout = 1000;
1601 short dpnt;
1602 int conv_flags = 0;
1603 unsigned long irq_flags;
1604
1605
1606 aref = CR_AREF(insn->chanspec);
1607 conv_flags |= UQEN;
1608 if (aref != AREF_DIFF)
1609 conv_flags |= SD;
1610 if (aref == AREF_COMMON)
1611 conv_flags |= CMEN;
1612
1613 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1614 conv_flags |= UB;
1615
1616 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);
1617 outb(CVEN, dev->iobase + DAS1800_STATUS);
1618 outb(0x0, dev->iobase + DAS1800_CONTROL_A);
1619 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1620
1621 chan = CR_CHAN(insn->chanspec);
1622
1623 range = CR_RANGE(insn->chanspec) & 0x3;
1624 chan_range = chan | (range << 8);
1625 spin_lock_irqsave(&dev->spinlock, irq_flags);
1626 outb(QRAM, dev->iobase + DAS1800_SELECT);
1627 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);
1628 outw(chan_range, dev->iobase + DAS1800_QRAM);
1629 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);
1630 outb(ADC, dev->iobase + DAS1800_SELECT);
1631
1632 for (n = 0; n < insn->n; n++) {
1633
1634 outb(0, dev->iobase + DAS1800_FIFO);
1635 for (i = 0; i < timeout; i++) {
1636 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1637 break;
1638 }
1639 if (i == timeout) {
1640 comedi_error(dev, "timeout");
1641 return -ETIME;
1642 }
1643 dpnt = inw(dev->iobase + DAS1800_FIFO);
1644
1645 if ((conv_flags & UB) == 0)
1646 dpnt += 1 << (thisboard->resolution - 1);
1647 data[n] = dpnt;
1648 }
1649 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1650
1651 return n;
1652}
1653
1654
1655static int das1800_ao_winsn(struct comedi_device *dev,
1656 struct comedi_subdevice *s,
1657 struct comedi_insn *insn, unsigned int *data)
1658{
1659 int chan = CR_CHAN(insn->chanspec);
1660
1661 int update_chan = thisboard->ao_n_chan - 1;
1662 short output;
1663 unsigned long irq_flags;
1664
1665
1666 output = data[0] - (1 << (thisboard->resolution - 1));
1667
1668 if (chan == update_chan)
1669 devpriv->ao_update_bits = output;
1670
1671 spin_lock_irqsave(&dev->spinlock, irq_flags);
1672 outb(DAC(chan), dev->iobase + DAS1800_SELECT);
1673 outw(output, dev->iobase + DAS1800_DAC);
1674
1675 if (chan != update_chan) {
1676 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);
1677 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1678 }
1679 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1680
1681 return 1;
1682}
1683
1684
1685static int das1800_di_rbits(struct comedi_device *dev,
1686 struct comedi_subdevice *s,
1687 struct comedi_insn *insn, unsigned int *data)
1688{
1689
1690 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1691 data[0] = 0;
1692
1693 return 2;
1694}
1695
1696
1697static int das1800_do_wbits(struct comedi_device *dev,
1698 struct comedi_subdevice *s,
1699 struct comedi_insn *insn, unsigned int *data)
1700{
1701 unsigned int wbits;
1702
1703
1704 data[0] &= (1 << s->n_chan) - 1;
1705 wbits = devpriv->do_bits;
1706 wbits &= ~data[0];
1707 wbits |= data[0] & data[1];
1708 devpriv->do_bits = wbits;
1709
1710 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1711
1712 data[1] = devpriv->do_bits;
1713
1714 return 2;
1715}
1716
1717
1718static int das1800_set_frequency(struct comedi_device *dev)
1719{
1720 int err = 0;
1721
1722
1723 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1724 2))
1725 err++;
1726
1727 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1728 2))
1729 err++;
1730 if (err)
1731 return -1;
1732
1733 return 0;
1734}
1735
1736
1737
1738
1739static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1740{
1741 unsigned int micro_sec;
1742
1743
1744 if (convert_arg > 64000)
1745 convert_arg = 64000;
1746
1747
1748 switch (round_mode) {
1749 case TRIG_ROUND_NEAREST:
1750 default:
1751 micro_sec = (convert_arg + 500) / 1000;
1752 break;
1753 case TRIG_ROUND_DOWN:
1754 micro_sec = convert_arg / 1000;
1755 break;
1756 case TRIG_ROUND_UP:
1757 micro_sec = (convert_arg - 1) / 1000 + 1;
1758 break;
1759 }
1760
1761
1762 return micro_sec * 1000;
1763}
1764
1765
1766static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
1767{
1768 unsigned int size = DMA_BUF_SIZE;
1769 static const int sample_size = 2;
1770 unsigned int fill_time = 300000000;
1771 unsigned int max_size;
1772
1773
1774 switch (cmd->scan_begin_src) {
1775 case TRIG_FOLLOW:
1776 if (cmd->convert_src == TRIG_TIMER)
1777 size = (fill_time / cmd->convert_arg) * sample_size;
1778 break;
1779 case TRIG_TIMER:
1780 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1781 sample_size;
1782 break;
1783 default:
1784 size = DMA_BUF_SIZE;
1785 break;
1786 }
1787
1788
1789 max_size = DMA_BUF_SIZE;
1790
1791 if (cmd->stop_src == TRIG_COUNT &&
1792 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1793 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1794
1795 if (size > max_size)
1796 size = max_size;
1797 if (size < sample_size)
1798 size = sample_size;
1799
1800 return size;
1801}
1802