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#include "../comedidev.h"
66
67#include <linux/delay.h>
68#include <linux/gfp.h>
69#include <linux/interrupt.h>
70
71#include "amcc_s5933.h"
72#include "8253.h"
73#include "comedi_pci.h"
74#include "comedi_fc.h"
75
76#define PCI_VENDOR_ID_AMCC 0x10e8
77
78
79#undef PCI9118_PARANOIDCHECK
80
81
82
83
84#undef PCI9118_EXTDEBUG
85
86
87
88
89#undef DPRINTK
90#ifdef PCI9118_EXTDEBUG
91#define DPRINTK(fmt, args...) printk(fmt, ## args)
92#else
93#define DPRINTK(fmt, args...)
94#endif
95
96#define IORANGE_9118 64
97#define PCI9118_CHANLEN 255
98
99
100
101
102#define PCI9118_CNT0 0x00
103#define PCI9118_CNT1 0x04
104#define PCI9118_CNT2 0x08
105#define PCI9118_CNTCTRL 0x0c
106#define PCI9118_AD_DATA 0x10
107#define PCI9118_DA1 0x10
108#define PCI9118_DA2 0x14
109#define PCI9118_ADSTAT 0x18
110#define PCI9118_ADCNTRL 0x18
111#define PCI9118_DI 0x1c
112#define PCI9118_DO 0x1c
113#define PCI9118_SOFTTRG 0x20
114#define PCI9118_GAIN 0x24
115#define PCI9118_BURST 0x28
116#define PCI9118_SCANMOD 0x2c
117#define PCI9118_ADFUNC 0x30
118#define PCI9118_DELFIFO 0x34
119#define PCI9118_INTSRC 0x38
120#define PCI9118_INTCTRL 0x38
121
122
123#define AdControl_UniP 0x80
124#define AdControl_Diff 0x40
125#define AdControl_SoftG 0x20
126#define AdControl_ExtG 0x10
127
128
129
130#define AdControl_ExtM 0x08
131
132
133
134#define AdControl_TmrTr 0x04
135
136
137
138
139#define AdControl_Int 0x02
140#define AdControl_Dma 0x01
141
142
143#define AdFunction_PDTrg 0x80
144
145
146
147
148#define AdFunction_PETrg 0x40
149
150
151
152
153#define AdFunction_BSSH 0x20
154#define AdFunction_BM 0x10
155#define AdFunction_BS 0x08
156
157
158
159#define AdFunction_PM 0x04
160
161
162
163#define AdFunction_AM 0x02
164
165
166
167#define AdFunction_Start 0x01
168
169
170#define AdStatus_nFull 0x100
171#define AdStatus_nHfull 0x080
172#define AdStatus_nEpty 0x040
173#define AdStatus_Acmp 0x020
174#define AdStatus_DTH 0x010
175#define AdStatus_Bover 0x008
176#define AdStatus_ADOS 0x004
177#define AdStatus_ADOR 0x002
178#define AdStatus_ADrdy 0x001
179
180
181
182#define Int_Timer 0x08
183#define Int_About 0x04
184#define Int_Hfull 0x02
185#define Int_DTrg 0x01
186
187#define START_AI_EXT 0x01
188#define STOP_AI_EXT 0x02
189#define START_AI_INT 0x04
190#define STOP_AI_INT 0x08
191
192#define EXTTRG_AI 0
193
194static const struct comedi_lrange range_pci9118dg_hr = { 8, {
195 BIP_RANGE(5),
196 BIP_RANGE(2.5),
197 BIP_RANGE(1.25),
198 BIP_RANGE(0.625),
199 UNI_RANGE(10),
200 UNI_RANGE(5),
201 UNI_RANGE(2.5),
202 UNI_RANGE(1.25)
203 }
204};
205
206static const struct comedi_lrange range_pci9118hg = { 8, {
207 BIP_RANGE(5),
208 BIP_RANGE(0.5),
209 BIP_RANGE(0.05),
210 BIP_RANGE(0.005),
211 UNI_RANGE(10),
212 UNI_RANGE(1),
213 UNI_RANGE(0.1),
214 UNI_RANGE(0.01)
215 }
216};
217
218#define PCI9118_BIPOLAR_RANGES 4
219
220
221
222
223static int pci9118_attach(struct comedi_device *dev,
224 struct comedi_devconfig *it);
225static int pci9118_detach(struct comedi_device *dev);
226
227struct boardtype {
228 const char *name;
229 int vendor_id;
230 int device_id;
231 int iorange_amcc;
232 int iorange_9118;
233 int n_aichan;
234 int n_aichand;
235 int mux_aichan;
236
237
238
239 int n_aichanlist;
240 int n_aochan;
241 int ai_maxdata;
242 int ao_maxdata;
243 const struct comedi_lrange *rangelist_ai;
244 const struct comedi_lrange *rangelist_ao;
245 unsigned int ai_ns_min;
246 unsigned int ai_pacer_min;
247
248
249
250 int half_fifo_size;
251
252};
253
254static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
255 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
256 { 0 }
257};
258
259MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
260
261static const struct boardtype boardtypes[] = {
262 {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
263 AMCC_OP_REG_SIZE, IORANGE_9118,
264 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
265 &range_pci9118dg_hr, &range_bipolar10,
266 3000, 12, 512},
267 {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
268 AMCC_OP_REG_SIZE, IORANGE_9118,
269 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
270 &range_pci9118hg, &range_bipolar10,
271 3000, 12, 512},
272 {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
273 AMCC_OP_REG_SIZE, IORANGE_9118,
274 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
275 &range_pci9118dg_hr, &range_bipolar10,
276 10000, 40, 512},
277};
278
279#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
280
281static struct comedi_driver driver_pci9118 = {
282 .driver_name = "adl_pci9118",
283 .module = THIS_MODULE,
284 .attach = pci9118_attach,
285 .detach = pci9118_detach,
286 .num_names = n_boardtypes,
287 .board_name = &boardtypes[0].name,
288 .offset = sizeof(struct boardtype),
289};
290
291static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
292 const struct pci_device_id *ent)
293{
294 return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
295}
296
297static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
298{
299 comedi_pci_auto_unconfig(dev);
300}
301
302static struct pci_driver driver_pci9118_pci_driver = {
303 .id_table = pci9118_pci_table,
304 .probe = &driver_pci9118_pci_probe,
305 .remove = __devexit_p(&driver_pci9118_pci_remove)
306};
307
308static int __init driver_pci9118_init_module(void)
309{
310 int retval;
311
312 retval = comedi_driver_register(&driver_pci9118);
313 if (retval < 0)
314 return retval;
315
316 driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
317 return pci_register_driver(&driver_pci9118_pci_driver);
318}
319
320static void __exit driver_pci9118_cleanup_module(void)
321{
322 pci_unregister_driver(&driver_pci9118_pci_driver);
323 comedi_driver_unregister(&driver_pci9118);
324}
325
326module_init(driver_pci9118_init_module);
327module_exit(driver_pci9118_cleanup_module);
328
329struct pci9118_private {
330 unsigned long iobase_a;
331 unsigned int master;
332 struct pci_dev *pcidev;
333 unsigned int usemux;
334#ifdef PCI9118_PARANOIDCHECK
335 unsigned short chanlist[PCI9118_CHANLEN + 1];
336
337
338
339 unsigned char chanlistlen;
340#endif
341 unsigned char AdControlReg;
342 unsigned char IntControlReg;
343 unsigned char AdFunctionReg;
344 char valid;
345 char ai_neverending;
346 unsigned int i8254_osc_base;
347 unsigned int ai_do;
348 unsigned int ai_act_scan;
349 unsigned int ai_buf_ptr;
350 unsigned int ai_n_chan;
351 unsigned int ai_n_scanlen;
352 unsigned int ai_n_realscanlen;
353
354
355
356 unsigned int ai_act_dmapos;
357 unsigned int ai_add_front;
358
359
360
361 unsigned int ai_add_back;
362
363
364
365 unsigned int *ai_chanlist;
366 unsigned int ai_timer1;
367 unsigned int ai_timer2;
368 unsigned int ai_flags;
369 char ai12_startstop;
370
371
372
373 unsigned int ai_divisor1, ai_divisor2;
374
375
376
377 unsigned int ai_data_len;
378 short *ai_data;
379 short ao_data[2];
380 unsigned int ai_scans;
381 char dma_doublebuf;
382 unsigned int dma_actbuf;
383 short *dmabuf_virt[2];
384
385
386
387 unsigned long dmabuf_hw[2];
388 unsigned int dmabuf_size[2];
389
390
391 unsigned int dmabuf_use_size[2];
392
393
394
395 unsigned int dmabuf_used_size[2];
396 unsigned int dmabuf_panic_size[2];
397 unsigned int dmabuf_samples[2];
398 int dmabuf_pages[2];
399 unsigned char cnt0_users;
400
401
402
403 unsigned char exttrg_users;
404
405
406
407 unsigned int cnt0_divisor;
408 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
409 unsigned short,
410 unsigned int,
411 unsigned short);
412
413
414
415 unsigned char ai16bits;
416 unsigned char usedma;
417 unsigned char useeoshandle;
418
419
420
421 unsigned char usessh;
422 int softsshdelay;
423
424
425
426 unsigned char softsshsample;
427
428
429
430 unsigned char softsshhold;
431
432
433
434 unsigned int ai_maskerr;
435 unsigned int ai_maskharderr;
436 unsigned int ai_inttrig_start;
437};
438
439#define devpriv ((struct pci9118_private *)dev->private)
440#define this_board ((struct boardtype *)dev->board_ptr)
441
442
443
444
445
446static int check_channel_list(struct comedi_device *dev,
447 struct comedi_subdevice *s, int n_chan,
448 unsigned int *chanlist, int frontadd,
449 int backadd);
450static int setup_channel_list(struct comedi_device *dev,
451 struct comedi_subdevice *s, int n_chan,
452 unsigned int *chanlist, int rot, int frontadd,
453 int backadd, int usedma, char eoshandle);
454static void start_pacer(struct comedi_device *dev, int mode,
455 unsigned int divisor1, unsigned int divisor2);
456static int pci9118_reset(struct comedi_device *dev);
457static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
458static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
459static int pci9118_ai_cancel(struct comedi_device *dev,
460 struct comedi_subdevice *s);
461static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
462 struct comedi_subdevice *s,
463 unsigned int *tim1, unsigned int *tim2,
464 unsigned int flags, int chans,
465 unsigned int *div1, unsigned int *div2,
466 char usessh, unsigned int chnsshfront);
467
468
469
470
471static int pci9118_insn_read_ai(struct comedi_device *dev,
472 struct comedi_subdevice *s,
473 struct comedi_insn *insn, unsigned int *data)
474{
475
476 int n, timeout;
477
478 devpriv->AdControlReg = AdControl_Int & 0xff;
479 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
480 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
481
482
483
484
485
486
487
488
489 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
490 return -EINVAL;
491
492 outl(0, dev->iobase + PCI9118_DELFIFO);
493
494 for (n = 0; n < insn->n; n++) {
495 outw(0, dev->iobase + PCI9118_SOFTTRG);
496 udelay(2);
497 timeout = 100;
498 while (timeout--) {
499 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
500 goto conv_finish;
501 udelay(1);
502 }
503
504 comedi_error(dev, "A/D insn timeout");
505 data[n] = 0;
506 outl(0, dev->iobase + PCI9118_DELFIFO);
507 return -ETIME;
508
509conv_finish:
510 if (devpriv->ai16bits) {
511 data[n] =
512 (inl(dev->iobase +
513 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
514 } else {
515 data[n] =
516 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
517 }
518 }
519
520 outl(0, dev->iobase + PCI9118_DELFIFO);
521 return n;
522
523}
524
525
526
527
528static int pci9118_insn_write_ao(struct comedi_device *dev,
529 struct comedi_subdevice *s,
530 struct comedi_insn *insn, unsigned int *data)
531{
532 int n, chanreg, ch;
533
534 ch = CR_CHAN(insn->chanspec);
535 if (ch)
536 chanreg = PCI9118_DA2;
537 else
538 chanreg = PCI9118_DA1;
539
540
541 for (n = 0; n < insn->n; n++) {
542 outl(data[n], dev->iobase + chanreg);
543 devpriv->ao_data[ch] = data[n];
544 }
545
546 return n;
547}
548
549
550
551
552static int pci9118_insn_read_ao(struct comedi_device *dev,
553 struct comedi_subdevice *s,
554 struct comedi_insn *insn, unsigned int *data)
555{
556 int n, chan;
557
558 chan = CR_CHAN(insn->chanspec);
559 for (n = 0; n < insn->n; n++)
560 data[n] = devpriv->ao_data[chan];
561
562 return n;
563}
564
565
566
567
568static int pci9118_insn_bits_di(struct comedi_device *dev,
569 struct comedi_subdevice *s,
570 struct comedi_insn *insn, unsigned int *data)
571{
572 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
573
574 return 2;
575}
576
577
578
579
580static int pci9118_insn_bits_do(struct comedi_device *dev,
581 struct comedi_subdevice *s,
582 struct comedi_insn *insn, unsigned int *data)
583{
584 if (data[0]) {
585 s->state &= ~data[0];
586 s->state |= (data[0] & data[1]);
587 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
588 }
589 data[1] = s->state;
590
591 return 2;
592}
593
594
595
596
597static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
598{
599 devpriv->AdFunctionReg =
600 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
601 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
602 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
603 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
604 dev->iobase + PCI9118_CNT0);
605 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
606 dev->iobase + PCI9118_CNT0);
607 devpriv->AdFunctionReg |= AdFunction_Start;
608 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
609}
610
611static unsigned int defragment_dma_buffer(struct comedi_device *dev,
612 struct comedi_subdevice *s,
613 short *dma_buffer,
614 unsigned int num_samples)
615{
616 unsigned int i = 0, j = 0;
617 unsigned int start_pos = devpriv->ai_add_front,
618 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
619 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
620 devpriv->ai_add_back;
621
622 for (i = 0; i < num_samples; i++) {
623 if (devpriv->ai_act_dmapos >= start_pos &&
624 devpriv->ai_act_dmapos < stop_pos) {
625 dma_buffer[j++] = dma_buffer[i];
626 }
627 devpriv->ai_act_dmapos++;
628 devpriv->ai_act_dmapos %= raw_scanlen;
629 }
630
631 return j;
632}
633
634
635
636
637static int move_block_from_dma(struct comedi_device *dev,
638 struct comedi_subdevice *s,
639 short *dma_buffer,
640 unsigned int num_samples)
641{
642 unsigned int num_bytes;
643
644 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
645 devpriv->ai_act_scan +=
646 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
647 s->async->cur_chan += num_samples;
648 s->async->cur_chan %= devpriv->ai_n_scanlen;
649 num_bytes =
650 cfc_write_array_to_buffer(s, dma_buffer,
651 num_samples * sizeof(short));
652 if (num_bytes < num_samples * sizeof(short))
653 return -1;
654 return 0;
655}
656
657
658
659
660static char pci9118_decode_error_status(struct comedi_device *dev,
661 struct comedi_subdevice *s,
662 unsigned char m)
663{
664 if (m & 0x100) {
665 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
666 devpriv->ai_maskerr &= ~0x100L;
667 }
668 if (m & 0x008) {
669 comedi_error(dev,
670 "A/D Burst Mode Overrun Status (Fatal Error!)");
671 devpriv->ai_maskerr &= ~0x008L;
672 }
673 if (m & 0x004) {
674 comedi_error(dev, "A/D Over Speed Status (Warning!)");
675 devpriv->ai_maskerr &= ~0x004L;
676 }
677 if (m & 0x002) {
678 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
679 devpriv->ai_maskerr &= ~0x002L;
680 }
681 if (m & devpriv->ai_maskharderr) {
682 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
683 pci9118_ai_cancel(dev, s);
684 comedi_event(dev, s);
685 return 1;
686 }
687
688 return 0;
689}
690
691static void pci9118_ai_munge(struct comedi_device *dev,
692 struct comedi_subdevice *s, void *data,
693 unsigned int num_bytes,
694 unsigned int start_chan_index)
695{
696 unsigned int i, num_samples = num_bytes / sizeof(short);
697 short *array = data;
698
699 for (i = 0; i < num_samples; i++) {
700 if (devpriv->usedma)
701 array[i] = be16_to_cpu(array[i]);
702 if (devpriv->ai16bits)
703 array[i] ^= 0x8000;
704 else
705 array[i] = (array[i] >> 4) & 0x0fff;
706
707 }
708}
709
710
711
712
713static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
714 struct comedi_subdevice *s,
715 unsigned short int_adstat,
716 unsigned int int_amcc,
717 unsigned short int_daq)
718{
719 register short sampl;
720
721 s->async->events = 0;
722
723 if (int_adstat & devpriv->ai_maskerr)
724 if (pci9118_decode_error_status(dev, s, int_adstat))
725 return;
726
727 sampl = inw(dev->iobase + PCI9118_AD_DATA);
728
729#ifdef PCI9118_PARANOIDCHECK
730 if (devpriv->ai16bits == 0) {
731 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
732
733 printk
734 ("comedi: A/D SAMPL - data dropout: "
735 "received channel %d, expected %d!\n",
736 sampl & 0x000f,
737 devpriv->chanlist[s->async->cur_chan]);
738 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
739 pci9118_ai_cancel(dev, s);
740 comedi_event(dev, s);
741 return;
742 }
743 }
744#endif
745 cfc_write_to_buffer(s, sampl);
746 s->async->cur_chan++;
747 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
748
749 s->async->cur_chan %= devpriv->ai_n_scanlen;
750 devpriv->ai_act_scan++;
751 if (!(devpriv->ai_neverending))
752 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
753
754 pci9118_ai_cancel(dev, s);
755 s->async->events |= COMEDI_CB_EOA;
756 }
757 }
758
759 if (s->async->events)
760 comedi_event(dev, s);
761}
762
763
764
765
766static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
767 struct comedi_subdevice *s,
768 unsigned short int_adstat,
769 unsigned int int_amcc,
770 unsigned short int_daq)
771{
772 unsigned int next_dma_buf, samplesinbuf, sampls, m;
773
774 if (int_amcc & MASTER_ABORT_INT) {
775 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
776 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
777 pci9118_ai_cancel(dev, s);
778 comedi_event(dev, s);
779 return;
780 }
781
782 if (int_amcc & TARGET_ABORT_INT) {
783 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
784 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
785 pci9118_ai_cancel(dev, s);
786 comedi_event(dev, s);
787 return;
788 }
789 if (int_adstat & devpriv->ai_maskerr)
790
791 if (pci9118_decode_error_status(dev, s, int_adstat))
792 return;
793
794 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
795
796
797
798 if (devpriv->dma_doublebuf) {
799
800
801
802 next_dma_buf = 1 - devpriv->dma_actbuf;
803 outl(devpriv->dmabuf_hw[next_dma_buf],
804 devpriv->iobase_a + AMCC_OP_REG_MWAR);
805 outl(devpriv->dmabuf_use_size[next_dma_buf],
806 devpriv->iobase_a + AMCC_OP_REG_MWTC);
807 devpriv->dmabuf_used_size[next_dma_buf] =
808 devpriv->dmabuf_use_size[next_dma_buf];
809 if (devpriv->ai_do == 4)
810 interrupt_pci9118_ai_mode4_switch(dev);
811 }
812
813 if (samplesinbuf) {
814 m = devpriv->ai_data_len >> 1;
815
816
817
818
819
820
821
822 sampls = m;
823 move_block_from_dma(dev, s,
824 devpriv->dmabuf_virt[devpriv->dma_actbuf],
825 samplesinbuf);
826 m = m - sampls;
827 }
828
829
830 if (!devpriv->ai_neverending)
831 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
832
833 pci9118_ai_cancel(dev, s);
834 s->async->events |= COMEDI_CB_EOA;
835 }
836
837 if (devpriv->dma_doublebuf) {
838 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
839 } else {
840 outl(devpriv->dmabuf_hw[0],
841 devpriv->iobase_a + AMCC_OP_REG_MWAR);
842 outl(devpriv->dmabuf_use_size[0],
843 devpriv->iobase_a + AMCC_OP_REG_MWTC);
844 if (devpriv->ai_do == 4)
845 interrupt_pci9118_ai_mode4_switch(dev);
846 }
847
848 comedi_event(dev, s);
849}
850
851
852
853
854static irqreturn_t interrupt_pci9118(int irq, void *d)
855{
856 struct comedi_device *dev = d;
857 unsigned int int_daq = 0, int_amcc, int_adstat;
858
859 if (!dev->attached)
860 return IRQ_NONE;
861
862 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
863
864 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
865
866
867
868
869
870
871
872
873
874
875 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
876 return IRQ_NONE;
877
878 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
879
880
881 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
882
883
884 if (devpriv->ai_do) {
885 if (devpriv->ai12_startstop)
886 if ((int_adstat & AdStatus_DTH) &&
887 (int_daq & Int_DTrg)) {
888
889 if (devpriv->ai12_startstop & START_AI_EXT) {
890 devpriv->ai12_startstop &=
891 ~START_AI_EXT;
892 if (!(devpriv->ai12_startstop &
893 STOP_AI_EXT))
894 pci9118_exttrg_del
895 (dev, EXTTRG_AI);
896
897 start_pacer(dev, devpriv->ai_do,
898 devpriv->ai_divisor1,
899 devpriv->ai_divisor2);
900
901 outl(devpriv->AdControlReg,
902 dev->iobase + PCI9118_ADCNTRL);
903 } else {
904 if (devpriv->ai12_startstop &
905 STOP_AI_EXT) {
906 devpriv->ai12_startstop &=
907 ~STOP_AI_EXT;
908 pci9118_exttrg_del
909 (dev, EXTTRG_AI);
910
911 devpriv->ai_neverending = 0;
912
913
914
915
916 }
917 }
918 }
919
920 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
921 int_amcc, int_daq);
922
923 }
924 return IRQ_HANDLED;
925}
926
927
928
929
930static int pci9118_ai_inttrig(struct comedi_device *dev,
931 struct comedi_subdevice *s, unsigned int trignum)
932{
933 if (trignum != devpriv->ai_inttrig_start)
934 return -EINVAL;
935
936 devpriv->ai12_startstop &= ~START_AI_INT;
937 s->async->inttrig = NULL;
938
939 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
940 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
941 if (devpriv->ai_do != 3) {
942 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
943 devpriv->ai_divisor2);
944 devpriv->AdControlReg |= AdControl_SoftG;
945 }
946 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
947
948 return 1;
949}
950
951
952
953
954static int pci9118_ai_cmdtest(struct comedi_device *dev,
955 struct comedi_subdevice *s,
956 struct comedi_cmd *cmd)
957{
958 int err = 0;
959 int tmp;
960 unsigned int divisor1 = 0, divisor2 = 0;
961
962
963
964 tmp = cmd->start_src;
965 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
966 if (!cmd->start_src || tmp != cmd->start_src)
967 err++;
968
969 tmp = cmd->scan_begin_src;
970 if (devpriv->master)
971 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
972 else
973 cmd->scan_begin_src &= TRIG_FOLLOW;
974
975 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
976 err++;
977
978 tmp = cmd->convert_src;
979 if (devpriv->master)
980 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
981 else
982 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
983
984 if (!cmd->convert_src || tmp != cmd->convert_src)
985 err++;
986
987 tmp = cmd->scan_end_src;
988 cmd->scan_end_src &= TRIG_COUNT;
989 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
990 err++;
991
992 tmp = cmd->stop_src;
993 cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
994 if (!cmd->stop_src || tmp != cmd->stop_src)
995 err++;
996
997 if (err)
998 return 1;
999
1000
1001
1002
1003
1004
1005
1006 if (cmd->start_src != TRIG_NOW &&
1007 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
1008 cmd->start_src = TRIG_NOW;
1009 err++;
1010 }
1011
1012 if (cmd->scan_begin_src != TRIG_TIMER &&
1013 cmd->scan_begin_src != TRIG_EXT &&
1014 cmd->scan_begin_src != TRIG_INT &&
1015 cmd->scan_begin_src != TRIG_FOLLOW) {
1016 cmd->scan_begin_src = TRIG_FOLLOW;
1017 err++;
1018 }
1019
1020 if (cmd->convert_src != TRIG_TIMER &&
1021 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
1022 cmd->convert_src = TRIG_TIMER;
1023 err++;
1024 }
1025
1026 if (cmd->scan_end_src != TRIG_COUNT) {
1027 cmd->scan_end_src = TRIG_COUNT;
1028 err++;
1029 }
1030
1031 if (cmd->stop_src != TRIG_NONE &&
1032 cmd->stop_src != TRIG_COUNT &&
1033 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
1034 cmd->stop_src = TRIG_COUNT;
1035 err++;
1036 }
1037
1038 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1039 cmd->start_src = TRIG_NOW;
1040 err++;
1041 }
1042
1043 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
1044 cmd->start_src = TRIG_NOW;
1045 err++;
1046 }
1047
1048 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1049 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
1050 cmd->convert_src = TRIG_TIMER;
1051 err++;
1052 }
1053
1054 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1055 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
1056 cmd->convert_src = TRIG_TIMER;
1057 err++;
1058 }
1059
1060 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1061 cmd->stop_src = TRIG_COUNT;
1062 err++;
1063 }
1064
1065 if (err)
1066 return 2;
1067
1068
1069
1070 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1071 if (cmd->start_arg != 0) {
1072 cmd->start_arg = 0;
1073 err++;
1074 }
1075
1076 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1077 if (cmd->scan_begin_arg != 0) {
1078 cmd->scan_begin_arg = 0;
1079 err++;
1080 }
1081
1082 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1083 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1084 cmd->scan_begin_src = TRIG_FOLLOW;
1085 cmd->convert_arg = cmd->scan_begin_arg;
1086 cmd->scan_begin_arg = 0;
1087 }
1088
1089 if (cmd->scan_begin_src == TRIG_TIMER)
1090 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1091 cmd->scan_begin_arg = this_board->ai_ns_min;
1092 err++;
1093 }
1094
1095 if (cmd->scan_begin_src == TRIG_EXT)
1096 if (cmd->scan_begin_arg) {
1097 cmd->scan_begin_arg = 0;
1098 err++;
1099 if (cmd->scan_end_arg > 65535) {
1100 cmd->scan_end_arg = 65535;
1101 err++;
1102 }
1103 }
1104
1105 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1106 if (cmd->convert_arg < this_board->ai_ns_min) {
1107 cmd->convert_arg = this_board->ai_ns_min;
1108 err++;
1109 }
1110
1111 if (cmd->convert_src == TRIG_EXT)
1112 if (cmd->convert_arg) {
1113 cmd->convert_arg = 0;
1114 err++;
1115 }
1116
1117 if (cmd->stop_src == TRIG_COUNT) {
1118 if (!cmd->stop_arg) {
1119 cmd->stop_arg = 1;
1120 err++;
1121 }
1122 } else {
1123 if (cmd->stop_arg != 0) {
1124 cmd->stop_arg = 0;
1125 err++;
1126 }
1127 }
1128
1129 if (!cmd->chanlist_len) {
1130 cmd->chanlist_len = 1;
1131 err++;
1132 }
1133
1134 if (cmd->chanlist_len > this_board->n_aichanlist) {
1135 cmd->chanlist_len = this_board->n_aichanlist;
1136 err++;
1137 }
1138
1139 if (cmd->scan_end_arg < cmd->chanlist_len) {
1140 cmd->scan_end_arg = cmd->chanlist_len;
1141 err++;
1142 }
1143
1144 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1145 cmd->scan_end_arg =
1146 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1147 err++;
1148 }
1149
1150 if (err)
1151 return 3;
1152
1153
1154
1155 if (cmd->scan_begin_src == TRIG_TIMER) {
1156 tmp = cmd->scan_begin_arg;
1157
1158 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1159 &divisor2, &cmd->scan_begin_arg,
1160 cmd->flags & TRIG_ROUND_MASK);
1161
1162 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1163 cmd->scan_begin_arg = this_board->ai_ns_min;
1164 if (tmp != cmd->scan_begin_arg)
1165 err++;
1166 }
1167
1168 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1169 tmp = cmd->convert_arg;
1170 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1171 &divisor2, &cmd->convert_arg,
1172 cmd->flags & TRIG_ROUND_MASK);
1173
1174 if (cmd->convert_arg < this_board->ai_ns_min)
1175 cmd->convert_arg = this_board->ai_ns_min;
1176 if (tmp != cmd->convert_arg)
1177 err++;
1178 if (cmd->scan_begin_src == TRIG_TIMER
1179 && cmd->convert_src == TRIG_NOW) {
1180 if (cmd->convert_arg == 0) {
1181 if (cmd->scan_begin_arg <
1182 this_board->ai_ns_min *
1183 (cmd->scan_end_arg + 2)) {
1184 cmd->scan_begin_arg =
1185 this_board->ai_ns_min *
1186 (cmd->scan_end_arg + 2);
1187
1188 err++;
1189 }
1190 } else {
1191 if (cmd->scan_begin_arg <
1192 cmd->convert_arg * cmd->chanlist_len) {
1193 cmd->scan_begin_arg =
1194 cmd->convert_arg *
1195 cmd->chanlist_len;
1196
1197 err++;
1198 }
1199 }
1200 }
1201 }
1202
1203 if (err)
1204 return 4;
1205
1206 if (cmd->chanlist)
1207 if (!check_channel_list(dev, s, cmd->chanlist_len,
1208 cmd->chanlist, 0, 0))
1209 return 5;
1210
1211 return 0;
1212}
1213
1214
1215
1216
1217static int Compute_and_setup_dma(struct comedi_device *dev)
1218{
1219 unsigned int dmalen0, dmalen1, i;
1220
1221 DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
1222 dmalen0 = devpriv->dmabuf_size[0];
1223 dmalen1 = devpriv->dmabuf_size[1];
1224 DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
1225 devpriv->ai_data_len);
1226
1227 if (dmalen0 > (devpriv->ai_data_len)) {
1228 dmalen0 = devpriv->ai_data_len & ~3L;
1229
1230
1231 }
1232 if (dmalen1 > (devpriv->ai_data_len)) {
1233 dmalen1 = devpriv->ai_data_len & ~3L;
1234
1235
1236 }
1237 DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1238
1239
1240 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1241 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1242
1243 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1244 printk
1245 ("comedi%d: WAR: DMA0 buf too short, can't "
1246 "support TRIG_WAKE_EOS (%d<%d)\n",
1247 dev->minor, dmalen0,
1248 devpriv->ai_n_realscanlen << 1);
1249 } else {
1250
1251 dmalen0 = devpriv->ai_n_realscanlen << 1;
1252 DPRINTK
1253 ("21 dmalen0=%d ai_n_realscanlen=%d "
1254 "useeoshandle=%d\n",
1255 dmalen0, devpriv->ai_n_realscanlen,
1256 devpriv->useeoshandle);
1257 if (devpriv->useeoshandle)
1258 dmalen0 += 2;
1259 if (dmalen0 < 4) {
1260 printk
1261 ("comedi%d: ERR: DMA0 buf len bug? "
1262 "(%d<4)\n",
1263 dev->minor, dmalen0);
1264 dmalen0 = 4;
1265 }
1266 }
1267 }
1268 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1269 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1270
1271 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1272 printk
1273 ("comedi%d: WAR: DMA1 buf too short, "
1274 "can't support TRIG_WAKE_EOS (%d<%d)\n",
1275 dev->minor, dmalen1,
1276 devpriv->ai_n_realscanlen << 1);
1277 } else {
1278
1279 dmalen1 = devpriv->ai_n_realscanlen << 1;
1280 DPRINTK
1281 ("22 dmalen1=%d ai_n_realscanlen=%d "
1282 "useeoshandle=%d\n",
1283 dmalen1, devpriv->ai_n_realscanlen,
1284 devpriv->useeoshandle);
1285 if (devpriv->useeoshandle)
1286 dmalen1 -= 2;
1287 if (dmalen1 < 4) {
1288 printk
1289 ("comedi%d: ERR: DMA1 buf len bug? "
1290 "(%d<4)\n",
1291 dev->minor, dmalen1);
1292 dmalen1 = 4;
1293 }
1294 }
1295 }
1296
1297 DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1298
1299 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1300
1301 i = dmalen0;
1302 dmalen0 =
1303 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1304 (devpriv->ai_n_realscanlen << 1);
1305 dmalen0 &= ~3L;
1306 if (!dmalen0)
1307 dmalen0 = i;
1308 i = dmalen1;
1309 dmalen1 =
1310 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1311 (devpriv->ai_n_realscanlen << 1);
1312 dmalen1 &= ~3L;
1313 if (!dmalen1)
1314 dmalen1 = i;
1315
1316
1317
1318
1319 if (!devpriv->ai_neverending) {
1320
1321 if (dmalen0 >
1322 ((devpriv->ai_n_realscanlen << 1) *
1323 devpriv->ai_scans)) {
1324 DPRINTK
1325 ("3.0 ai_n_realscanlen=%d ai_scans=%d\n",
1326 devpriv->ai_n_realscanlen,
1327 devpriv->ai_scans);
1328 dmalen0 =
1329 (devpriv->ai_n_realscanlen << 1) *
1330 devpriv->ai_scans;
1331 DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0,
1332 dmalen1);
1333 dmalen0 &= ~3L;
1334 } else {
1335
1336
1337
1338 if (dmalen1 >
1339 ((devpriv->ai_n_realscanlen << 1) *
1340 devpriv->ai_scans - dmalen0))
1341 dmalen1 =
1342 (devpriv->ai_n_realscanlen << 1) *
1343 devpriv->ai_scans - dmalen0;
1344 DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0,
1345 dmalen1);
1346 dmalen1 &= ~3L;
1347 }
1348 }
1349 }
1350
1351 DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1352
1353
1354 devpriv->dma_actbuf = 0;
1355 devpriv->dmabuf_use_size[0] = dmalen0;
1356 devpriv->dmabuf_use_size[1] = dmalen1;
1357
1358 DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1359#if 0
1360 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1361 devpriv->dmabuf_panic_size[0] =
1362 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1363 1) * devpriv->ai_n_scanlen * sizeof(short);
1364 devpriv->dmabuf_panic_size[1] =
1365 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1366 1) * devpriv->ai_n_scanlen * sizeof(short);
1367 } else {
1368 devpriv->dmabuf_panic_size[0] =
1369 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1370 devpriv->dmabuf_panic_size[1] =
1371 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1372 }
1373#endif
1374
1375 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1376 devpriv->iobase_a + AMCC_OP_REG_MCSR);
1377 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1378 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1379
1380 outl(0x00000000 | AINT_WRITE_COMPL,
1381 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1382
1383
1384 outl(inl(devpriv->iobase_a +
1385 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1386 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1387 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1388 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1389
1390
1391 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1392 return 0;
1393}
1394
1395
1396
1397
1398static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1399 struct comedi_subdevice *s)
1400{
1401 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
1402 dev->minor, devpriv->ai_do);
1403 switch (devpriv->ai_do) {
1404 case 1:
1405 devpriv->AdControlReg |= AdControl_TmrTr;
1406 break;
1407 case 2:
1408 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1409 return -EIO;
1410 case 3:
1411 devpriv->AdControlReg |= AdControl_ExtM;
1412 break;
1413 case 4:
1414 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1415 return -EIO;
1416 default:
1417 comedi_error(dev,
1418 "pci9118_ai_docmd_sampl() mode number bug!\n");
1419 return -EIO;
1420 };
1421
1422 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1423
1424
1425 if (devpriv->ai12_startstop)
1426 pci9118_exttrg_add(dev, EXTTRG_AI);
1427
1428
1429 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1430 devpriv->IntControlReg |= Int_Timer;
1431
1432 devpriv->AdControlReg |= AdControl_Int;
1433
1434 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1435 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1436
1437
1438 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1439 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1440 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1441 if (devpriv->ai_do != 3) {
1442 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1443 devpriv->ai_divisor2);
1444 devpriv->AdControlReg |= AdControl_SoftG;
1445 }
1446 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1447 }
1448
1449 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
1450 return 0;
1451}
1452
1453
1454
1455
1456static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1457 struct comedi_subdevice *s)
1458{
1459 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
1460 dev->minor, devpriv->ai_do, devpriv->usedma);
1461 Compute_and_setup_dma(dev);
1462
1463 switch (devpriv->ai_do) {
1464 case 1:
1465 devpriv->AdControlReg |=
1466 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1467 break;
1468 case 2:
1469 devpriv->AdControlReg |=
1470 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1471 devpriv->AdFunctionReg =
1472 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1473 AdFunction_BS;
1474 if (devpriv->usessh && (!devpriv->softsshdelay))
1475 devpriv->AdFunctionReg |= AdFunction_BSSH;
1476 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1477 break;
1478 case 3:
1479 devpriv->AdControlReg |=
1480 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1481 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1482 break;
1483 case 4:
1484 devpriv->AdControlReg |=
1485 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1486 devpriv->AdFunctionReg =
1487 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1488 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1489 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1490 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1491 dev->iobase + PCI9118_CNT0);
1492 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1493 dev->iobase + PCI9118_CNT0);
1494 devpriv->AdFunctionReg |= AdFunction_Start;
1495 break;
1496 default:
1497 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1498 return -EIO;
1499 };
1500
1501 if (devpriv->ai12_startstop) {
1502 pci9118_exttrg_add(dev, EXTTRG_AI);
1503
1504 }
1505
1506 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1507
1508
1509 outl(0x02000000 | AINT_WRITE_COMPL,
1510 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1511
1512 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1513 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1514 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1515 if (devpriv->ai_do != 3) {
1516 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1517 devpriv->ai_divisor2);
1518 devpriv->AdControlReg |= AdControl_SoftG;
1519 }
1520 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1521 }
1522
1523 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
1524 return 0;
1525}
1526
1527
1528
1529
1530static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1531{
1532 struct comedi_cmd *cmd = &s->async->cmd;
1533 unsigned int addchans = 0;
1534 int ret = 0;
1535
1536 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
1537 devpriv->ai12_startstop = 0;
1538 devpriv->ai_flags = cmd->flags;
1539 devpriv->ai_n_chan = cmd->chanlist_len;
1540 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1541 devpriv->ai_chanlist = cmd->chanlist;
1542 devpriv->ai_data = s->async->prealloc_buf;
1543 devpriv->ai_data_len = s->async->prealloc_bufsz;
1544 devpriv->ai_timer1 = 0;
1545 devpriv->ai_timer2 = 0;
1546 devpriv->ai_add_front = 0;
1547 devpriv->ai_add_back = 0;
1548 devpriv->ai_maskerr = 0x10e;
1549
1550
1551 if (cmd->start_src == TRIG_EXT)
1552 devpriv->ai12_startstop |= START_AI_EXT;
1553 if (cmd->stop_src == TRIG_EXT) {
1554 devpriv->ai_neverending = 1;
1555 devpriv->ai12_startstop |= STOP_AI_EXT;
1556 }
1557 if (cmd->start_src == TRIG_INT) {
1558 devpriv->ai12_startstop |= START_AI_INT;
1559 devpriv->ai_inttrig_start = cmd->start_arg;
1560 s->async->inttrig = pci9118_ai_inttrig;
1561 }
1562#if 0
1563 if (cmd->stop_src == TRIG_INT) {
1564 devpriv->ai_neverending = 1;
1565 devpriv->ai12_startstop |= STOP_AI_INT;
1566 }
1567#endif
1568 if (cmd->stop_src == TRIG_NONE)
1569 devpriv->ai_neverending = 1;
1570 if (cmd->stop_src == TRIG_COUNT) {
1571 devpriv->ai_scans = cmd->stop_arg;
1572 devpriv->ai_neverending = 0;
1573 } else {
1574 devpriv->ai_scans = 0;
1575 }
1576
1577
1578 if (cmd->convert_src == TRIG_NOW)
1579 devpriv->usessh = 1;
1580
1581 else
1582 devpriv->usessh = 0;
1583
1584
1585 DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
1586 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
1587 devpriv->ai12_startstop);
1588
1589
1590
1591
1592
1593 devpriv->ai_add_front = 0;
1594 devpriv->ai_add_back = 0;
1595 devpriv->useeoshandle = 0;
1596 if (devpriv->master) {
1597 devpriv->usedma = 1;
1598 if ((cmd->flags & TRIG_WAKE_EOS) &&
1599 (devpriv->ai_n_scanlen == 1)) {
1600 if (cmd->convert_src == TRIG_NOW)
1601 devpriv->ai_add_back = 1;
1602 if (cmd->convert_src == TRIG_TIMER) {
1603 devpriv->usedma = 0;
1604
1605
1606
1607
1608 }
1609 }
1610 if ((cmd->flags & TRIG_WAKE_EOS) &&
1611 (devpriv->ai_n_scanlen & 1) &&
1612 (devpriv->ai_n_scanlen > 1)) {
1613 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1614
1615
1616
1617
1618 devpriv->usedma = 0;
1619
1620
1621
1622 } else {
1623
1624
1625
1626 devpriv->ai_add_back = 1;
1627 }
1628 }
1629 } else {
1630 devpriv->usedma = 0;
1631 }
1632
1633
1634
1635
1636
1637 if (devpriv->usessh && devpriv->softsshdelay) {
1638 devpriv->ai_add_front = 2;
1639 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1640
1641 devpriv->ai_add_front++;
1642 devpriv->ai_add_back = 0;
1643 }
1644 if (cmd->convert_arg < this_board->ai_ns_min)
1645 cmd->convert_arg = this_board->ai_ns_min;
1646 addchans = devpriv->softsshdelay / cmd->convert_arg;
1647 if (devpriv->softsshdelay % cmd->convert_arg)
1648 addchans++;
1649 if (addchans > (devpriv->ai_add_front - 1)) {
1650
1651 devpriv->ai_add_front = addchans + 1;
1652 if (devpriv->usedma == 1)
1653 if ((devpriv->ai_add_front +
1654 devpriv->ai_n_chan +
1655 devpriv->ai_add_back) & 1)
1656 devpriv->ai_add_front++;
1657
1658 }
1659 }
1660
1661 devpriv->ai_n_realscanlen =
1662
1663
1664
1665 (devpriv->ai_add_front + devpriv->ai_n_chan +
1666 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1667 devpriv->ai_n_chan);
1668
1669 DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
1670 devpriv->usedma,
1671 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
1672 devpriv->ai_n_chan, devpriv->ai_add_back,
1673 devpriv->ai_n_scanlen);
1674
1675
1676 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1677 devpriv->ai_chanlist, devpriv->ai_add_front,
1678 devpriv->ai_add_back))
1679 return -EINVAL;
1680 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1681 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1682 devpriv->ai_add_back, devpriv->usedma,
1683 devpriv->useeoshandle))
1684 return -EINVAL;
1685
1686
1687
1688
1689
1690
1691 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1692 (cmd->scan_begin_src == TRIG_EXT) ||
1693 (cmd->scan_begin_src == TRIG_INT)) &&
1694 (cmd->convert_src == TRIG_TIMER)) {
1695
1696 if (cmd->scan_begin_src == TRIG_EXT)
1697 devpriv->ai_do = 4;
1698 else
1699 devpriv->ai_do = 1;
1700 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1701 &cmd->scan_begin_arg, &cmd->convert_arg,
1702 devpriv->ai_flags,
1703 devpriv->ai_n_realscanlen,
1704 &devpriv->ai_divisor1,
1705 &devpriv->ai_divisor2, devpriv->usessh,
1706 devpriv->ai_add_front);
1707 devpriv->ai_timer2 = cmd->convert_arg;
1708 }
1709
1710 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1711 ((cmd->convert_src == TRIG_TIMER) ||
1712 (cmd->convert_src == TRIG_NOW))) {
1713
1714 if (!devpriv->usedma) {
1715 comedi_error(dev,
1716 "cmd->scan_begin_src=TRIG_TIMER works "
1717 "only with bus mastering!");
1718 return -EIO;
1719 }
1720
1721 devpriv->ai_do = 2;
1722 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1723 &cmd->scan_begin_arg, &cmd->convert_arg,
1724 devpriv->ai_flags,
1725 devpriv->ai_n_realscanlen,
1726 &devpriv->ai_divisor1,
1727 &devpriv->ai_divisor2, devpriv->usessh,
1728 devpriv->ai_add_front);
1729 devpriv->ai_timer1 = cmd->scan_begin_arg;
1730 devpriv->ai_timer2 = cmd->convert_arg;
1731 }
1732
1733 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1734 && (cmd->convert_src == TRIG_EXT)) {
1735 devpriv->ai_do = 3;
1736 }
1737
1738 start_pacer(dev, -1, 0, 0);
1739
1740 devpriv->AdControlReg = 0;
1741
1742
1743
1744
1745 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1746 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1747
1748
1749
1750
1751
1752 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1753 udelay(1);
1754 outl(0, dev->iobase + PCI9118_DELFIFO);
1755 inl(dev->iobase + PCI9118_ADSTAT);
1756
1757
1758
1759 inl(dev->iobase + PCI9118_INTSRC);
1760
1761 devpriv->ai_act_scan = 0;
1762 devpriv->ai_act_dmapos = 0;
1763 s->async->cur_chan = 0;
1764 devpriv->ai_buf_ptr = 0;
1765
1766 if (devpriv->usedma)
1767 ret = pci9118_ai_docmd_dma(dev, s);
1768 else
1769 ret = pci9118_ai_docmd_sampl(dev, s);
1770
1771 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1772 return ret;
1773}
1774
1775
1776
1777
1778static int check_channel_list(struct comedi_device *dev,
1779 struct comedi_subdevice *s, int n_chan,
1780 unsigned int *chanlist, int frontadd, int backadd)
1781{
1782 unsigned int i, differencial = 0, bipolar = 0;
1783
1784
1785 if (n_chan < 1) {
1786 comedi_error(dev, "range/channel list is empty!");
1787 return 0;
1788 }
1789 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
1790 printk
1791 ("comedi%d: range/channel list is too long for "
1792 "actual configuration (%d>%d)!",
1793 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
1794 return 0;
1795 }
1796
1797 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1798 differencial = 1;
1799 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1800 bipolar = 1;
1801 if (n_chan > 1)
1802 for (i = 1; i < n_chan; i++) {
1803 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
1804 (differencial)) {
1805 comedi_error(dev,
1806 "Differencial and single ended "
1807 "inputs can't be mixtured!");
1808 return 0;
1809 }
1810 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
1811 (bipolar)) {
1812 comedi_error(dev,
1813 "Bipolar and unipolar ranges "
1814 "can't be mixtured!");
1815 return 0;
1816 }
1817 if ((!devpriv->usemux) & (differencial) &
1818 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
1819 comedi_error(dev,
1820 "If AREF_DIFF is used then is "
1821 "available only first 8 channels!");
1822 return 0;
1823 }
1824 }
1825
1826 return 1;
1827}
1828
1829
1830
1831
1832static int setup_channel_list(struct comedi_device *dev,
1833 struct comedi_subdevice *s, int n_chan,
1834 unsigned int *chanlist, int rot, int frontadd,
1835 int backadd, int usedma, char useeos)
1836{
1837 unsigned int i, differencial = 0, bipolar = 0;
1838 unsigned int scanquad, gain, ssh = 0x00;
1839
1840 DPRINTK
1841 ("adl_pci9118 EDBG: BGN: setup_channel_list"
1842 "(%d,.,%d,.,%d,%d,%d,%d)\n",
1843 dev->minor, n_chan, rot, frontadd, backadd, usedma);
1844
1845 if (usedma == 1) {
1846 rot = 8;
1847 usedma = 0;
1848 }
1849
1850 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1851 differencial = 1;
1852 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1853 bipolar = 1;
1854
1855
1856
1857 if (!bipolar) {
1858 devpriv->AdControlReg |= AdControl_UniP;
1859
1860 } else {
1861 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
1862
1863 }
1864
1865 if (differencial) {
1866 devpriv->AdControlReg |= AdControl_Diff;
1867
1868 } else {
1869 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
1870
1871 }
1872
1873 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1874
1875
1876 outl(2, dev->iobase + PCI9118_SCANMOD);
1877
1878 outl(0, dev->iobase + PCI9118_SCANMOD);
1879 outl(1, dev->iobase + PCI9118_SCANMOD);
1880
1881#ifdef PCI9118_PARANOIDCHECK
1882 devpriv->chanlistlen = n_chan;
1883 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
1884 devpriv->chanlist[i] = 0x55aa;
1885#endif
1886
1887 if (frontadd) {
1888 ssh = devpriv->softsshsample;
1889 DPRINTK("FA: %04x: ", ssh);
1890 for (i = 0; i < frontadd; i++) {
1891
1892 scanquad = CR_CHAN(chanlist[0]);
1893
1894 gain = CR_RANGE(chanlist[0]);
1895
1896 scanquad |= ((gain & 0x03) << 8);
1897 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1898 DPRINTK("%02x ", scanquad | ssh);
1899 ssh = devpriv->softsshhold;
1900 }
1901 DPRINTK("\n ");
1902 }
1903
1904 DPRINTK("SL: ", ssh);
1905 for (i = 0; i < n_chan; i++) {
1906 scanquad = CR_CHAN(chanlist[i]);
1907#ifdef PCI9118_PARANOIDCHECK
1908 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1909#endif
1910 gain = CR_RANGE(chanlist[i]);
1911 scanquad |= ((gain & 0x03) << 8);
1912 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1913 DPRINTK("%02x ", scanquad | ssh);
1914 }
1915 DPRINTK("\n ");
1916
1917 if (backadd) {
1918 DPRINTK("BA: %04x: ", ssh);
1919 for (i = 0; i < backadd; i++) {
1920 scanquad = CR_CHAN(chanlist[0]);
1921
1922 gain = CR_RANGE(chanlist[0]);
1923 scanquad |= ((gain & 0x03) << 8);
1924 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1925 DPRINTK("%02x ", scanquad | ssh);
1926 }
1927 DPRINTK("\n ");
1928 }
1929#ifdef PCI9118_PARANOIDCHECK
1930 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
1931
1932 if (useeos) {
1933 for (i = 1; i < n_chan; i++) {
1934 devpriv->chanlist[(n_chan + i) ^ usedma] =
1935 (CR_CHAN(chanlist[i]) & 0xf) << rot;
1936 }
1937 devpriv->chanlist[(2 * n_chan) ^ usedma] =
1938 devpriv->chanlist[0 ^ usedma];
1939
1940 useeos = 2;
1941 } else {
1942 useeos = 1;
1943 }
1944#ifdef PCI9118_EXTDEBUG
1945 DPRINTK("CHL: ");
1946 for (i = 0; i <= (useeos * n_chan); i++)
1947 DPRINTK("%04x ", devpriv->chanlist[i]);
1948
1949 DPRINTK("\n ");
1950#endif
1951#endif
1952 outl(0, dev->iobase + PCI9118_SCANMOD);
1953
1954
1955 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1956 return 1;
1957}
1958
1959
1960
1961
1962
1963static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1964 struct comedi_subdevice *s,
1965 unsigned int *tim1, unsigned int *tim2,
1966 unsigned int flags, int chans,
1967 unsigned int *div1, unsigned int *div2,
1968 char usessh, unsigned int chnsshfront)
1969{
1970 DPRINTK
1971 ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors"
1972 "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
1973 mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
1974 switch (mode) {
1975 case 1:
1976 case 4:
1977 if (*tim2 < this_board->ai_ns_min)
1978 *tim2 = this_board->ai_ns_min;
1979 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
1980 tim2, flags & TRIG_ROUND_NEAREST);
1981 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
1982 devpriv->i8254_osc_base, *div1, *div2, *tim1);
1983 break;
1984 case 2:
1985 if (*tim2 < this_board->ai_ns_min)
1986 *tim2 = this_board->ai_ns_min;
1987 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1988 *tim1, *tim2);
1989 *div1 = *tim2 / devpriv->i8254_osc_base;
1990
1991 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1992 *tim1, *tim2);
1993 if (*div1 < this_board->ai_pacer_min)
1994 *div1 = this_board->ai_pacer_min;
1995 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1996 *tim1, *tim2);
1997 *div2 = *tim1 / devpriv->i8254_osc_base;
1998 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1999 *tim1, *tim2);
2000 *div2 = *div2 / *div1;
2001 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2002 *tim1, *tim2);
2003 if (*div2 < chans)
2004 *div2 = chans;
2005 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2006 *tim1, *tim2);
2007
2008 *tim2 = *div1 * devpriv->i8254_osc_base;
2009
2010
2011 if (usessh & (chnsshfront == 0))
2012 if (*div2 < (chans + 2))
2013 *div2 = chans + 2;
2014
2015 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2016 *tim1, *tim2);
2017 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
2018 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
2019 devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
2020 break;
2021 }
2022 DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
2023 *div1, *div2);
2024}
2025
2026
2027
2028
2029static void start_pacer(struct comedi_device *dev, int mode,
2030 unsigned int divisor1, unsigned int divisor2)
2031{
2032 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
2033 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
2034
2035 udelay(1);
2036
2037 if ((mode == 1) || (mode == 2) || (mode == 4)) {
2038 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
2039 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
2040 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
2041 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
2042 }
2043}
2044
2045
2046
2047
2048static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
2049{
2050 if (source > 3)
2051 return -1;
2052 devpriv->exttrg_users |= (1 << source);
2053 devpriv->IntControlReg |= Int_DTrg;
2054 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2055 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2056 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2057
2058 return 0;
2059}
2060
2061
2062
2063
2064static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
2065{
2066 if (source > 3)
2067 return -1;
2068 devpriv->exttrg_users &= ~(1 << source);
2069 if (!devpriv->exttrg_users) {
2070 devpriv->IntControlReg &= ~Int_DTrg;
2071 if (!devpriv->IntControlReg)
2072 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
2073 (~0x00001f00),
2074 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2075
2076 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2077 }
2078 return 0;
2079}
2080
2081
2082
2083
2084static int pci9118_ai_cancel(struct comedi_device *dev,
2085 struct comedi_subdevice *s)
2086{
2087 if (devpriv->usedma)
2088 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
2089 (~EN_A2P_TRANSFERS),
2090 devpriv->iobase_a + AMCC_OP_REG_MCSR);
2091 pci9118_exttrg_del(dev, EXTTRG_AI);
2092 start_pacer(dev, 0, 0, 0);
2093 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2094 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2095
2096
2097
2098
2099
2100 devpriv->AdControlReg = 0x00;
2101 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2102
2103
2104
2105
2106
2107 outl(0, dev->iobase + PCI9118_BURST);
2108 outl(1, dev->iobase + PCI9118_SCANMOD);
2109 outl(2, dev->iobase + PCI9118_SCANMOD);
2110 outl(0, dev->iobase + PCI9118_DELFIFO);
2111
2112 devpriv->ai_do = 0;
2113 devpriv->usedma = 0;
2114
2115 devpriv->ai_act_scan = 0;
2116 devpriv->ai_act_dmapos = 0;
2117 s->async->cur_chan = 0;
2118 s->async->inttrig = NULL;
2119 devpriv->ai_buf_ptr = 0;
2120 devpriv->ai_neverending = 0;
2121 devpriv->dma_actbuf = 0;
2122
2123 if (!devpriv->IntControlReg)
2124 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2125 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2126
2127
2128 return 0;
2129}
2130
2131
2132
2133
2134static int pci9118_reset(struct comedi_device *dev)
2135{
2136 devpriv->IntControlReg = 0;
2137 devpriv->exttrg_users = 0;
2138 inl(dev->iobase + PCI9118_INTCTRL);
2139 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2140
2141 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
2142
2143 start_pacer(dev, 0, 0, 0);
2144 devpriv->AdControlReg = 0;
2145 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2146
2147
2148
2149
2150
2151
2152 outl(0, dev->iobase + PCI9118_BURST);
2153 outl(1, dev->iobase + PCI9118_SCANMOD);
2154 outl(2, dev->iobase + PCI9118_SCANMOD);
2155 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2156 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2157
2158
2159
2160
2161
2162
2163
2164
2165 devpriv->ao_data[0] = 2047;
2166 devpriv->ao_data[1] = 2047;
2167 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
2168
2169 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
2170 outl(0, dev->iobase + PCI9118_DO);
2171 udelay(10);
2172 inl(dev->iobase + PCI9118_AD_DATA);
2173 outl(0, dev->iobase + PCI9118_DELFIFO);
2174 outl(0, dev->iobase + PCI9118_INTSRC);
2175 inl(dev->iobase + PCI9118_ADSTAT);
2176 inl(dev->iobase + PCI9118_INTSRC);
2177 devpriv->AdControlReg = 0;
2178 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2179
2180
2181
2182
2183
2184
2185
2186 devpriv->cnt0_users = 0;
2187 devpriv->exttrg_users = 0;
2188
2189 return 0;
2190}
2191
2192
2193
2194
2195static int pci9118_attach(struct comedi_device *dev,
2196 struct comedi_devconfig *it)
2197{
2198 struct comedi_subdevice *s;
2199 int ret, pages, i;
2200 unsigned short master;
2201 unsigned int irq;
2202 unsigned long iobase_a, iobase_9;
2203 struct pci_dev *pcidev;
2204 int opt_bus, opt_slot;
2205 const char *errstr;
2206 unsigned char pci_bus, pci_slot, pci_func;
2207 u16 u16w;
2208
2209 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
2210
2211 opt_bus = it->options[0];
2212 opt_slot = it->options[1];
2213 if (it->options[3] & 1)
2214 master = 0;
2215 else
2216 master = 1;
2217
2218 ret = alloc_private(dev, sizeof(struct pci9118_private));
2219 if (ret < 0) {
2220 printk(" - Allocation failed!\n");
2221 return -ENOMEM;
2222 }
2223
2224
2225 errstr = "not found!";
2226 pcidev = NULL;
2227 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC,
2228 this_board->device_id,
2229 pcidev))) {
2230
2231 if (opt_bus || opt_slot) {
2232
2233 if (opt_bus != pcidev->bus->number
2234 || opt_slot != PCI_SLOT(pcidev->devfn))
2235 continue;
2236 }
2237
2238
2239
2240
2241 if (comedi_pci_enable(pcidev, "adl_pci9118")) {
2242 errstr =
2243 "failed to enable PCI device and request regions!";
2244 continue;
2245 }
2246 break;
2247 }
2248
2249 if (!pcidev) {
2250 if (opt_bus || opt_slot) {
2251 printk(KERN_ERR " - Card at b:s %d:%d %s\n",
2252 opt_bus, opt_slot, errstr);
2253 } else {
2254 printk(KERN_ERR " - Card %s\n", errstr);
2255 }
2256 return -EIO;
2257 }
2258
2259 if (master)
2260 pci_set_master(pcidev);
2261
2262
2263 pci_bus = pcidev->bus->number;
2264 pci_slot = PCI_SLOT(pcidev->devfn);
2265 pci_func = PCI_FUNC(pcidev->devfn);
2266 irq = pcidev->irq;
2267 iobase_a = pci_resource_start(pcidev, 0);
2268 iobase_9 = pci_resource_start(pcidev, 2);
2269
2270 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus,
2271 pci_slot, pci_func, iobase_9, iobase_a);
2272
2273 dev->iobase = iobase_9;
2274 dev->board_name = this_board->name;
2275
2276 devpriv->pcidev = pcidev;
2277 devpriv->iobase_a = iobase_a;
2278
2279 pci9118_reset(dev);
2280
2281 if (it->options[3] & 2)
2282 irq = 0;
2283 if (irq > 0) {
2284 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
2285 "ADLink PCI-9118", dev)) {
2286 printk(", unable to allocate IRQ %d, DISABLING IT",
2287 irq);
2288 irq = 0;
2289 } else {
2290 printk(", irq=%u", irq);
2291 }
2292 } else {
2293 printk(", IRQ disabled");
2294 }
2295
2296 dev->irq = irq;
2297
2298 if (master) {
2299 devpriv->dma_doublebuf = 0;
2300 for (i = 0; i < 2; i++) {
2301 for (pages = 4; pages >= 0; pages--) {
2302 devpriv->dmabuf_virt[i] =
2303 (short *)__get_free_pages(GFP_KERNEL,
2304 pages);
2305 if (devpriv->dmabuf_virt[i])
2306 break;
2307 }
2308 if (devpriv->dmabuf_virt[i]) {
2309 devpriv->dmabuf_pages[i] = pages;
2310 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2311 devpriv->dmabuf_samples[i] =
2312 devpriv->dmabuf_size[i] >> 1;
2313 devpriv->dmabuf_hw[i] =
2314 virt_to_bus((void *)
2315 devpriv->dmabuf_virt[i]);
2316 }
2317 }
2318 if (!devpriv->dmabuf_virt[0]) {
2319 printk(", Can't allocate DMA buffer, DMA disabled!");
2320 master = 0;
2321 }
2322
2323 if (devpriv->dmabuf_virt[1])
2324 devpriv->dma_doublebuf = 1;
2325
2326 }
2327
2328 devpriv->master = master;
2329 if (devpriv->master)
2330 printk(", bus master");
2331 else
2332 printk(", no bus master");
2333
2334 devpriv->usemux = 0;
2335 if (it->options[2] > 0) {
2336 devpriv->usemux = it->options[2];
2337 if (devpriv->usemux > 256)
2338 devpriv->usemux = 256;
2339 if (it->options[4] > 0)
2340 if (devpriv->usemux > 128) {
2341 devpriv->usemux = 128;
2342
2343 }
2344 printk(", ext. mux %d channels", devpriv->usemux);
2345 }
2346
2347 devpriv->softsshdelay = it->options[4];
2348 if (devpriv->softsshdelay < 0) {
2349
2350 devpriv->softsshdelay = -devpriv->softsshdelay;
2351 devpriv->softsshsample = 0x80;
2352 devpriv->softsshhold = 0x00;
2353 } else {
2354 devpriv->softsshsample = 0x00;
2355 devpriv->softsshhold = 0x80;
2356 }
2357
2358 printk(".\n");
2359
2360 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
2361 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);
2362
2363
2364 ret = alloc_subdevices(dev, 4);
2365 if (ret < 0)
2366 return ret;
2367
2368 s = dev->subdevices + 0;
2369 dev->read_subdev = s;
2370 s->type = COMEDI_SUBD_AI;
2371 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2372 if (devpriv->usemux)
2373 s->n_chan = devpriv->usemux;
2374 else
2375 s->n_chan = this_board->n_aichan;
2376
2377 s->maxdata = this_board->ai_maxdata;
2378 s->len_chanlist = this_board->n_aichanlist;
2379 s->range_table = this_board->rangelist_ai;
2380 s->cancel = pci9118_ai_cancel;
2381 s->insn_read = pci9118_insn_read_ai;
2382 if (dev->irq) {
2383 s->subdev_flags |= SDF_CMD_READ;
2384 s->do_cmdtest = pci9118_ai_cmdtest;
2385 s->do_cmd = pci9118_ai_cmd;
2386 s->munge = pci9118_ai_munge;
2387 }
2388
2389 s = dev->subdevices + 1;
2390 s->type = COMEDI_SUBD_AO;
2391 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2392 s->n_chan = this_board->n_aochan;
2393 s->maxdata = this_board->ao_maxdata;
2394 s->len_chanlist = this_board->n_aochan;
2395 s->range_table = this_board->rangelist_ao;
2396 s->insn_write = pci9118_insn_write_ao;
2397 s->insn_read = pci9118_insn_read_ao;
2398
2399 s = dev->subdevices + 2;
2400 s->type = COMEDI_SUBD_DI;
2401 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2402 s->n_chan = 4;
2403 s->maxdata = 1;
2404 s->len_chanlist = 4;
2405 s->range_table = &range_digital;
2406 s->io_bits = 0;
2407 s->insn_bits = pci9118_insn_bits_di;
2408
2409 s = dev->subdevices + 3;
2410 s->type = COMEDI_SUBD_DO;
2411 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2412 s->n_chan = 4;
2413 s->maxdata = 1;
2414 s->len_chanlist = 4;
2415 s->range_table = &range_digital;
2416 s->io_bits = 0xf;
2417 s->insn_bits = pci9118_insn_bits_do;
2418
2419 devpriv->valid = 1;
2420 devpriv->i8254_osc_base = 250;
2421 devpriv->ai_maskharderr = 0x10a;
2422
2423 if (it->options[5])
2424 devpriv->ai_maskharderr &= ~it->options[5];
2425
2426 switch (this_board->ai_maxdata) {
2427 case 0xffff:
2428 devpriv->ai16bits = 1;
2429 break;
2430 default:
2431 devpriv->ai16bits = 0;
2432 break;
2433 }
2434 return 0;
2435}
2436
2437
2438
2439
2440static int pci9118_detach(struct comedi_device *dev)
2441{
2442 if (dev->private) {
2443 if (devpriv->valid)
2444 pci9118_reset(dev);
2445 if (dev->irq)
2446 free_irq(dev->irq, dev);
2447 if (devpriv->pcidev) {
2448 if (dev->iobase)
2449 comedi_pci_disable(devpriv->pcidev);
2450
2451 pci_dev_put(devpriv->pcidev);
2452 }
2453 if (devpriv->dmabuf_virt[0])
2454 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2455 devpriv->dmabuf_pages[0]);
2456 if (devpriv->dmabuf_virt[1])
2457 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2458 devpriv->dmabuf_pages[1]);
2459 }
2460
2461 return 0;
2462}
2463
2464
2465
2466
2467
2468MODULE_AUTHOR("Comedi http://www.comedi.org");
2469MODULE_DESCRIPTION("Comedi low-level driver");
2470MODULE_LICENSE("GPL");
2471