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