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#include "hwdrv_apci3120.h"
48static unsigned int ui_Temp;
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
77int i_APCI3120_InsnConfigAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
78 struct comedi_insn *insn, unsigned int *data)
79{
80 unsigned int i;
81
82 if ((data[0] != APCI3120_EOC_MODE) && (data[0] != APCI3120_EOS_MODE))
83 return -1;
84
85
86 devpriv->ui_EocEosConversionTime = data[2];
87
88 if (data[0] == APCI3120_EOS_MODE) {
89
90
91 for (i = 0; i < data[3]; i++) {
92
93 if (CR_CHAN(data[4 + i]) >= this_board->i_NbrAiChannel) {
94 printk("bad channel list\n");
95 return -2;
96 }
97 }
98
99 devpriv->b_InterruptMode = APCI3120_EOS_MODE;
100
101 if (data[1])
102 devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
103 else
104 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
105
106
107 devpriv->ui_AiNbrofChannels = data[3];
108 for (i = 0; i < devpriv->ui_AiNbrofChannels; i++)
109 devpriv->ui_AiChannelList[i] = data[4 + i];
110
111 } else {
112 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
113 if (data[1])
114 devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
115 else
116 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
117 }
118
119 return insn->n;
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
145int i_APCI3120_InsnReadAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
146 struct comedi_insn *insn, unsigned int *data)
147{
148 unsigned short us_ConvertTiming, us_TmpValue, i;
149 unsigned char b_Tmp;
150
151
152 if (!devpriv->ui_EocEosConversionTime) {
153 printk("No timer0 Value using 10 us\n");
154 us_ConvertTiming = 10;
155 } else
156 us_ConvertTiming = (unsigned short) (devpriv->ui_EocEosConversionTime / 1000);
157
158
159
160
161 devpriv->b_TimerSelectMode = 0;
162 devpriv->b_ModeSelectRegister = 0;
163 devpriv->us_OutputRegister = 0;
164
165
166 if (insn->unused[0] == 222) {
167 for (i = 0; i < insn->n; i++)
168 data[i] = devpriv->ui_AiReadData[i];
169 } else {
170 devpriv->tsk_Current = current;
171
172
173
174
175
176 us_TmpValue =
177 (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
178
179
180 if ((us_TmpValue & 0x00B0) == 0x00B0
181 || !strcmp(this_board->pc_DriverName, "apci3001")) {
182 us_ConvertTiming = (us_ConvertTiming * 2) - 2;
183 } else {
184 us_ConvertTiming =
185 ((us_ConvertTiming * 12926) / 10000) - 1;
186 }
187
188 us_TmpValue = (unsigned short) devpriv->b_InterruptMode;
189
190 switch (us_TmpValue) {
191
192 case APCI3120_EOC_MODE:
193
194
195
196
197 inw(devpriv->iobase + APCI3120_RESET_FIFO);
198
199
200
201
202
203 if (!i_APCI3120_SetupChannelList(dev, s, 1,
204 &insn->chanspec, 0))
205 return -EINVAL;
206
207
208 devpriv->b_TimerSelectMode =
209 (devpriv->
210 b_TimerSelectMode & 0xFC) |
211 APCI3120_TIMER_0_MODE_4;
212 outb(devpriv->b_TimerSelectMode,
213 devpriv->iobase + APCI3120_TIMER_CRT1);
214
215
216 devpriv->b_ModeSelectRegister =
217 devpriv->
218 b_ModeSelectRegister & APCI3120_DISABLE_SCAN;
219
220 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
221
222
223 devpriv->b_ModeSelectRegister =
224 (devpriv->
225 b_ModeSelectRegister &
226 APCI3120_DISABLE_EOS_INT) |
227 APCI3120_ENABLE_EOC_INT;
228 inw(devpriv->iobase);
229
230 } else {
231 devpriv->b_ModeSelectRegister =
232 devpriv->
233 b_ModeSelectRegister &
234 APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
235 }
236
237 outb(devpriv->b_ModeSelectRegister,
238 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
239
240
241 devpriv->us_OutputRegister =
242 (devpriv->
243 us_OutputRegister & APCI3120_CLEAR_PA_PR) |
244 APCI3120_ENABLE_TIMER0;
245 outw(devpriv->us_OutputRegister,
246 devpriv->iobase + APCI3120_WR_ADDRESS);
247
248
249 b_Tmp = ((devpriv->
250 b_DigitalOutputRegister) & 0xF0) |
251 APCI3120_SELECT_TIMER_0_WORD;
252 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
253
254
255 outw(us_ConvertTiming,
256 devpriv->iobase + APCI3120_TIMER_VALUE);
257
258 us_TmpValue =
259 (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
260
261 if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
262
263 do {
264
265 us_TmpValue =
266 inw(devpriv->iobase +
267 APCI3120_RD_STATUS);
268 } while ((us_TmpValue & APCI3120_EOC) ==
269 APCI3120_EOC);
270
271
272 us_TmpValue = inw(devpriv->iobase + 0);
273 *data = us_TmpValue;
274
275 inw(devpriv->iobase + APCI3120_RESET_FIFO);
276 }
277
278 break;
279
280 case APCI3120_EOS_MODE:
281
282 inw(devpriv->iobase);
283
284 inw(devpriv->iobase + APCI3120_RESET_FIFO);
285
286
287 devpriv->us_OutputRegister =
288 (devpriv->
289 us_OutputRegister & APCI3120_CLEAR_PA_PR) |
290 APCI3120_DISABLE_TIMER0;
291
292 outw(devpriv->us_OutputRegister,
293 devpriv->iobase + APCI3120_WR_ADDRESS);
294
295 if (!i_APCI3120_SetupChannelList(dev, s,
296 devpriv->ui_AiNbrofChannels,
297 devpriv->ui_AiChannelList, 0))
298 return -EINVAL;
299
300
301 devpriv->b_TimerSelectMode =
302 (devpriv->
303 b_TimerSelectMode & 0xFC) |
304 APCI3120_TIMER_0_MODE_2;
305 outb(devpriv->b_TimerSelectMode,
306 devpriv->iobase + APCI3120_TIMER_CRT1);
307
308
309 b_Tmp = ((devpriv->
310 b_DigitalOutputRegister) & 0xF0) |
311 APCI3120_SELECT_TIMER_0_WORD;
312 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
313
314
315 outw(us_ConvertTiming,
316 devpriv->iobase + APCI3120_TIMER_VALUE);
317
318
319 devpriv->b_ModeSelectRegister =
320 devpriv->
321 b_ModeSelectRegister | APCI3120_ENABLE_SCAN;
322 outb(devpriv->b_ModeSelectRegister,
323 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
324
325
326 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
327
328 devpriv->b_ModeSelectRegister =
329 (devpriv->
330 b_ModeSelectRegister &
331 APCI3120_DISABLE_EOC_INT) |
332 APCI3120_ENABLE_EOS_INT;
333 inw(devpriv->iobase);
334
335 } else
336 devpriv->b_ModeSelectRegister =
337 devpriv->
338 b_ModeSelectRegister &
339 APCI3120_DISABLE_ALL_INTERRUPT_WITHOUT_TIMER;
340
341 outb(devpriv->b_ModeSelectRegister,
342 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
343
344 inw(devpriv->iobase + APCI3120_RD_STATUS);
345
346
347
348 devpriv->us_OutputRegister =
349 devpriv->
350 us_OutputRegister | APCI3120_ENABLE_TIMER0;
351 outw(devpriv->us_OutputRegister,
352 devpriv->iobase + APCI3120_WR_ADDRESS);
353
354
355 outw(0, devpriv->iobase + APCI3120_START_CONVERSION);
356
357
358 if (devpriv->b_EocEosInterrupt == APCI3120_DISABLE) {
359
360 do {
361 us_TmpValue =
362 inw(devpriv->iobase +
363 APCI3120_RD_STATUS);
364 } while ((us_TmpValue & APCI3120_EOS) !=
365 APCI3120_EOS);
366
367 for (i = 0; i < devpriv->ui_AiNbrofChannels;
368 i++) {
369
370 us_TmpValue = inw(devpriv->iobase);
371 data[i] = (unsigned int) us_TmpValue;
372 }
373
374 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
375 }
376 break;
377
378 default:
379 printk("inputs wrong\n");
380
381 }
382 devpriv->ui_EocEosConversionTime = 0;
383 }
384
385 return insn->n;
386
387}
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407int i_APCI3120_StopCyclicAcquisition(struct comedi_device *dev, struct comedi_subdevice *s)
408{
409
410 outw(0, devpriv->i_IobaseAddon + 4);
411
412
413 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
414 outw(0, devpriv->i_IobaseAddon + 2);
415 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
416 outw(0, devpriv->i_IobaseAddon + 2);
417
418
419 outl(0, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
420
421
422
423
424
425
426
427
428 i_APCI3120_ExttrigDisable(dev);
429
430 devpriv->us_OutputRegister = 0;
431
432 outw(devpriv->
433 us_OutputRegister & APCI3120_DISABLE_TIMER0 &
434 APCI3120_DISABLE_TIMER1, dev->iobase + APCI3120_WR_ADDRESS);
435
436 outw(APCI3120_DISABLE_ALL_TIMER, dev->iobase + APCI3120_WR_ADDRESS);
437
438
439 outb(APCI3120_DISABLE_ALL_INTERRUPT,
440 dev->iobase + APCI3120_WRITE_MODE_SELECT);
441
442 inb(dev->iobase + APCI3120_RESET_FIFO);
443 inw(dev->iobase + APCI3120_RD_STATUS);
444 devpriv->ui_AiActualScan = 0;
445 devpriv->ui_AiActualScanPosition = 0;
446 s->async->cur_chan = 0;
447 devpriv->ui_AiBufferPtr = 0;
448 devpriv->b_AiContinuous = 0;
449 devpriv->ui_DmaActualBuffer = 0;
450
451 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
452 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
453 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
454 i_APCI3120_Reset(dev);
455 return 0;
456}
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477int i_APCI3120_CommandTestAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s,
478 struct comedi_cmd *cmd)
479{
480 int err = 0;
481 int tmp;
482
483
484
485 tmp = cmd->start_src;
486 cmd->start_src &= TRIG_NOW | TRIG_EXT;
487 if (!cmd->start_src || tmp != cmd->start_src)
488 err++;
489
490 tmp = cmd->scan_begin_src;
491 cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW;
492 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
493 err++;
494
495 tmp = cmd->convert_src;
496 cmd->convert_src &= TRIG_TIMER;
497 if (!cmd->convert_src || tmp != cmd->convert_src)
498 err++;
499
500 tmp = cmd->scan_end_src;
501 cmd->scan_end_src &= TRIG_COUNT;
502 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
503 err++;
504
505 tmp = cmd->stop_src;
506 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
507 if (!cmd->stop_src || tmp != cmd->stop_src)
508 err++;
509
510 if (err)
511 return 1;
512
513
514
515 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
516 err++;
517
518 if (cmd->scan_begin_src != TRIG_TIMER &&
519 cmd->scan_begin_src != TRIG_FOLLOW)
520 err++;
521
522 if (cmd->convert_src != TRIG_TIMER)
523 err++;
524
525 if (cmd->scan_end_src != TRIG_COUNT) {
526 cmd->scan_end_src = TRIG_COUNT;
527 err++;
528 }
529
530 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
531 err++;
532
533 if (err)
534 return 2;
535
536
537
538 if (cmd->start_arg != 0) {
539 cmd->start_arg = 0;
540 err++;
541 }
542
543 if (cmd->scan_begin_src == TRIG_TIMER) {
544 if (cmd->scan_begin_arg < this_board->ui_MinDelaytimeNs) {
545 cmd->scan_begin_arg = this_board->ui_MinDelaytimeNs;
546 err++;
547 }
548 }
549
550 if (cmd->convert_src == TRIG_TIMER) {
551 if (cmd->scan_begin_src == TRIG_TIMER) {
552 if ((cmd->convert_arg)
553 && (cmd->convert_arg <
554 this_board->ui_MinAcquisitiontimeNs)) {
555 cmd->convert_arg =
556 this_board->ui_MinAcquisitiontimeNs;
557 err++;
558 }
559 } else {
560 if (cmd->convert_arg <
561 this_board->ui_MinAcquisitiontimeNs) {
562 cmd->convert_arg =
563 this_board->ui_MinAcquisitiontimeNs;
564 err++;
565
566 }
567 }
568 }
569
570 if (!cmd->chanlist_len) {
571 cmd->chanlist_len = 1;
572 err++;
573 }
574 if (cmd->chanlist_len > this_board->i_AiChannelList) {
575 cmd->chanlist_len = this_board->i_AiChannelList;
576 err++;
577 }
578 if (cmd->stop_src == TRIG_COUNT) {
579 if (!cmd->stop_arg) {
580 cmd->stop_arg = 1;
581 err++;
582 }
583 } else {
584 if (cmd->stop_arg != 0) {
585 cmd->stop_arg = 0;
586 err++;
587 }
588 }
589
590 if (err)
591 return 3;
592
593
594
595 if (cmd->convert_src == TRIG_TIMER) {
596
597 if (cmd->scan_begin_src == TRIG_TIMER &&
598 cmd->scan_begin_arg <
599 cmd->convert_arg * cmd->scan_end_arg) {
600 cmd->scan_begin_arg =
601 cmd->convert_arg * cmd->scan_end_arg;
602 err++;
603 }
604 }
605
606 if (err)
607 return 4;
608
609 return 0;
610}
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631int i_APCI3120_CommandAnalogInput(struct comedi_device *dev, struct comedi_subdevice *s)
632{
633 struct comedi_cmd *cmd = &s->async->cmd;
634
635
636 devpriv->ui_AiFlags = cmd->flags;
637 devpriv->ui_AiNbrofChannels = cmd->chanlist_len;
638 devpriv->ui_AiScanLength = cmd->scan_end_arg;
639 devpriv->pui_AiChannelList = cmd->chanlist;
640
641
642 devpriv->AiData = s->async->prealloc_buf;
643
644 devpriv->ui_AiDataLength = s->async->prealloc_bufsz;
645
646 if (cmd->stop_src == TRIG_COUNT)
647 devpriv->ui_AiNbrofScans = cmd->stop_arg;
648 else
649 devpriv->ui_AiNbrofScans = 0;
650
651 devpriv->ui_AiTimer0 = 0;
652 devpriv->ui_AiTimer1 = 0;
653 if ((devpriv->ui_AiNbrofScans == 0) || (devpriv->ui_AiNbrofScans == -1))
654 devpriv->b_AiContinuous = 1;
655
656
657 if (cmd->start_src == TRIG_EXT)
658 devpriv->b_ExttrigEnable = APCI3120_ENABLE;
659 else
660 devpriv->b_ExttrigEnable = APCI3120_DISABLE;
661
662 if (cmd->scan_begin_src == TRIG_FOLLOW) {
663
664 if (cmd->convert_src == TRIG_TIMER) {
665
666
667 devpriv->ui_AiTimer0 = cmd->convert_arg;
668
669 return i_APCI3120_CyclicAnalogInput(1, dev, s);
670 }
671
672 }
673 if ((cmd->scan_begin_src == TRIG_TIMER)
674 && (cmd->convert_src == TRIG_TIMER)) {
675
676 devpriv->ui_AiTimer1 = cmd->scan_begin_arg;
677 devpriv->ui_AiTimer0 = cmd->convert_arg;
678
679 return i_APCI3120_CyclicAnalogInput(2, dev, s);
680 }
681 return -1;
682}
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704int i_APCI3120_CyclicAnalogInput(int mode, struct comedi_device *dev,
705 struct comedi_subdevice *s)
706{
707 unsigned char b_Tmp;
708 unsigned int ui_Tmp, ui_DelayTiming = 0, ui_TimerValue1 = 0, dmalen0 =
709 0, dmalen1 = 0, ui_TimerValue2 =
710 0, ui_TimerValue0, ui_ConvertTiming;
711 unsigned short us_TmpValue;
712
713
714
715
716
717
718
719
720 inb(dev->iobase + APCI3120_RESET_FIFO);
721
722
723
724
725
726
727
728
729
730 devpriv->b_AiCyclicAcquisition = APCI3120_ENABLE;
731
732
733
734 devpriv->b_TimerSelectMode = 0;
735 devpriv->us_OutputRegister = 0;
736 devpriv->b_ModeSelectRegister = 0;
737
738
739
740
741
742
743
744 outl(APCI3120_CLEAR_WRITE_TC_INT,
745 devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_REG_INTCSR);
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760 devpriv->us_OutputRegister = devpriv->us_OutputRegister &
761 APCI3120_DISABLE_TIMER0 &
762 APCI3120_DISABLE_TIMER1 & APCI3120_CLEAR_PA_PR;
763
764 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
765
766
767
768
769
770 inb(devpriv->iobase + APCI3120_RESET_FIFO);
771
772
773 devpriv->ui_AiActualScan = 0;
774 devpriv->ui_AiActualScanPosition = 0;
775 s->async->cur_chan = 0;
776 devpriv->ui_AiBufferPtr = 0;
777 devpriv->ui_DmaActualBuffer = 0;
778
779
780 ui_TimerValue2 = devpriv->ui_AiNbrofScans - 2;
781 ui_ConvertTiming = devpriv->ui_AiTimer0;
782
783 if (mode == 2)
784 ui_DelayTiming = devpriv->ui_AiTimer1;
785
786
787
788
789 if (!i_APCI3120_SetupChannelList(dev, s, devpriv->ui_AiNbrofChannels,
790 devpriv->pui_AiChannelList, 0))
791 return -EINVAL;
792
793 us_TmpValue = (unsigned short) inw(dev->iobase + APCI3120_RD_STATUS);
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818 if ((us_TmpValue & 0x00B0) == 0x00B0
819 || !strcmp(this_board->pc_DriverName, "apci3001")) {
820 ui_TimerValue0 = ui_ConvertTiming * 2 - 2000;
821 ui_TimerValue0 = ui_TimerValue0 / 1000;
822
823 if (mode == 2) {
824 ui_DelayTiming = ui_DelayTiming / 1000;
825 ui_TimerValue1 = ui_DelayTiming * 2 - 200;
826 ui_TimerValue1 = ui_TimerValue1 / 100;
827 }
828 } else {
829 ui_ConvertTiming = ui_ConvertTiming / 1000;
830 ui_TimerValue0 = ui_ConvertTiming * 12926 - 10000;
831 ui_TimerValue0 = ui_TimerValue0 / 10000;
832
833 if (mode == 2) {
834 ui_DelayTiming = ui_DelayTiming / 1000;
835 ui_TimerValue1 = ui_DelayTiming * 12926 - 1;
836 ui_TimerValue1 = ui_TimerValue1 / 1000000;
837 }
838 }
839
840
841 if (devpriv->b_ExttrigEnable == APCI3120_ENABLE)
842 i_APCI3120_ExttrigEnable(dev);
843 switch (mode) {
844 case 1:
845
846 devpriv->b_TimerSelectMode =
847 (devpriv->
848 b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
849 outb(devpriv->b_TimerSelectMode,
850 dev->iobase + APCI3120_TIMER_CRT1);
851
852
853 b_Tmp = ((devpriv->
854 b_DigitalOutputRegister) & 0xF0) |
855 APCI3120_SELECT_TIMER_0_WORD;
856 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
857
858 outw(((unsigned short) ui_TimerValue0),
859 dev->iobase + APCI3120_TIMER_VALUE);
860 break;
861
862 case 2:
863
864 devpriv->b_TimerSelectMode =
865 (devpriv->
866 b_TimerSelectMode & 0xF3) | APCI3120_TIMER_1_MODE_2;
867 outb(devpriv->b_TimerSelectMode,
868 dev->iobase + APCI3120_TIMER_CRT1);
869
870
871 b_Tmp = ((devpriv->
872 b_DigitalOutputRegister) & 0xF0) |
873 APCI3120_SELECT_TIMER_1_WORD;
874 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
875
876 outw(((unsigned short) ui_TimerValue1),
877 dev->iobase + APCI3120_TIMER_VALUE);
878
879
880 devpriv->b_TimerSelectMode =
881 (devpriv->
882 b_TimerSelectMode & 0xFC) | APCI3120_TIMER_0_MODE_2;
883 outb(devpriv->b_TimerSelectMode,
884 dev->iobase + APCI3120_TIMER_CRT1);
885
886
887 b_Tmp = ((devpriv->
888 b_DigitalOutputRegister) & 0xF0) |
889 APCI3120_SELECT_TIMER_0_WORD;
890 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
891
892
893 outw(((unsigned short) ui_TimerValue0),
894 dev->iobase + APCI3120_TIMER_VALUE);
895 break;
896
897 }
898
899
900
901
902
903
904
905
906
907 devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
908 APCI3120_DISABLE_SCAN;
909
910
911 outb(devpriv->b_ModeSelectRegister,
912 dev->iobase + APCI3120_WRITE_MODE_SELECT);
913
914
915 if (devpriv->us_UseDma == APCI3120_DISABLE) {
916
917 devpriv->b_InterruptMode = APCI3120_EOS_MODE;
918 devpriv->b_EocEosInterrupt = APCI3120_ENABLE;
919
920 devpriv->b_ModeSelectRegister =
921 (devpriv->
922 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT) |
923 APCI3120_ENABLE_EOS_INT;
924 outb(devpriv->b_ModeSelectRegister,
925 dev->iobase + APCI3120_WRITE_MODE_SELECT);
926
927 if (!devpriv->b_AiContinuous) {
928
929
930
931
932 devpriv->us_OutputRegister =
933 devpriv->
934 us_OutputRegister & APCI3120_DISABLE_TIMER2;
935 outw(devpriv->us_OutputRegister,
936 dev->iobase + APCI3120_WR_ADDRESS);
937
938
939 devpriv->b_ModeSelectRegister =
940 devpriv->
941 b_ModeSelectRegister &
942 APCI3120_DISABLE_TIMER_INT & 0xEF;
943 outb(devpriv->b_ModeSelectRegister,
944 dev->iobase + APCI3120_WRITE_MODE_SELECT);
945
946
947 devpriv->b_TimerSelectMode =
948 (devpriv->
949 b_TimerSelectMode & 0x0F) |
950 APCI3120_TIMER_2_MODE_0;
951 outb(devpriv->b_TimerSelectMode,
952 dev->iobase + APCI3120_TIMER_CRT1);
953
954
955 b_Tmp = ((devpriv->
956 b_DigitalOutputRegister) & 0xF0) |
957 APCI3120_SELECT_TIMER_2_LOW_WORD;
958 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
959 outw(LOWORD(ui_TimerValue2),
960 dev->iobase + APCI3120_TIMER_VALUE);
961
962
963 b_Tmp = ((devpriv->
964 b_DigitalOutputRegister) & 0xF0) |
965 APCI3120_SELECT_TIMER_2_HIGH_WORD;
966 outb(b_Tmp, dev->iobase + APCI3120_TIMER_CRT0);
967 outw(HIWORD(ui_TimerValue2),
968 dev->iobase + APCI3120_TIMER_VALUE);
969
970
971 inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
972
973 devpriv->b_ModeSelectRegister =
974 (devpriv->
975 b_ModeSelectRegister |
976 APCI3120_ENABLE_TIMER_COUNTER) &
977 APCI3120_DISABLE_WATCHDOG;
978
979 devpriv->b_ModeSelectRegister =
980 devpriv->
981 b_ModeSelectRegister |
982 APCI3120_TIMER2_SELECT_EOS;
983
984 devpriv->b_ModeSelectRegister =
985 devpriv->
986 b_ModeSelectRegister |
987 APCI3120_ENABLE_TIMER_INT;
988 outb(devpriv->b_ModeSelectRegister,
989 dev->iobase + APCI3120_WRITE_MODE_SELECT);
990 devpriv->b_Timer2Mode = APCI3120_COUNTER;
991 devpriv->b_Timer2Interrupt = APCI3120_ENABLE;
992 }
993 } else {
994
995
996
997
998
999 devpriv->b_InterruptMode = APCI3120_DMA_MODE;
1000
1001
1002
1003
1004 devpriv->b_ModeSelectRegister = devpriv->b_ModeSelectRegister &
1005 APCI3120_DISABLE_EOC_INT & APCI3120_DISABLE_EOS_INT;
1006
1007 outb(devpriv->b_ModeSelectRegister,
1008 dev->iobase + APCI3120_WRITE_MODE_SELECT);
1009
1010 dmalen0 = devpriv->ui_DmaBufferSize[0];
1011 dmalen1 = devpriv->ui_DmaBufferSize[1];
1012
1013 if (!devpriv->b_AiContinuous) {
1014
1015 if (dmalen0 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2)) {
1016 dmalen0 =
1017 devpriv->ui_AiNbrofScans *
1018 devpriv->ui_AiScanLength * 2;
1019 } else if (dmalen1 > (devpriv->ui_AiNbrofScans * devpriv->ui_AiScanLength * 2 - dmalen0))
1020 dmalen1 =
1021 devpriv->ui_AiNbrofScans *
1022 devpriv->ui_AiScanLength * 2 - dmalen0;
1023 }
1024
1025 if (devpriv->ui_AiFlags & TRIG_WAKE_EOS) {
1026
1027 if (dmalen0 > (devpriv->ui_AiScanLength * 2)) {
1028 dmalen0 = devpriv->ui_AiScanLength * 2;
1029 if (devpriv->ui_AiScanLength & 1)
1030 dmalen0 += 2;
1031 }
1032 if (dmalen1 > (devpriv->ui_AiScanLength * 2)) {
1033 dmalen1 = devpriv->ui_AiScanLength * 2;
1034 if (devpriv->ui_AiScanLength & 1)
1035 dmalen1 -= 2;
1036 if (dmalen1 < 4)
1037 dmalen1 = 4;
1038 }
1039 } else {
1040 if (dmalen0 > (devpriv->ui_AiDataLength))
1041 dmalen0 = devpriv->ui_AiDataLength;
1042 if (dmalen1 > (devpriv->ui_AiDataLength))
1043 dmalen1 = devpriv->ui_AiDataLength;
1044 }
1045 devpriv->ui_DmaBufferUsesize[0] = dmalen0;
1046 devpriv->ui_DmaBufferUsesize[1] = dmalen1;
1047
1048
1049
1050
1051
1052
1053
1054 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
1055 outl(ui_Tmp, devpriv->i_IobaseAmcc + AMCC_OP_REG_AGCSTS);
1056
1057
1058
1059
1060
1061 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
1062 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
1063 devpriv->i_IobaseAddon + 2);
1064
1065 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
1066 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH,
1067 devpriv->i_IobaseAddon + 2);
1068
1069
1070
1071
1072
1073 outw(0x1000, devpriv->i_IobaseAddon + 2);
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083 outl(APCI3120_A2P_FIFO_MANAGEMENT, devpriv->i_IobaseAmcc +
1084 APCI3120_AMCC_OP_MCSR);
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
1095 outw((devpriv->ul_DmaBufferHw[0] & 0xFFFF),
1096 devpriv->i_IobaseAddon + 2);
1097
1098
1099
1100
1101 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
1102 outw((devpriv->ul_DmaBufferHw[0] / 65536),
1103 devpriv->i_IobaseAddon + 2);
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
1117 outw((devpriv->ui_DmaBufferUsesize[0] & 0xFFFF),
1118 devpriv->i_IobaseAddon + 2);
1119
1120
1121
1122
1123 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
1124 outw((devpriv->ui_DmaBufferUsesize[0] / 65536),
1125 devpriv->i_IobaseAddon + 2);
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140 outl(0x04000000UL, devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
1162 APCI3120_ENABLE_WRITE_TC_INT),
1163 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
1164
1165
1166
1167
1168
1169 outw(3, devpriv->i_IobaseAddon + 4);
1170
1171
1172
1173
1174
1175
1176 outl(0x04000000UL,
1177 devpriv->i_IobaseAmcc + APCI3120_AMCC_OP_MCSR);
1178
1179 }
1180
1181 if ((devpriv->us_UseDma == APCI3120_DISABLE)
1182 && !devpriv->b_AiContinuous) {
1183
1184 devpriv->us_OutputRegister =
1185 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER2;
1186 outw(devpriv->us_OutputRegister,
1187 dev->iobase + APCI3120_WR_ADDRESS);
1188 }
1189
1190 switch (mode) {
1191 case 1:
1192
1193 devpriv->us_OutputRegister =
1194 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
1195 outw(devpriv->us_OutputRegister,
1196 dev->iobase + APCI3120_WR_ADDRESS);
1197 break;
1198 case 2:
1199
1200 devpriv->us_OutputRegister =
1201 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER1;
1202 devpriv->us_OutputRegister =
1203 devpriv->us_OutputRegister | APCI3120_ENABLE_TIMER0;
1204 outw(devpriv->us_OutputRegister,
1205 dev->iobase + APCI3120_WR_ADDRESS);
1206 break;
1207
1208 }
1209
1210 return 0;
1211
1212}
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238int i_APCI3120_Reset(struct comedi_device *dev)
1239{
1240 unsigned int i;
1241 unsigned short us_TmpValue;
1242
1243 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
1244 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
1245 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
1246 devpriv->ui_EocEosConversionTime = 0;
1247 devpriv->b_OutputMemoryStatus = 0;
1248
1249
1250 devpriv->b_Timer2Mode = 0;
1251 devpriv->b_Timer2Interrupt = 0;
1252 devpriv->b_ExttrigEnable = 0;
1253
1254
1255 devpriv->b_ModeSelectRegister = 0;
1256 outb(devpriv->b_ModeSelectRegister,
1257 dev->iobase + APCI3120_WRITE_MODE_SELECT);
1258
1259
1260 devpriv->us_OutputRegister = 0;
1261 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
1262
1263
1264
1265
1266
1267 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_1, dev->iobase + APCI3120_ANALOG_OUTPUT_1);
1268 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_2, dev->iobase + APCI3120_ANALOG_OUTPUT_1);
1269 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_3, dev->iobase + APCI3120_ANALOG_OUTPUT_1);
1270 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_4, dev->iobase + APCI3120_ANALOG_OUTPUT_1);
1271
1272 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_5, dev->iobase + APCI3120_ANALOG_OUTPUT_2);
1273 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_6, dev->iobase + APCI3120_ANALOG_OUTPUT_2);
1274 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_7, dev->iobase + APCI3120_ANALOG_OUTPUT_2);
1275 outw(8191 | APCI3120_ANALOG_OP_CHANNEL_8, dev->iobase + APCI3120_ANALOG_OUTPUT_2);
1276
1277
1278
1279
1280 udelay(10);
1281
1282 inw(dev->iobase + 0);
1283 inb(dev->iobase + APCI3120_RESET_FIFO);
1284 inw(dev->iobase + APCI3120_RD_STATUS);
1285
1286
1287 for (i = 0; i < 16; i++) {
1288 us_TmpValue = i << 8;
1289 outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
1290 }
1291 return 0;
1292}
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318int i_APCI3120_SetupChannelList(struct comedi_device *dev, struct comedi_subdevice *s,
1319 int n_chan, unsigned int *chanlist, char check)
1320{
1321 unsigned int i;
1322 unsigned int gain;
1323 unsigned short us_TmpValue;
1324
1325
1326 if (n_chan < 1) {
1327 if (!check)
1328 comedi_error(dev, "range/channel list is empty!");
1329 return 0;
1330 }
1331
1332 if (check)
1333 return 1;
1334
1335
1336 devpriv->us_OutputRegister =
1337 devpriv->us_OutputRegister & APCI3120_CLEAR_PA_PR;
1338 devpriv->us_OutputRegister = ((n_chan - 1) & 0xf) << 8;
1339 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
1340
1341 for (i = 0; i < n_chan; i++) {
1342
1343 us_TmpValue = CR_CHAN(chanlist[i]);
1344
1345 if (CR_RANGE(chanlist[i]) < APCI3120_BIPOLAR_RANGES)
1346 us_TmpValue &= ((~APCI3120_UNIPOLAR) & 0xff);
1347 else
1348 us_TmpValue |= APCI3120_UNIPOLAR;
1349
1350 gain = CR_RANGE(chanlist[i]);
1351 us_TmpValue |= ((gain & 0x03) << 4);
1352 us_TmpValue |= i << 8;
1353 outw(us_TmpValue, dev->iobase + APCI3120_SEQ_RAM_ADDRESS);
1354
1355 printk("\n Gain = %i",
1356 (((unsigned char)CR_RANGE(chanlist[i]) & 0x03) << 2));
1357 printk("\n Channel = %i", CR_CHAN(chanlist[i]));
1358 printk("\n Polarity = %i", us_TmpValue & APCI3120_UNIPOLAR);
1359 }
1360 return 1;
1361}
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381int i_APCI3120_ExttrigEnable(struct comedi_device *dev)
1382{
1383
1384 devpriv->us_OutputRegister |= APCI3120_ENABLE_EXT_TRIGGER;
1385 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
1386 return 0;
1387}
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406int i_APCI3120_ExttrigDisable(struct comedi_device *dev)
1407{
1408 devpriv->us_OutputRegister &= ~APCI3120_ENABLE_EXT_TRIGGER;
1409 outw(devpriv->us_OutputRegister, dev->iobase + APCI3120_WR_ADDRESS);
1410 return 0;
1411}
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440void v_APCI3120_Interrupt(int irq, void *d)
1441{
1442 struct comedi_device *dev = d;
1443 unsigned short int_daq;
1444
1445 unsigned int int_amcc, ui_Check, i;
1446 unsigned short us_TmpValue;
1447 unsigned char b_DummyRead;
1448
1449 struct comedi_subdevice *s = dev->subdevices + 0;
1450 ui_Check = 1;
1451
1452 int_daq = inw(dev->iobase + APCI3120_RD_STATUS) & 0xf000;
1453 int_amcc = inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
1454
1455 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT))) {
1456 comedi_error(dev, "IRQ from unknown source");
1457 return;
1458 }
1459
1460 outl(int_amcc | 0x00ff0000, devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
1461
1462 int_daq = (int_daq >> 12) & 0xF;
1463
1464 if (devpriv->b_ExttrigEnable == APCI3120_ENABLE) {
1465
1466 i_APCI3120_ExttrigDisable(dev);
1467 devpriv->b_ExttrigEnable = APCI3120_DISABLE;
1468 }
1469
1470 inb(devpriv->i_IobaseAmcc + APCI3120_TIMER_STATUS_REGISTER);
1471
1472 if (int_amcc & MASTER_ABORT_INT)
1473 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
1474 if (int_amcc & TARGET_ABORT_INT)
1475 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
1476
1477
1478 if (((int_daq & 0x8) == 0)
1479 && (devpriv->b_InterruptMode == APCI3120_EOC_MODE)) {
1480 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
1481
1482
1483
1484 devpriv->ui_AiReadData[0] =
1485 (unsigned int) inw(devpriv->iobase + 0);
1486 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
1487 send_sig(SIGIO, devpriv->tsk_Current, 0);
1488 } else {
1489
1490 devpriv->b_ModeSelectRegister =
1491 devpriv->
1492 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT;
1493 outb(devpriv->b_ModeSelectRegister,
1494 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
1495
1496 }
1497 }
1498
1499
1500 if ((int_daq & 0x2) && (devpriv->b_InterruptMode == APCI3120_EOS_MODE)) {
1501
1502 if (devpriv->b_EocEosInterrupt == APCI3120_ENABLE) {
1503
1504 if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
1505 ui_Check = 0;
1506 i_APCI3120_InterruptHandleEos(dev);
1507 devpriv->ui_AiActualScan++;
1508 devpriv->b_ModeSelectRegister =
1509 devpriv->
1510 b_ModeSelectRegister |
1511 APCI3120_ENABLE_EOS_INT;
1512 outb(devpriv->b_ModeSelectRegister,
1513 dev->iobase +
1514 APCI3120_WRITE_MODE_SELECT);
1515 } else {
1516 ui_Check = 0;
1517 for (i = 0; i < devpriv->ui_AiNbrofChannels;
1518 i++) {
1519 us_TmpValue = inw(devpriv->iobase + 0);
1520 devpriv->ui_AiReadData[i] =
1521 (unsigned int) us_TmpValue;
1522 }
1523 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
1524 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
1525
1526 send_sig(SIGIO, devpriv->tsk_Current, 0);
1527
1528 }
1529
1530 } else {
1531 devpriv->b_ModeSelectRegister =
1532 devpriv->
1533 b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
1534 outb(devpriv->b_ModeSelectRegister,
1535 dev->iobase + APCI3120_WRITE_MODE_SELECT);
1536 devpriv->b_EocEosInterrupt = APCI3120_DISABLE;
1537 devpriv->b_InterruptMode = APCI3120_EOC_MODE;
1538 }
1539
1540 }
1541
1542 if (int_daq & 0x1) {
1543
1544 switch (devpriv->b_Timer2Mode) {
1545 case APCI3120_COUNTER:
1546
1547 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
1548 devpriv->b_ModeSelectRegister =
1549 devpriv->
1550 b_ModeSelectRegister & APCI3120_DISABLE_EOS_INT;
1551 outb(devpriv->b_ModeSelectRegister,
1552 dev->iobase + APCI3120_WRITE_MODE_SELECT);
1553
1554
1555 devpriv->us_OutputRegister =
1556 devpriv->
1557 us_OutputRegister & APCI3120_DISABLE_ALL_TIMER;
1558 outw(devpriv->us_OutputRegister,
1559 dev->iobase + APCI3120_WR_ADDRESS);
1560
1561
1562 i_APCI3120_StopCyclicAcquisition(dev, s);
1563 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
1564
1565
1566 s->async->events |= COMEDI_CB_EOA;
1567 comedi_event(dev, s);
1568
1569 break;
1570
1571 case APCI3120_TIMER:
1572
1573
1574 send_sig(SIGIO, devpriv->tsk_Current, 0);
1575 break;
1576
1577 case APCI3120_WATCHDOG:
1578
1579
1580 send_sig(SIGIO, devpriv->tsk_Current, 0);
1581 break;
1582
1583 default:
1584
1585
1586
1587 devpriv->b_ModeSelectRegister =
1588 devpriv->
1589 b_ModeSelectRegister &
1590 APCI3120_DISABLE_TIMER_INT;
1591
1592 outb(devpriv->b_ModeSelectRegister,
1593 dev->iobase + APCI3120_WRITE_MODE_SELECT);
1594
1595 }
1596
1597 b_DummyRead = inb(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
1598
1599 }
1600
1601 if ((int_daq & 0x4) && (devpriv->b_InterruptMode == APCI3120_DMA_MODE)) {
1602 if (devpriv->b_AiCyclicAcquisition == APCI3120_ENABLE) {
1603
1604
1605
1606
1607
1608 outl(APCI3120_CLEAR_WRITE_TC_INT,
1609 devpriv->i_IobaseAmcc +
1610 APCI3120_AMCC_OP_REG_INTCSR);
1611
1612
1613
1614
1615 inw(dev->iobase + APCI3120_TIMER_STATUS_REGISTER);
1616 v_APCI3120_InterruptDma(irq, d);
1617 } else {
1618
1619 outw(devpriv->
1620 us_OutputRegister & APCI3120_DISABLE_TIMER0 &
1621 APCI3120_DISABLE_TIMER1,
1622 dev->iobase + APCI3120_WR_ADDRESS);
1623 }
1624
1625 }
1626
1627 return;
1628}
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651int i_APCI3120_InterruptHandleEos(struct comedi_device *dev)
1652{
1653 int n_chan, i;
1654 struct comedi_subdevice *s = dev->subdevices + 0;
1655 int err = 1;
1656
1657 n_chan = devpriv->ui_AiNbrofChannels;
1658
1659 s->async->events = 0;
1660
1661 for (i = 0; i < n_chan; i++)
1662 err &= comedi_buf_put(s->async, inw(dev->iobase + 0));
1663
1664 s->async->events |= COMEDI_CB_EOS;
1665
1666 if (err == 0)
1667 s->async->events |= COMEDI_CB_OVERFLOW;
1668
1669 comedi_event(dev, s);
1670
1671 return 0;
1672}
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693void v_APCI3120_InterruptDma(int irq, void *d)
1694{
1695 struct comedi_device *dev = d;
1696 struct comedi_subdevice *s = dev->subdevices + 0;
1697 unsigned int next_dma_buf, samplesinbuf;
1698 unsigned long low_word, high_word, var;
1699
1700 unsigned int ui_Tmp;
1701 samplesinbuf =
1702 devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer] -
1703 inl(devpriv->i_IobaseAmcc + AMCC_OP_REG_MWTC);
1704
1705 if (samplesinbuf <
1706 devpriv->ui_DmaBufferUsesize[devpriv->ui_DmaActualBuffer]) {
1707 comedi_error(dev, "Interrupted DMA transfer!");
1708 }
1709 if (samplesinbuf & 1) {
1710 comedi_error(dev, "Odd count of bytes in DMA ring!");
1711 i_APCI3120_StopCyclicAcquisition(dev, s);
1712 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
1713
1714 return;
1715 }
1716 samplesinbuf = samplesinbuf >> 1;
1717 if (devpriv->b_DmaDoubleBuffer) {
1718
1719 next_dma_buf = 1 - devpriv->ui_DmaActualBuffer;
1720
1721 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
1722 outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
1723
1724
1725 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
1726 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
1727 devpriv->i_IobaseAddon + 2);
1728 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
1729 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);
1730
1731 var = devpriv->ul_DmaBufferHw[next_dma_buf];
1732 low_word = var & 0xffff;
1733 var = devpriv->ul_DmaBufferHw[next_dma_buf];
1734 high_word = var / 65536;
1735
1736
1737 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
1738 outw(low_word, devpriv->i_IobaseAddon + 2);
1739
1740
1741 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
1742 outw(high_word, devpriv->i_IobaseAddon + 2);
1743
1744 var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
1745 low_word = var & 0xffff;
1746 var = devpriv->ui_DmaBufferUsesize[next_dma_buf];
1747 high_word = var / 65536;
1748
1749
1750 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
1751 outw(low_word, devpriv->i_IobaseAddon + 2);
1752
1753
1754 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
1755 outw(high_word, devpriv->i_IobaseAddon + 2);
1756
1757
1758
1759
1760
1761
1762 outw(3, devpriv->i_IobaseAddon + 4);
1763
1764 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
1765 APCI3120_ENABLE_WRITE_TC_INT),
1766 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
1767
1768 }
1769 if (samplesinbuf) {
1770 v_APCI3120_InterruptDmaMoveBlock16bit(dev, s,
1771 devpriv->ul_DmaBufferVirtual[devpriv->
1772 ui_DmaActualBuffer], samplesinbuf);
1773
1774 if (!(devpriv->ui_AiFlags & TRIG_WAKE_EOS)) {
1775 s->async->events |= COMEDI_CB_EOS;
1776 comedi_event(dev, s);
1777 }
1778 }
1779 if (!devpriv->b_AiContinuous)
1780 if (devpriv->ui_AiActualScan >= devpriv->ui_AiNbrofScans) {
1781
1782 i_APCI3120_StopCyclicAcquisition(dev, s);
1783 devpriv->b_AiCyclicAcquisition = APCI3120_DISABLE;
1784 s->async->events |= COMEDI_CB_EOA;
1785 comedi_event(dev, s);
1786 return;
1787 }
1788
1789 if (devpriv->b_DmaDoubleBuffer) {
1790 devpriv->ui_DmaActualBuffer = 1 - devpriv->ui_DmaActualBuffer;
1791 } else {
1792
1793
1794
1795
1796 ui_Tmp = AGCSTS_TC_ENABLE | AGCSTS_RESET_A2P_FIFO;
1797 outl(ui_Tmp, devpriv->i_IobaseAddon + AMCC_OP_REG_AGCSTS);
1798
1799
1800 outw(APCI3120_ADD_ON_AGCSTS_LOW, devpriv->i_IobaseAddon + 0);
1801 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_LOW,
1802 devpriv->i_IobaseAddon + 2);
1803 outw(APCI3120_ADD_ON_AGCSTS_HIGH, devpriv->i_IobaseAddon + 0);
1804 outw(APCI3120_ENABLE_TRANSFER_ADD_ON_HIGH, devpriv->i_IobaseAddon + 2);
1805
1806
1807
1808
1809 outl(APCI3120_A2P_FIFO_MANAGEMENT,
1810 devpriv->i_IobaseAmcc + AMCC_OP_REG_MCSR);
1811
1812 var = devpriv->ul_DmaBufferHw[0];
1813 low_word = var & 0xffff;
1814 var = devpriv->ul_DmaBufferHw[0];
1815 high_word = var / 65536;
1816 outw(APCI3120_ADD_ON_MWAR_LOW, devpriv->i_IobaseAddon + 0);
1817 outw(low_word, devpriv->i_IobaseAddon + 2);
1818 outw(APCI3120_ADD_ON_MWAR_HIGH, devpriv->i_IobaseAddon + 0);
1819 outw(high_word, devpriv->i_IobaseAddon + 2);
1820
1821 var = devpriv->ui_DmaBufferUsesize[0];
1822 low_word = var & 0xffff;
1823 var = devpriv->ui_DmaBufferUsesize[0];
1824 high_word = var / 65536;
1825 outw(APCI3120_ADD_ON_MWTC_LOW, devpriv->i_IobaseAddon + 0);
1826 outw(low_word, devpriv->i_IobaseAddon + 2);
1827 outw(APCI3120_ADD_ON_MWTC_HIGH, devpriv->i_IobaseAddon + 0);
1828 outw(high_word, devpriv->i_IobaseAddon + 2);
1829
1830
1831
1832
1833
1834
1835 outw(3, devpriv->i_IobaseAddon + 4);
1836
1837 outl((APCI3120_FIFO_ADVANCE_ON_BYTE_2 |
1838 APCI3120_ENABLE_WRITE_TC_INT),
1839 devpriv->i_IobaseAmcc + AMCC_OP_REG_INTCSR);
1840 }
1841}
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863void v_APCI3120_InterruptDmaMoveBlock16bit(struct comedi_device *dev,
1864 struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
1865{
1866 devpriv->ui_AiActualScan +=
1867 (s->async->cur_chan + num_samples) / devpriv->ui_AiScanLength;
1868 s->async->cur_chan += num_samples;
1869 s->async->cur_chan %= devpriv->ui_AiScanLength;
1870
1871 cfc_write_array_to_buffer(s, dma_buffer, num_samples * sizeof(short));
1872}
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905int i_APCI3120_InsnConfigTimer(struct comedi_device *dev, struct comedi_subdevice *s,
1906 struct comedi_insn *insn, unsigned int *data)
1907{
1908
1909 unsigned int ui_Timervalue2;
1910 unsigned short us_TmpValue;
1911 unsigned char b_Tmp;
1912
1913 if (!data[1])
1914 comedi_error(dev, "config:No timer constant !");
1915
1916 devpriv->b_Timer2Interrupt = (unsigned char) data[2];
1917
1918 ui_Timervalue2 = data[1] / 1000;
1919
1920
1921 us_TmpValue = (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
1922
1923
1924
1925
1926
1927 if ((us_TmpValue & 0x00B0) == 0x00B0
1928 || !strcmp(this_board->pc_DriverName, "apci3001")) {
1929
1930 ui_Timervalue2 = ui_Timervalue2 / 50;
1931 } else {
1932
1933 ui_Timervalue2 = ui_Timervalue2 / 70;
1934 }
1935
1936
1937 devpriv->us_OutputRegister =
1938 devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER2;
1939 outw(devpriv->us_OutputRegister, devpriv->iobase + APCI3120_WR_ADDRESS);
1940
1941
1942 devpriv->b_ModeSelectRegister =
1943 devpriv->
1944 b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT & 0xEF;
1945
1946
1947 devpriv->b_ModeSelectRegister =
1948 devpriv->
1949 b_ModeSelectRegister & APCI3120_DISABLE_EOC_INT &
1950 APCI3120_DISABLE_EOS_INT;
1951 outb(devpriv->b_ModeSelectRegister,
1952 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
1953 if (data[0] == APCI3120_TIMER) {
1954
1955
1956
1957
1958
1959
1960 devpriv->b_TimerSelectMode =
1961 (devpriv->
1962 b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_2;
1963 outb(devpriv->b_TimerSelectMode,
1964 devpriv->iobase + APCI3120_TIMER_CRT1);
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975 b_Tmp = ((devpriv->
1976 b_DigitalOutputRegister) & 0xF0) |
1977 APCI3120_SELECT_TIMER_2_LOW_WORD;
1978 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
1979 outw(LOWORD(ui_Timervalue2),
1980 devpriv->iobase + APCI3120_TIMER_VALUE);
1981
1982
1983 b_Tmp = ((devpriv->
1984 b_DigitalOutputRegister) & 0xF0) |
1985 APCI3120_SELECT_TIMER_2_HIGH_WORD;
1986 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
1987 outw(HIWORD(ui_Timervalue2),
1988 devpriv->iobase + APCI3120_TIMER_VALUE);
1989
1990 devpriv->b_Timer2Mode = APCI3120_TIMER;
1991
1992 } else {
1993
1994
1995
1996 devpriv->b_TimerSelectMode =
1997 (devpriv->
1998 b_TimerSelectMode & 0x0F) | APCI3120_TIMER_2_MODE_5;
1999 outb(devpriv->b_TimerSelectMode,
2000 devpriv->iobase + APCI3120_TIMER_CRT1);
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011 b_Tmp = ((devpriv->
2012 b_DigitalOutputRegister) & 0xF0) |
2013 APCI3120_SELECT_TIMER_2_LOW_WORD;
2014 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2015 outw(LOWORD(ui_Timervalue2),
2016 devpriv->iobase + APCI3120_TIMER_VALUE);
2017
2018
2019 b_Tmp = ((devpriv->
2020 b_DigitalOutputRegister) & 0xF0) |
2021 APCI3120_SELECT_TIMER_2_HIGH_WORD;
2022 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2023
2024 outw(HIWORD(ui_Timervalue2),
2025 devpriv->iobase + APCI3120_TIMER_VALUE);
2026
2027 devpriv->b_Timer2Mode = APCI3120_WATCHDOG;
2028
2029 }
2030
2031 return insn->n;
2032
2033}
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063int i_APCI3120_InsnWriteTimer(struct comedi_device *dev, struct comedi_subdevice *s,
2064 struct comedi_insn *insn, unsigned int *data)
2065{
2066
2067 unsigned int ui_Timervalue2 = 0;
2068 unsigned short us_TmpValue;
2069 unsigned char b_Tmp;
2070
2071 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
2072 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
2073 comedi_error(dev, "\nwrite:timer2 not configured ");
2074 return -EINVAL;
2075 }
2076
2077 if (data[0] == 2) {
2078 if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
2079 comedi_error(dev,
2080 "write :timer2 not configured in TIMER MODE");
2081 return -EINVAL;
2082 }
2083
2084 if (data[1])
2085 ui_Timervalue2 = data[1];
2086 else
2087 ui_Timervalue2 = 0;
2088 }
2089
2090
2091
2092 switch (data[0]) {
2093 case APCI3120_START:
2094
2095
2096 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
2097 if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
2098
2099 devpriv->b_ModeSelectRegister =
2100 devpriv->b_ModeSelectRegister & 0x0B;
2101 } else {
2102
2103 devpriv->b_ModeSelectRegister =
2104 (devpriv->
2105 b_ModeSelectRegister & 0x0B) |
2106 APCI3120_ENABLE_WATCHDOG;
2107 }
2108
2109
2110 if ((devpriv->b_Timer2Interrupt) == APCI3120_ENABLE) {
2111
2112 devpriv->b_ModeSelectRegister =
2113 devpriv->
2114 b_ModeSelectRegister |
2115 APCI3120_ENABLE_TIMER_INT;
2116
2117 devpriv->tsk_Current = current;
2118 } else {
2119
2120 devpriv->b_ModeSelectRegister =
2121 devpriv->
2122 b_ModeSelectRegister &
2123 APCI3120_DISABLE_TIMER_INT;
2124 }
2125 outb(devpriv->b_ModeSelectRegister,
2126 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
2127
2128 if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
2129
2130 devpriv->us_OutputRegister =
2131 devpriv->
2132 us_OutputRegister | APCI3120_ENABLE_TIMER2;
2133 outw(devpriv->us_OutputRegister,
2134 devpriv->iobase + APCI3120_WR_ADDRESS);
2135 }
2136
2137 break;
2138
2139 case APCI3120_STOP:
2140 if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
2141
2142 devpriv->b_ModeSelectRegister =
2143 devpriv->
2144 b_ModeSelectRegister &
2145 APCI3120_DISABLE_TIMER_COUNTER;
2146 } else {
2147
2148 devpriv->b_ModeSelectRegister =
2149 devpriv->
2150 b_ModeSelectRegister &
2151 APCI3120_DISABLE_WATCHDOG;
2152 }
2153
2154 devpriv->b_ModeSelectRegister =
2155 devpriv->
2156 b_ModeSelectRegister & APCI3120_DISABLE_TIMER_INT;
2157
2158
2159 outb(devpriv->b_ModeSelectRegister,
2160 devpriv->iobase + APCI3120_WRITE_MODE_SELECT);
2161
2162
2163 devpriv->us_OutputRegister =
2164 devpriv->us_OutputRegister & APCI3120_DISABLE_TIMER_INT;
2165 outw(devpriv->us_OutputRegister,
2166 devpriv->iobase + APCI3120_WR_ADDRESS);
2167
2168
2169 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
2170
2171
2172
2173
2174 break;
2175
2176 case 2:
2177 if (devpriv->b_Timer2Mode != APCI3120_TIMER) {
2178 comedi_error(dev,
2179 "write :timer2 not configured in TIMER MODE");
2180 return -EINVAL;
2181 }
2182
2183 us_TmpValue =
2184 (unsigned short) inw(devpriv->iobase + APCI3120_RD_STATUS);
2185
2186
2187
2188
2189
2190 if ((us_TmpValue & 0x00B0) == 0x00B0
2191 || !strcmp(this_board->pc_DriverName, "apci3001")) {
2192
2193 ui_Timervalue2 = ui_Timervalue2 / 50;
2194 } else {
2195
2196 ui_Timervalue2 = ui_Timervalue2 / 70;
2197 }
2198
2199 b_Tmp = ((devpriv->
2200 b_DigitalOutputRegister) & 0xF0) |
2201 APCI3120_SELECT_TIMER_2_LOW_WORD;
2202 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2203
2204 outw(LOWORD(ui_Timervalue2),
2205 devpriv->iobase + APCI3120_TIMER_VALUE);
2206
2207
2208 b_Tmp = ((devpriv->
2209 b_DigitalOutputRegister) & 0xF0) |
2210 APCI3120_SELECT_TIMER_2_HIGH_WORD;
2211 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2212
2213 outw(HIWORD(ui_Timervalue2),
2214 devpriv->iobase + APCI3120_TIMER_VALUE);
2215
2216 break;
2217 default:
2218 return -EINVAL;
2219 }
2220
2221 return insn->n;
2222}
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247int i_APCI3120_InsnReadTimer(struct comedi_device *dev, struct comedi_subdevice *s,
2248 struct comedi_insn *insn, unsigned int *data)
2249{
2250 unsigned char b_Tmp;
2251 unsigned short us_TmpValue, us_TmpValue_2, us_StatusValue;
2252
2253 if ((devpriv->b_Timer2Mode != APCI3120_WATCHDOG)
2254 && (devpriv->b_Timer2Mode != APCI3120_TIMER)) {
2255 comedi_error(dev, "\nread:timer2 not configured ");
2256 }
2257
2258
2259 if (devpriv->b_Timer2Mode == APCI3120_TIMER) {
2260
2261
2262 b_Tmp = ((devpriv->
2263 b_DigitalOutputRegister) & 0xF0) |
2264 APCI3120_SELECT_TIMER_2_LOW_WORD;
2265 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2266
2267 us_TmpValue = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
2268
2269
2270 b_Tmp = ((devpriv->
2271 b_DigitalOutputRegister) & 0xF0) |
2272 APCI3120_SELECT_TIMER_2_HIGH_WORD;
2273 outb(b_Tmp, devpriv->iobase + APCI3120_TIMER_CRT0);
2274
2275 us_TmpValue_2 = inw(devpriv->iobase + APCI3120_TIMER_VALUE);
2276
2277
2278 data[0] = (unsigned int) ((us_TmpValue) | ((us_TmpValue_2) << 16));
2279
2280 } else {
2281
2282 us_StatusValue = inw(devpriv->iobase + APCI3120_RD_STATUS);
2283 us_StatusValue =
2284 ((us_StatusValue & APCI3120_FC_TIMER) >> 12) & 1;
2285 if (us_StatusValue == 1) {
2286
2287 inb(devpriv->iobase + APCI3120_TIMER_STATUS_REGISTER);
2288 }
2289 data[0] = us_StatusValue;
2290 }
2291 return insn->n;
2292}
2293
2294
2295
2296
2297
2298
2299
2300
2301
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320int i_APCI3120_InsnReadDigitalInput(struct comedi_device *dev,
2321 struct comedi_subdevice *s,
2322 struct comedi_insn *insn,
2323 unsigned int *data)
2324{
2325 unsigned int ui_Chan, ui_TmpValue;
2326
2327 ui_Chan = CR_CHAN(insn->chanspec);
2328
2329
2330 if (ui_Chan <= 3) {
2331 ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
2332
2333
2334
2335
2336
2337 *data = (ui_TmpValue >> (ui_Chan + 8)) & 1;
2338
2339 } else {
2340
2341 return -EINVAL;
2342 }
2343 return insn->n;
2344
2345}
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366int i_APCI3120_InsnBitsDigitalInput(struct comedi_device *dev, struct comedi_subdevice *s,
2367 struct comedi_insn *insn, unsigned int *data)
2368{
2369 unsigned int ui_TmpValue;
2370 ui_TmpValue = (unsigned int) inw(devpriv->iobase + APCI3120_RD_STATUS);
2371
2372
2373
2374
2375
2376 *data = (ui_TmpValue >> 8) & 0xf;
2377
2378 return insn->n;
2379}
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
2405int i_APCI3120_InsnConfigDigitalOutput(struct comedi_device *dev,
2406 struct comedi_subdevice *s, struct comedi_insn *insn, unsigned int *data)
2407{
2408
2409 if ((data[0] != 0) && (data[0] != 1)) {
2410 comedi_error(dev,
2411 "Not a valid Data !!! ,Data should be 1 or 0\n");
2412 return -EINVAL;
2413 }
2414 if (data[0]) {
2415 devpriv->b_OutputMemoryStatus = APCI3120_ENABLE;
2416
2417 } else {
2418 devpriv->b_OutputMemoryStatus = APCI3120_DISABLE;
2419 devpriv->b_DigitalOutputRegister = 0;
2420 }
2421 if (!devpriv->b_OutputMemoryStatus)
2422 ui_Temp = 0;
2423
2424
2425 return insn->n;
2426}
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450int i_APCI3120_InsnBitsDigitalOutput(struct comedi_device *dev,
2451 struct comedi_subdevice *s,
2452 struct comedi_insn *insn,
2453 unsigned int *data)
2454{
2455 if ((data[0] > this_board->i_DoMaxdata) || (data[0] < 0)) {
2456
2457 comedi_error(dev, "Data is not valid !!! \n");
2458 return -EINVAL;
2459 }
2460
2461 switch (data[1]) {
2462 case 1:
2463 data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
2464 break;
2465
2466 case 2:
2467 data[0] = data[0];
2468 break;
2469 default:
2470 printk("\nThe parameter passed is in error \n");
2471 return -EINVAL;
2472 }
2473 outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
2474
2475 devpriv->b_DigitalOutputRegister = data[0] & 0xF0;
2476
2477 return insn->n;
2478
2479}
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503int i_APCI3120_InsnWriteDigitalOutput(struct comedi_device *dev,
2504 struct comedi_subdevice *s,
2505 struct comedi_insn *insn,
2506 unsigned int *data)
2507{
2508
2509 unsigned int ui_Temp1;
2510
2511 unsigned int ui_NoOfChannel = CR_CHAN(insn->chanspec);
2512
2513 if ((data[0] != 0) && (data[0] != 1)) {
2514 comedi_error(dev,
2515 "Not a valid Data !!! ,Data should be 1 or 0\n");
2516 return -EINVAL;
2517 }
2518 if (ui_NoOfChannel > this_board->i_NbrDoChannel - 1) {
2519 comedi_error(dev,
2520 "This board doesn't have specified channel !!! \n");
2521 return -EINVAL;
2522 }
2523
2524 switch (data[1]) {
2525 case 1:
2526 data[0] = (data[0] << ui_NoOfChannel);
2527
2528 data[0] = (data[0] << 4) | devpriv->b_DigitalOutputRegister;
2529 break;
2530
2531 case 2:
2532 data[0] = ~data[0] & 0x1;
2533 ui_Temp1 = 1;
2534 ui_Temp1 = ui_Temp1 << ui_NoOfChannel;
2535 ui_Temp1 = ui_Temp1 << 4;
2536
2537 devpriv->b_DigitalOutputRegister =
2538 devpriv->b_DigitalOutputRegister | ui_Temp1;
2539
2540 data[0] = (data[0] << ui_NoOfChannel) ^ 0xf;
2541 data[0] = data[0] << 4;
2542
2543 data[0] = data[0] & devpriv->b_DigitalOutputRegister;
2544 break;
2545 default:
2546 printk("\nThe parameter passed is in error \n");
2547 return -EINVAL;
2548 }
2549 outb(data[0], devpriv->iobase + APCI3120_DIGITAL_OUTPUT);
2550
2551
2552 devpriv->b_DigitalOutputRegister = data[0] & 0xf0;
2553 return insn->n;
2554
2555}
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582int i_APCI3120_InsnWriteAnalogOutput(struct comedi_device *dev,
2583 struct comedi_subdevice *s,
2584 struct comedi_insn *insn,
2585 unsigned int *data)
2586{
2587 unsigned int ui_Range, ui_Channel;
2588 unsigned short us_TmpValue;
2589
2590 ui_Range = CR_RANGE(insn->chanspec);
2591 ui_Channel = CR_CHAN(insn->chanspec);
2592
2593
2594 if (ui_Range) {
2595
2596 if (data[0] != 0)
2597 data[0] =
2598 ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
2599 13) | (data[0] + 8191));
2600 else
2601 data[0] =
2602 ((((ui_Channel & 0x03) << 14) & 0xC000) | (1 <<
2603 13) | 8192);
2604
2605 } else {
2606 data[0] =
2607 ((((ui_Channel & 0x03) << 14) & 0xC000) | (0 << 13) |
2608 data[0]);
2609
2610 }
2611
2612
2613
2614
2615
2616 do {
2617 us_TmpValue =
2618 ((unsigned short) inw(devpriv->iobase +
2619 APCI3120_RD_STATUS)) & 0x0001;
2620 } while (us_TmpValue != 0x0001);
2621
2622 if (ui_Channel <= 3)
2623
2624
2625
2626
2627 outw((unsigned short) data[0],
2628 devpriv->iobase + APCI3120_ANALOG_OUTPUT_1);
2629 else
2630
2631
2632
2633
2634 outw((unsigned short) data[0],
2635 devpriv->iobase + APCI3120_ANALOG_OUTPUT_2);
2636
2637 return insn->n;
2638}
2639