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#include <linux/pci.h>
45#include <linux/interrupt.h>
46
47#include "../comedidev.h"
48
49#include "comedi_fc.h"
50#include "8253.h"
51#include "amcc_s5933.h"
52
53#define PCI171x_PARANOIDCHECK
54
55
56
57
58#define TYPE_PCI171X 0
59#define TYPE_PCI1713 2
60#define TYPE_PCI1720 3
61
62#define PCI171x_AD_DATA 0
63#define PCI171x_SOFTTRG 0
64#define PCI171x_RANGE 2
65#define PCI171x_MUX 4
66#define PCI171x_STATUS 6
67#define PCI171x_CONTROL 6
68#define PCI171x_CLRINT 8
69#define PCI171x_CLRFIFO 9
70#define PCI171x_DA1 10
71#define PCI171x_DA2 12
72#define PCI171x_DAREF 14
73#define PCI171x_DI 16
74#define PCI171x_DO 16
75#define PCI171x_CNT0 24
76#define PCI171x_CNT1 26
77#define PCI171x_CNT2 28
78#define PCI171x_CNTCTRL 30
79
80
81
82#define Status_FE 0x0100
83#define Status_FH 0x0200
84#define Status_FF 0x0400
85#define Status_IRQ 0x0800
86
87#define Control_CNT0 0x0040
88
89#define Control_ONEFH 0x0020
90#define Control_IRQEN 0x0010
91#define Control_GATE 0x0008
92#define Control_EXT 0x0004
93#define Control_PACER 0x0002
94#define Control_SW 0x0001
95
96#define Counter_BCD 0x0001
97#define Counter_M0 0x0002
98#define Counter_M1 0x0004
99#define Counter_M2 0x0008
100#define Counter_RW0 0x0010
101#define Counter_RW1 0x0020
102#define Counter_SC0 0x0040
103#define Counter_SC1 0x0080
104
105
106#define PCI1720_DA0 0
107#define PCI1720_DA1 2
108#define PCI1720_DA2 4
109#define PCI1720_DA3 6
110#define PCI1720_RANGE 8
111#define PCI1720_SYNCOUT 9
112#define PCI1720_SYNCONT 15
113
114
115#define Syncont_SC0 1
116
117static const struct comedi_lrange range_pci1710_3 = { 9, {
118 BIP_RANGE(5),
119 BIP_RANGE(2.5),
120 BIP_RANGE(1.25),
121 BIP_RANGE(0.625),
122 BIP_RANGE(10),
123 UNI_RANGE(10),
124 UNI_RANGE(5),
125 UNI_RANGE(2.5),
126 UNI_RANGE(1.25)
127 }
128};
129
130static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
131 0x10, 0x11, 0x12, 0x13 };
132
133static const struct comedi_lrange range_pci1710hg = { 12, {
134 BIP_RANGE(5),
135 BIP_RANGE(0.5),
136 BIP_RANGE(0.05),
137 BIP_RANGE(0.005),
138 BIP_RANGE(10),
139 BIP_RANGE(1),
140 BIP_RANGE(0.1),
141 BIP_RANGE(0.01),
142 UNI_RANGE(10),
143 UNI_RANGE(1),
144 UNI_RANGE(0.1),
145 UNI_RANGE(0.01)
146 }
147};
148
149static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
150 0x05, 0x06, 0x07, 0x10, 0x11,
151 0x12, 0x13 };
152
153static const struct comedi_lrange range_pci17x1 = { 5, {
154 BIP_RANGE(10),
155 BIP_RANGE(5),
156 BIP_RANGE(2.5),
157 BIP_RANGE(1.25),
158 BIP_RANGE(0.625)
159 }
160};
161
162static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
163
164static const struct comedi_lrange range_pci1720 = { 4, {
165 UNI_RANGE(5),
166 UNI_RANGE(10),
167 BIP_RANGE(5),
168 BIP_RANGE(10)
169 }
170};
171
172static const struct comedi_lrange range_pci171x_da = { 2, {
173 UNI_RANGE(5),
174 UNI_RANGE(10),
175 }
176};
177
178enum pci1710_boardid {
179 BOARD_PCI1710,
180 BOARD_PCI1710HG,
181 BOARD_PCI1711,
182 BOARD_PCI1713,
183 BOARD_PCI1720,
184 BOARD_PCI1731,
185};
186
187struct boardtype {
188 const char *name;
189 char have_irq;
190 char cardtype;
191 int n_aichan;
192 int n_aichand;
193 int n_aochan;
194 int n_dichan;
195 int n_dochan;
196 int n_counter;
197 int ai_maxdata;
198 int ao_maxdata;
199 const struct comedi_lrange *rangelist_ai;
200 const char *rangecode_ai;
201 const struct comedi_lrange *rangelist_ao;
202 unsigned int ai_ns_min;
203 unsigned int fifo_half_size;
204};
205
206static const struct boardtype boardtypes[] = {
207 [BOARD_PCI1710] = {
208 .name = "pci1710",
209 .have_irq = 1,
210 .cardtype = TYPE_PCI171X,
211 .n_aichan = 16,
212 .n_aichand = 8,
213 .n_aochan = 2,
214 .n_dichan = 16,
215 .n_dochan = 16,
216 .n_counter = 1,
217 .ai_maxdata = 0x0fff,
218 .ao_maxdata = 0x0fff,
219 .rangelist_ai = &range_pci1710_3,
220 .rangecode_ai = range_codes_pci1710_3,
221 .rangelist_ao = &range_pci171x_da,
222 .ai_ns_min = 10000,
223 .fifo_half_size = 2048,
224 },
225 [BOARD_PCI1710HG] = {
226 .name = "pci1710hg",
227 .have_irq = 1,
228 .cardtype = TYPE_PCI171X,
229 .n_aichan = 16,
230 .n_aichand = 8,
231 .n_aochan = 2,
232 .n_dichan = 16,
233 .n_dochan = 16,
234 .n_counter = 1,
235 .ai_maxdata = 0x0fff,
236 .ao_maxdata = 0x0fff,
237 .rangelist_ai = &range_pci1710hg,
238 .rangecode_ai = range_codes_pci1710hg,
239 .rangelist_ao = &range_pci171x_da,
240 .ai_ns_min = 10000,
241 .fifo_half_size = 2048,
242 },
243 [BOARD_PCI1711] = {
244 .name = "pci1711",
245 .have_irq = 1,
246 .cardtype = TYPE_PCI171X,
247 .n_aichan = 16,
248 .n_aochan = 2,
249 .n_dichan = 16,
250 .n_dochan = 16,
251 .n_counter = 1,
252 .ai_maxdata = 0x0fff,
253 .ao_maxdata = 0x0fff,
254 .rangelist_ai = &range_pci17x1,
255 .rangecode_ai = range_codes_pci17x1,
256 .rangelist_ao = &range_pci171x_da,
257 .ai_ns_min = 10000,
258 .fifo_half_size = 512,
259 },
260 [BOARD_PCI1713] = {
261 .name = "pci1713",
262 .have_irq = 1,
263 .cardtype = TYPE_PCI1713,
264 .n_aichan = 32,
265 .n_aichand = 16,
266 .ai_maxdata = 0x0fff,
267 .rangelist_ai = &range_pci1710_3,
268 .rangecode_ai = range_codes_pci1710_3,
269 .ai_ns_min = 10000,
270 .fifo_half_size = 2048,
271 },
272 [BOARD_PCI1720] = {
273 .name = "pci1720",
274 .cardtype = TYPE_PCI1720,
275 .n_aochan = 4,
276 .ao_maxdata = 0x0fff,
277 .rangelist_ao = &range_pci1720,
278 },
279 [BOARD_PCI1731] = {
280 .name = "pci1731",
281 .have_irq = 1,
282 .cardtype = TYPE_PCI171X,
283 .n_aichan = 16,
284 .n_dichan = 16,
285 .n_dochan = 16,
286 .ai_maxdata = 0x0fff,
287 .rangelist_ai = &range_pci17x1,
288 .rangecode_ai = range_codes_pci17x1,
289 .ai_ns_min = 10000,
290 .fifo_half_size = 512,
291 },
292};
293
294struct pci1710_private {
295 char neverending_ai;
296 unsigned int CntrlReg;
297 unsigned int i8254_osc_base;
298 unsigned int ai_do;
299 unsigned int ai_act_scan;
300 unsigned int ai_act_chan;
301 unsigned int ai_buf_ptr;
302 unsigned char ai_eos;
303 unsigned char ai_et;
304 unsigned int ai_et_CntrlReg;
305 unsigned int ai_et_MuxVal;
306 unsigned int ai_et_div1, ai_et_div2;
307 unsigned int act_chanlist[32];
308 unsigned char act_chanlist_len;
309 unsigned char act_chanlist_pos;
310 unsigned char da_ranges;
311 unsigned int ai_scans;
312 unsigned int ai_n_chan;
313 unsigned int *ai_chanlist;
314 unsigned int ai_flags;
315 unsigned int ai_data_len;
316 short *ai_data;
317 unsigned int ai_timer1;
318 unsigned int ai_timer2;
319 short ao_data[4];
320 unsigned int cnt0_write_wait;
321
322};
323
324
325static const unsigned int muxonechan[] = {
326 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
327 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
328 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
329 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
330};
331
332
333
334
335
336
337
338static int check_channel_list(struct comedi_device *dev,
339 struct comedi_subdevice *s,
340 unsigned int *chanlist, unsigned int n_chan)
341{
342 unsigned int chansegment[32];
343 unsigned int i, nowmustbechan, seglen, segpos;
344
345
346 if (n_chan < 1) {
347 comedi_error(dev, "range/channel list is empty!");
348 return 0;
349 }
350
351 if (n_chan == 1)
352 return 1;
353
354 chansegment[0] = chanlist[0];
355 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
356 if (chanlist[0] == chanlist[i])
357 break;
358 if ((CR_CHAN(chanlist[i]) & 1) &&
359 (CR_AREF(chanlist[i]) == AREF_DIFF)) {
360 comedi_error(dev, "Odd channel cannot be differential input!\n");
361 return 0;
362 }
363 nowmustbechan = (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
364 if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
365 nowmustbechan = (nowmustbechan + 1) % s->n_chan;
366 if (nowmustbechan != CR_CHAN(chanlist[i])) {
367 printk("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
368 i, CR_CHAN(chanlist[i]), nowmustbechan,
369 CR_CHAN(chanlist[0]));
370 return 0;
371 }
372 chansegment[i] = chanlist[i];
373 }
374
375 for (i = 0, segpos = 0; i < n_chan; i++) {
376 if (chanlist[i] != chansegment[i % seglen]) {
377 printk("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
378 i, CR_CHAN(chansegment[i]),
379 CR_RANGE(chansegment[i]),
380 CR_AREF(chansegment[i]),
381 CR_CHAN(chanlist[i % seglen]),
382 CR_RANGE(chanlist[i % seglen]),
383 CR_AREF(chansegment[i % seglen]));
384 return 0;
385 }
386 }
387 return seglen;
388}
389
390static void setup_channel_list(struct comedi_device *dev,
391 struct comedi_subdevice *s,
392 unsigned int *chanlist, unsigned int n_chan,
393 unsigned int seglen)
394{
395 const struct boardtype *this_board = comedi_board(dev);
396 struct pci1710_private *devpriv = dev->private;
397 unsigned int i, range, chanprog;
398
399 devpriv->act_chanlist_len = seglen;
400 devpriv->act_chanlist_pos = 0;
401
402 for (i = 0; i < seglen; i++) {
403 chanprog = muxonechan[CR_CHAN(chanlist[i])];
404 outw(chanprog, dev->iobase + PCI171x_MUX);
405 range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
406 if (CR_AREF(chanlist[i]) == AREF_DIFF)
407 range |= 0x0020;
408 outw(range, dev->iobase + PCI171x_RANGE);
409#ifdef PCI171x_PARANOIDCHECK
410 devpriv->act_chanlist[i] =
411 (CR_CHAN(chanlist[i]) << 12) & 0xf000;
412#endif
413 }
414#ifdef PCI171x_PARANOIDCHECK
415 for ( ; i < n_chan; i++) {
416 devpriv->act_chanlist[i] =
417 (CR_CHAN(chanlist[i]) << 12) & 0xf000;
418 }
419#endif
420
421 devpriv->ai_et_MuxVal =
422 CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
423
424 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
425}
426
427
428
429
430static int pci171x_insn_read_ai(struct comedi_device *dev,
431 struct comedi_subdevice *s,
432 struct comedi_insn *insn, unsigned int *data)
433{
434 struct pci1710_private *devpriv = dev->private;
435 int n, timeout;
436#ifdef PCI171x_PARANOIDCHECK
437 const struct boardtype *this_board = comedi_board(dev);
438 unsigned int idata;
439#endif
440
441 devpriv->CntrlReg &= Control_CNT0;
442 devpriv->CntrlReg |= Control_SW;
443 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
444 outb(0, dev->iobase + PCI171x_CLRFIFO);
445 outb(0, dev->iobase + PCI171x_CLRINT);
446
447 setup_channel_list(dev, s, &insn->chanspec, 1, 1);
448
449 for (n = 0; n < insn->n; n++) {
450 outw(0, dev->iobase + PCI171x_SOFTTRG);
451
452 timeout = 100;
453 while (timeout--) {
454 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE))
455 goto conv_finish;
456 }
457 comedi_error(dev, "A/D insn timeout");
458 outb(0, dev->iobase + PCI171x_CLRFIFO);
459 outb(0, dev->iobase + PCI171x_CLRINT);
460 data[n] = 0;
461 return -ETIME;
462
463conv_finish:
464#ifdef PCI171x_PARANOIDCHECK
465 idata = inw(dev->iobase + PCI171x_AD_DATA);
466 if (this_board->cardtype != TYPE_PCI1713)
467 if ((idata & 0xf000) != devpriv->act_chanlist[0]) {
468 comedi_error(dev, "A/D insn data droput!");
469 return -ETIME;
470 }
471 data[n] = idata & 0x0fff;
472#else
473 data[n] = inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff;
474#endif
475
476 }
477
478 outb(0, dev->iobase + PCI171x_CLRFIFO);
479 outb(0, dev->iobase + PCI171x_CLRINT);
480
481 return n;
482}
483
484
485
486
487static int pci171x_insn_write_ao(struct comedi_device *dev,
488 struct comedi_subdevice *s,
489 struct comedi_insn *insn, unsigned int *data)
490{
491 struct pci1710_private *devpriv = dev->private;
492 int n, chan, range, ofs;
493
494 chan = CR_CHAN(insn->chanspec);
495 range = CR_RANGE(insn->chanspec);
496 if (chan) {
497 devpriv->da_ranges &= 0xfb;
498 devpriv->da_ranges |= (range << 2);
499 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
500 ofs = PCI171x_DA2;
501 } else {
502 devpriv->da_ranges &= 0xfe;
503 devpriv->da_ranges |= range;
504 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
505 ofs = PCI171x_DA1;
506 }
507
508 for (n = 0; n < insn->n; n++)
509 outw(data[n], dev->iobase + ofs);
510
511 devpriv->ao_data[chan] = data[n];
512
513 return n;
514
515}
516
517
518
519
520static int pci171x_insn_read_ao(struct comedi_device *dev,
521 struct comedi_subdevice *s,
522 struct comedi_insn *insn, unsigned int *data)
523{
524 struct pci1710_private *devpriv = dev->private;
525 int n, chan;
526
527 chan = CR_CHAN(insn->chanspec);
528 for (n = 0; n < insn->n; n++)
529 data[n] = devpriv->ao_data[chan];
530
531 return n;
532}
533
534
535
536
537static int pci171x_insn_bits_di(struct comedi_device *dev,
538 struct comedi_subdevice *s,
539 struct comedi_insn *insn, unsigned int *data)
540{
541 data[1] = inw(dev->iobase + PCI171x_DI);
542
543 return insn->n;
544}
545
546
547
548
549static int pci171x_insn_bits_do(struct comedi_device *dev,
550 struct comedi_subdevice *s,
551 struct comedi_insn *insn, unsigned int *data)
552{
553 if (data[0]) {
554 s->state &= ~data[0];
555 s->state |= (data[0] & data[1]);
556 outw(s->state, dev->iobase + PCI171x_DO);
557 }
558 data[1] = s->state;
559
560 return insn->n;
561}
562
563
564
565
566static void start_pacer(struct comedi_device *dev, int mode,
567 unsigned int divisor1, unsigned int divisor2)
568{
569 outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
570 outw(0x74, dev->iobase + PCI171x_CNTCTRL);
571
572 if (mode == 1) {
573 outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
574 outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
575 outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
576 outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
577 }
578}
579
580
581
582
583static int pci171x_insn_counter_read(struct comedi_device *dev,
584 struct comedi_subdevice *s,
585 struct comedi_insn *insn,
586 unsigned int *data)
587{
588 unsigned int msb, lsb, ccntrl;
589 int i;
590
591 ccntrl = 0xD2;
592 for (i = 0; i < insn->n; i++) {
593 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
594
595 lsb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
596 msb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
597
598 data[0] = lsb | (msb << 8);
599 }
600
601 return insn->n;
602}
603
604
605
606
607static int pci171x_insn_counter_write(struct comedi_device *dev,
608 struct comedi_subdevice *s,
609 struct comedi_insn *insn,
610 unsigned int *data)
611{
612 struct pci1710_private *devpriv = dev->private;
613 uint msb, lsb, ccntrl, status;
614
615 lsb = data[0] & 0x00FF;
616 msb = (data[0] & 0xFF00) >> 8;
617
618
619 outw(lsb, dev->iobase + PCI171x_CNT0);
620 outw(msb, dev->iobase + PCI171x_CNT0);
621
622 if (devpriv->cnt0_write_wait) {
623
624 ccntrl = 0xE2;
625 do {
626 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
627 status = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
628 } while (status & 0x40);
629 }
630
631 return insn->n;
632}
633
634
635
636
637static int pci171x_insn_counter_config(struct comedi_device *dev,
638 struct comedi_subdevice *s,
639 struct comedi_insn *insn,
640 unsigned int *data)
641{
642#ifdef unused
643
644 struct pci1710_private *devpriv = dev->private;
645 uint ccntrl = 0;
646
647 devpriv->cnt0_write_wait = data[0] & 0x20;
648
649
650 if (!(data[0] & 0x10)) {
651 devpriv->CntrlReg &= ~Control_CNT0;
652 } else {
653 devpriv->CntrlReg |= Control_CNT0;
654 }
655 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
656
657 if (data[0] & 0x01)
658 ccntrl |= Counter_M0;
659 if (data[0] & 0x02)
660 ccntrl |= Counter_M1;
661 if (data[0] & 0x04)
662 ccntrl |= Counter_M2;
663 if (data[0] & 0x08)
664 ccntrl |= Counter_BCD;
665 ccntrl |= Counter_RW0;
666 ccntrl |= Counter_RW1;
667 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
668#endif
669
670 return 1;
671}
672
673
674
675
676static int pci1720_insn_write_ao(struct comedi_device *dev,
677 struct comedi_subdevice *s,
678 struct comedi_insn *insn, unsigned int *data)
679{
680 struct pci1710_private *devpriv = dev->private;
681 int n, rangereg, chan;
682
683 chan = CR_CHAN(insn->chanspec);
684 rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1)));
685 rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1));
686 if (rangereg != devpriv->da_ranges) {
687 outb(rangereg, dev->iobase + PCI1720_RANGE);
688 devpriv->da_ranges = rangereg;
689 }
690
691 for (n = 0; n < insn->n; n++) {
692 outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
693 outb(0, dev->iobase + PCI1720_SYNCOUT);
694 }
695
696 devpriv->ao_data[chan] = data[n];
697
698 return n;
699}
700
701
702
703
704static int pci171x_ai_cancel(struct comedi_device *dev,
705 struct comedi_subdevice *s)
706{
707 const struct boardtype *this_board = comedi_board(dev);
708 struct pci1710_private *devpriv = dev->private;
709
710 switch (this_board->cardtype) {
711 default:
712 devpriv->CntrlReg &= Control_CNT0;
713 devpriv->CntrlReg |= Control_SW;
714
715 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
716 start_pacer(dev, -1, 0, 0);
717 outb(0, dev->iobase + PCI171x_CLRFIFO);
718 outb(0, dev->iobase + PCI171x_CLRINT);
719 break;
720 }
721
722 devpriv->ai_do = 0;
723 devpriv->ai_act_scan = 0;
724 s->async->cur_chan = 0;
725 devpriv->ai_buf_ptr = 0;
726 devpriv->neverending_ai = 0;
727
728 return 0;
729}
730
731
732
733
734static void interrupt_pci1710_every_sample(void *d)
735{
736 struct comedi_device *dev = d;
737 struct pci1710_private *devpriv = dev->private;
738 struct comedi_subdevice *s = &dev->subdevices[0];
739 int m;
740#ifdef PCI171x_PARANOIDCHECK
741 const struct boardtype *this_board = comedi_board(dev);
742 short sampl;
743#endif
744
745 m = inw(dev->iobase + PCI171x_STATUS);
746 if (m & Status_FE) {
747 printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m);
748 pci171x_ai_cancel(dev, s);
749 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
750 comedi_event(dev, s);
751 return;
752 }
753 if (m & Status_FF) {
754 printk
755 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n",
756 dev->minor, m);
757 pci171x_ai_cancel(dev, s);
758 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
759 comedi_event(dev, s);
760 return;
761 }
762
763 outb(0, dev->iobase + PCI171x_CLRINT);
764
765 for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) {
766#ifdef PCI171x_PARANOIDCHECK
767 sampl = inw(dev->iobase + PCI171x_AD_DATA);
768 if (this_board->cardtype != TYPE_PCI1713)
769 if ((sampl & 0xf000) !=
770 devpriv->act_chanlist[s->async->cur_chan]) {
771 printk
772 ("comedi: A/D data dropout: received data from channel %d, expected %d!\n",
773 (sampl & 0xf000) >> 12,
774 (devpriv->
775 act_chanlist[s->
776 async->cur_chan] & 0xf000) >>
777 12);
778 pci171x_ai_cancel(dev, s);
779 s->async->events |=
780 COMEDI_CB_EOA | COMEDI_CB_ERROR;
781 comedi_event(dev, s);
782 return;
783 }
784 comedi_buf_put(s->async, sampl & 0x0fff);
785#else
786 comedi_buf_put(s->async,
787 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff);
788#endif
789 ++s->async->cur_chan;
790
791 if (s->async->cur_chan >= devpriv->ai_n_chan)
792 s->async->cur_chan = 0;
793
794
795 if (s->async->cur_chan == 0) {
796 devpriv->ai_act_scan++;
797 if ((!devpriv->neverending_ai) &&
798 (devpriv->ai_act_scan >= devpriv->ai_scans)) {
799
800 pci171x_ai_cancel(dev, s);
801 s->async->events |= COMEDI_CB_EOA;
802 comedi_event(dev, s);
803 return;
804 }
805 }
806 }
807
808 outb(0, dev->iobase + PCI171x_CLRINT);
809
810 comedi_event(dev, s);
811}
812
813
814
815
816static int move_block_from_fifo(struct comedi_device *dev,
817 struct comedi_subdevice *s, int n, int turn)
818{
819 struct pci1710_private *devpriv = dev->private;
820 int i, j;
821#ifdef PCI171x_PARANOIDCHECK
822 const struct boardtype *this_board = comedi_board(dev);
823 int sampl;
824#endif
825
826 j = s->async->cur_chan;
827 for (i = 0; i < n; i++) {
828#ifdef PCI171x_PARANOIDCHECK
829 sampl = inw(dev->iobase + PCI171x_AD_DATA);
830 if (this_board->cardtype != TYPE_PCI1713)
831 if ((sampl & 0xf000) != devpriv->act_chanlist[j]) {
832 printk
833 ("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n",
834 dev->minor, (sampl & 0xf000) >> 12,
835 (devpriv->act_chanlist[j] & 0xf000) >> 12,
836 i, j, devpriv->ai_act_scan, n, turn,
837 sampl);
838 pci171x_ai_cancel(dev, s);
839 s->async->events |=
840 COMEDI_CB_EOA | COMEDI_CB_ERROR;
841 comedi_event(dev, s);
842 return 1;
843 }
844 comedi_buf_put(s->async, sampl & 0x0fff);
845#else
846 comedi_buf_put(s->async,
847 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff);
848#endif
849 j++;
850 if (j >= devpriv->ai_n_chan) {
851 j = 0;
852 devpriv->ai_act_scan++;
853 }
854 }
855 s->async->cur_chan = j;
856 return 0;
857}
858
859
860
861
862static void interrupt_pci1710_half_fifo(void *d)
863{
864 struct comedi_device *dev = d;
865 const struct boardtype *this_board = comedi_board(dev);
866 struct pci1710_private *devpriv = dev->private;
867 struct comedi_subdevice *s = &dev->subdevices[0];
868 int m, samplesinbuf;
869
870 m = inw(dev->iobase + PCI171x_STATUS);
871 if (!(m & Status_FH)) {
872 printk("comedi%d: A/D FIFO not half full! (%4x)\n",
873 dev->minor, m);
874 pci171x_ai_cancel(dev, s);
875 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
876 comedi_event(dev, s);
877 return;
878 }
879 if (m & Status_FF) {
880 printk
881 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n",
882 dev->minor, m);
883 pci171x_ai_cancel(dev, s);
884 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
885 comedi_event(dev, s);
886 return;
887 }
888
889 samplesinbuf = this_board->fifo_half_size;
890 if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) {
891 m = devpriv->ai_data_len / sizeof(short);
892 if (move_block_from_fifo(dev, s, m, 0))
893 return;
894 samplesinbuf -= m;
895 }
896
897 if (samplesinbuf) {
898 if (move_block_from_fifo(dev, s, samplesinbuf, 1))
899 return;
900 }
901
902 if (!devpriv->neverending_ai)
903 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
904
905 pci171x_ai_cancel(dev, s);
906 s->async->events |= COMEDI_CB_EOA;
907 comedi_event(dev, s);
908 return;
909 }
910 outb(0, dev->iobase + PCI171x_CLRINT);
911
912 comedi_event(dev, s);
913}
914
915
916
917
918static irqreturn_t interrupt_service_pci1710(int irq, void *d)
919{
920 struct comedi_device *dev = d;
921 struct pci1710_private *devpriv = dev->private;
922
923 if (!dev->attached)
924 return IRQ_NONE;
925
926 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
927 return IRQ_NONE;
928
929 if (devpriv->ai_et) {
930 devpriv->ai_et = 0;
931 devpriv->CntrlReg &= Control_CNT0;
932 devpriv->CntrlReg |= Control_SW;
933 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
934 devpriv->CntrlReg = devpriv->ai_et_CntrlReg;
935 outb(0, dev->iobase + PCI171x_CLRFIFO);
936 outb(0, dev->iobase + PCI171x_CLRINT);
937 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
938 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
939
940 start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2);
941 return IRQ_HANDLED;
942 }
943 if (devpriv->ai_eos) {
944 interrupt_pci1710_every_sample(d);
945 } else {
946 interrupt_pci1710_half_fifo(d);
947 }
948 return IRQ_HANDLED;
949}
950
951
952
953
954static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
955 struct comedi_subdevice *s)
956{
957 const struct boardtype *this_board = comedi_board(dev);
958 struct pci1710_private *devpriv = dev->private;
959 unsigned int divisor1 = 0, divisor2 = 0;
960 unsigned int seglen;
961
962 start_pacer(dev, -1, 0, 0);
963
964 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
965 devpriv->ai_n_chan);
966 if (seglen < 1)
967 return -EINVAL;
968 setup_channel_list(dev, s, devpriv->ai_chanlist,
969 devpriv->ai_n_chan, seglen);
970
971 outb(0, dev->iobase + PCI171x_CLRFIFO);
972 outb(0, dev->iobase + PCI171x_CLRINT);
973
974 devpriv->ai_do = mode;
975
976 devpriv->ai_act_scan = 0;
977 s->async->cur_chan = 0;
978 devpriv->ai_buf_ptr = 0;
979 devpriv->neverending_ai = 0;
980
981 devpriv->CntrlReg &= Control_CNT0;
982
983 if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
984 devpriv->ai_eos = 1;
985 } else {
986 devpriv->CntrlReg |= Control_ONEFH;
987 devpriv->ai_eos = 0;
988 }
989
990 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
991 devpriv->neverending_ai = 1;
992
993 else
994 devpriv->neverending_ai = 0;
995
996 switch (mode) {
997 case 1:
998 case 2:
999 if (devpriv->ai_timer1 < this_board->ai_ns_min)
1000 devpriv->ai_timer1 = this_board->ai_ns_min;
1001 devpriv->CntrlReg |= Control_PACER | Control_IRQEN;
1002 if (mode == 2) {
1003 devpriv->ai_et_CntrlReg = devpriv->CntrlReg;
1004 devpriv->CntrlReg &=
1005 ~(Control_PACER | Control_ONEFH | Control_GATE);
1006 devpriv->CntrlReg |= Control_EXT;
1007 devpriv->ai_et = 1;
1008 } else {
1009 devpriv->ai_et = 0;
1010 }
1011 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1012 &divisor2, &devpriv->ai_timer1,
1013 devpriv->ai_flags & TRIG_ROUND_MASK);
1014 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
1015 if (mode != 2) {
1016
1017 start_pacer(dev, mode, divisor1, divisor2);
1018 } else {
1019 devpriv->ai_et_div1 = divisor1;
1020 devpriv->ai_et_div2 = divisor2;
1021 }
1022 break;
1023 case 3:
1024 devpriv->CntrlReg |= Control_EXT | Control_IRQEN;
1025 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
1026 break;
1027 }
1028
1029 return 0;
1030}
1031
1032
1033
1034
1035static int pci171x_ai_cmdtest(struct comedi_device *dev,
1036 struct comedi_subdevice *s,
1037 struct comedi_cmd *cmd)
1038{
1039 const struct boardtype *this_board = comedi_board(dev);
1040 struct pci1710_private *devpriv = dev->private;
1041 int err = 0;
1042 int tmp;
1043 unsigned int divisor1 = 0, divisor2 = 0;
1044
1045
1046
1047 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
1048 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
1049 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
1050 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1051 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1052
1053 if (err)
1054 return 1;
1055
1056
1057
1058 err |= cfc_check_trigger_is_unique(cmd->start_src);
1059 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1060 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1061
1062
1063
1064 if (err)
1065 return 2;
1066
1067
1068
1069 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1070 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1071
1072 if (cmd->convert_src == TRIG_TIMER)
1073 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1074 this_board->ai_ns_min);
1075 else
1076 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1077
1078 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1079
1080 if (cmd->stop_src == TRIG_COUNT)
1081 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1082 else
1083 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1084
1085 if (err)
1086 return 3;
1087
1088
1089
1090 if (cmd->convert_src == TRIG_TIMER) {
1091 tmp = cmd->convert_arg;
1092 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1093 &divisor2, &cmd->convert_arg,
1094 cmd->flags & TRIG_ROUND_MASK);
1095 if (cmd->convert_arg < this_board->ai_ns_min)
1096 cmd->convert_arg = this_board->ai_ns_min;
1097 if (tmp != cmd->convert_arg)
1098 err++;
1099 }
1100
1101 if (err)
1102 return 4;
1103
1104
1105
1106 if (cmd->chanlist) {
1107 if (!check_channel_list(dev, s, cmd->chanlist,
1108 cmd->chanlist_len))
1109 return 5;
1110 }
1111
1112 return 0;
1113}
1114
1115
1116
1117
1118static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1119{
1120 struct pci1710_private *devpriv = dev->private;
1121 struct comedi_cmd *cmd = &s->async->cmd;
1122
1123 devpriv->ai_n_chan = cmd->chanlist_len;
1124 devpriv->ai_chanlist = cmd->chanlist;
1125 devpriv->ai_flags = cmd->flags;
1126 devpriv->ai_data_len = s->async->prealloc_bufsz;
1127 devpriv->ai_data = s->async->prealloc_buf;
1128 devpriv->ai_timer1 = 0;
1129 devpriv->ai_timer2 = 0;
1130
1131 if (cmd->stop_src == TRIG_COUNT)
1132 devpriv->ai_scans = cmd->stop_arg;
1133 else
1134 devpriv->ai_scans = 0;
1135
1136
1137 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1138 if (cmd->convert_src == TRIG_TIMER) {
1139 devpriv->ai_timer1 = cmd->convert_arg;
1140 return pci171x_ai_docmd_and_mode(cmd->start_src ==
1141 TRIG_EXT ? 2 : 1, dev,
1142 s);
1143 }
1144 if (cmd->convert_src == TRIG_EXT) {
1145 return pci171x_ai_docmd_and_mode(3, dev, s);
1146 }
1147 }
1148
1149 return -1;
1150}
1151
1152
1153
1154
1155static int pci171x_reset(struct comedi_device *dev)
1156{
1157 const struct boardtype *this_board = comedi_board(dev);
1158 struct pci1710_private *devpriv = dev->private;
1159
1160 outw(0x30, dev->iobase + PCI171x_CNTCTRL);
1161 devpriv->CntrlReg = Control_SW | Control_CNT0;
1162 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
1163 outb(0, dev->iobase + PCI171x_CLRFIFO);
1164 outb(0, dev->iobase + PCI171x_CLRINT);
1165 start_pacer(dev, -1, 0, 0);
1166 devpriv->da_ranges = 0;
1167 if (this_board->n_aochan) {
1168 outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
1169 outw(0, dev->iobase + PCI171x_DA1);
1170 devpriv->ao_data[0] = 0x0000;
1171 if (this_board->n_aochan > 1) {
1172 outw(0, dev->iobase + PCI171x_DA2);
1173 devpriv->ao_data[1] = 0x0000;
1174 }
1175 }
1176 outw(0, dev->iobase + PCI171x_DO);
1177 outb(0, dev->iobase + PCI171x_CLRFIFO);
1178 outb(0, dev->iobase + PCI171x_CLRINT);
1179
1180 return 0;
1181}
1182
1183
1184
1185
1186static int pci1720_reset(struct comedi_device *dev)
1187{
1188 struct pci1710_private *devpriv = dev->private;
1189
1190 outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT);
1191 devpriv->da_ranges = 0xAA;
1192 outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE);
1193 outw(0x0800, dev->iobase + PCI1720_DA0);
1194 outw(0x0800, dev->iobase + PCI1720_DA1);
1195 outw(0x0800, dev->iobase + PCI1720_DA2);
1196 outw(0x0800, dev->iobase + PCI1720_DA3);
1197 outb(0, dev->iobase + PCI1720_SYNCOUT);
1198 devpriv->ao_data[0] = 0x0800;
1199 devpriv->ao_data[1] = 0x0800;
1200 devpriv->ao_data[2] = 0x0800;
1201 devpriv->ao_data[3] = 0x0800;
1202 return 0;
1203}
1204
1205
1206
1207
1208static int pci1710_reset(struct comedi_device *dev)
1209{
1210 const struct boardtype *this_board = comedi_board(dev);
1211
1212 switch (this_board->cardtype) {
1213 case TYPE_PCI1720:
1214 return pci1720_reset(dev);
1215 default:
1216 return pci171x_reset(dev);
1217 }
1218}
1219
1220static int pci1710_auto_attach(struct comedi_device *dev,
1221 unsigned long context)
1222{
1223 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1224 const struct boardtype *this_board = NULL;
1225 struct pci1710_private *devpriv;
1226 struct comedi_subdevice *s;
1227 int ret, subdev, n_subdevices;
1228
1229 if (context < ARRAY_SIZE(boardtypes))
1230 this_board = &boardtypes[context];
1231 if (!this_board)
1232 return -ENODEV;
1233 dev->board_ptr = this_board;
1234 dev->board_name = this_board->name;
1235
1236 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1237 if (!devpriv)
1238 return -ENOMEM;
1239 dev->private = devpriv;
1240
1241 ret = comedi_pci_enable(dev);
1242 if (ret)
1243 return ret;
1244 dev->iobase = pci_resource_start(pcidev, 2);
1245
1246 n_subdevices = 0;
1247 if (this_board->n_aichan)
1248 n_subdevices++;
1249 if (this_board->n_aochan)
1250 n_subdevices++;
1251 if (this_board->n_dichan)
1252 n_subdevices++;
1253 if (this_board->n_dochan)
1254 n_subdevices++;
1255 if (this_board->n_counter)
1256 n_subdevices++;
1257
1258 ret = comedi_alloc_subdevices(dev, n_subdevices);
1259 if (ret)
1260 return ret;
1261
1262 pci1710_reset(dev);
1263
1264 if (this_board->have_irq && pcidev->irq) {
1265 ret = request_irq(pcidev->irq, interrupt_service_pci1710,
1266 IRQF_SHARED, dev->board_name, dev);
1267 if (ret == 0)
1268 dev->irq = pcidev->irq;
1269 }
1270
1271 subdev = 0;
1272
1273 if (this_board->n_aichan) {
1274 s = &dev->subdevices[subdev];
1275 dev->read_subdev = s;
1276 s->type = COMEDI_SUBD_AI;
1277 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
1278 if (this_board->n_aichand)
1279 s->subdev_flags |= SDF_DIFF;
1280 s->n_chan = this_board->n_aichan;
1281 s->maxdata = this_board->ai_maxdata;
1282 s->len_chanlist = this_board->n_aichan;
1283 s->range_table = this_board->rangelist_ai;
1284 s->cancel = pci171x_ai_cancel;
1285 s->insn_read = pci171x_insn_read_ai;
1286 if (dev->irq) {
1287 s->subdev_flags |= SDF_CMD_READ;
1288 s->do_cmdtest = pci171x_ai_cmdtest;
1289 s->do_cmd = pci171x_ai_cmd;
1290 }
1291 devpriv->i8254_osc_base = 100;
1292 subdev++;
1293 }
1294
1295 if (this_board->n_aochan) {
1296 s = &dev->subdevices[subdev];
1297 s->type = COMEDI_SUBD_AO;
1298 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1299 s->n_chan = this_board->n_aochan;
1300 s->maxdata = this_board->ao_maxdata;
1301 s->len_chanlist = this_board->n_aochan;
1302 s->range_table = this_board->rangelist_ao;
1303 switch (this_board->cardtype) {
1304 case TYPE_PCI1720:
1305 s->insn_write = pci1720_insn_write_ao;
1306 break;
1307 default:
1308 s->insn_write = pci171x_insn_write_ao;
1309 break;
1310 }
1311 s->insn_read = pci171x_insn_read_ao;
1312 subdev++;
1313 }
1314
1315 if (this_board->n_dichan) {
1316 s = &dev->subdevices[subdev];
1317 s->type = COMEDI_SUBD_DI;
1318 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
1319 s->n_chan = this_board->n_dichan;
1320 s->maxdata = 1;
1321 s->len_chanlist = this_board->n_dichan;
1322 s->range_table = &range_digital;
1323 s->io_bits = 0;
1324 s->insn_bits = pci171x_insn_bits_di;
1325 subdev++;
1326 }
1327
1328 if (this_board->n_dochan) {
1329 s = &dev->subdevices[subdev];
1330 s->type = COMEDI_SUBD_DO;
1331 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1332 s->n_chan = this_board->n_dochan;
1333 s->maxdata = 1;
1334 s->len_chanlist = this_board->n_dochan;
1335 s->range_table = &range_digital;
1336
1337 s->io_bits = (1 << this_board->n_dochan) - 1;
1338 s->state = 0;
1339 s->insn_bits = pci171x_insn_bits_do;
1340 subdev++;
1341 }
1342
1343 if (this_board->n_counter) {
1344 s = &dev->subdevices[subdev];
1345 s->type = COMEDI_SUBD_COUNTER;
1346 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1347 s->n_chan = this_board->n_counter;
1348 s->len_chanlist = this_board->n_counter;
1349 s->maxdata = 0xffff;
1350 s->range_table = &range_unknown;
1351 s->insn_read = pci171x_insn_counter_read;
1352 s->insn_write = pci171x_insn_counter_write;
1353 s->insn_config = pci171x_insn_counter_config;
1354 subdev++;
1355 }
1356
1357 dev_info(dev->class_dev, "%s attached, irq %sabled\n",
1358 dev->board_name, dev->irq ? "en" : "dis");
1359
1360 return 0;
1361}
1362
1363static void pci1710_detach(struct comedi_device *dev)
1364{
1365 if (dev->iobase)
1366 pci1710_reset(dev);
1367 if (dev->irq)
1368 free_irq(dev->irq, dev);
1369 comedi_pci_disable(dev);
1370}
1371
1372static struct comedi_driver adv_pci1710_driver = {
1373 .driver_name = "adv_pci1710",
1374 .module = THIS_MODULE,
1375 .auto_attach = pci1710_auto_attach,
1376 .detach = pci1710_detach,
1377};
1378
1379static int adv_pci1710_pci_probe(struct pci_dev *dev,
1380 const struct pci_device_id *id)
1381{
1382 return comedi_pci_auto_config(dev, &adv_pci1710_driver,
1383 id->driver_data);
1384}
1385
1386static DEFINE_PCI_DEVICE_TABLE(adv_pci1710_pci_table) = {
1387 {
1388 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1389 PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050),
1390 .driver_data = BOARD_PCI1710,
1391 }, {
1392 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1393 PCI_VENDOR_ID_ADVANTECH, 0x0000),
1394 .driver_data = BOARD_PCI1710,
1395 }, {
1396 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1397 PCI_VENDOR_ID_ADVANTECH, 0xb100),
1398 .driver_data = BOARD_PCI1710,
1399 }, {
1400 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1401 PCI_VENDOR_ID_ADVANTECH, 0xb200),
1402 .driver_data = BOARD_PCI1710,
1403 }, {
1404 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1405 PCI_VENDOR_ID_ADVANTECH, 0xc100),
1406 .driver_data = BOARD_PCI1710,
1407 }, {
1408 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1409 PCI_VENDOR_ID_ADVANTECH, 0xc200),
1410 .driver_data = BOARD_PCI1710,
1411 }, {
1412 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd100),
1413 .driver_data = BOARD_PCI1710,
1414 }, {
1415 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1416 PCI_VENDOR_ID_ADVANTECH, 0x0002),
1417 .driver_data = BOARD_PCI1710HG,
1418 }, {
1419 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1420 PCI_VENDOR_ID_ADVANTECH, 0xb102),
1421 .driver_data = BOARD_PCI1710HG,
1422 }, {
1423 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1424 PCI_VENDOR_ID_ADVANTECH, 0xb202),
1425 .driver_data = BOARD_PCI1710HG,
1426 }, {
1427 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1428 PCI_VENDOR_ID_ADVANTECH, 0xc102),
1429 .driver_data = BOARD_PCI1710HG,
1430 }, {
1431 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710,
1432 PCI_VENDOR_ID_ADVANTECH, 0xc202),
1433 .driver_data = BOARD_PCI1710HG,
1434 }, {
1435 PCI_DEVICE_SUB(PCI_VENDOR_ID_ADVANTECH, 0x1710, 0x1000, 0xd102),
1436 .driver_data = BOARD_PCI1710HG,
1437 },
1438 { PCI_VDEVICE(ADVANTECH, 0x1711), BOARD_PCI1711 },
1439 { PCI_VDEVICE(ADVANTECH, 0x1713), BOARD_PCI1713 },
1440 { PCI_VDEVICE(ADVANTECH, 0x1720), BOARD_PCI1720 },
1441 { PCI_VDEVICE(ADVANTECH, 0x1731), BOARD_PCI1731 },
1442 { 0 }
1443};
1444MODULE_DEVICE_TABLE(pci, adv_pci1710_pci_table);
1445
1446static struct pci_driver adv_pci1710_pci_driver = {
1447 .name = "adv_pci1710",
1448 .id_table = adv_pci1710_pci_table,
1449 .probe = adv_pci1710_pci_probe,
1450 .remove = comedi_pci_auto_unconfig,
1451};
1452module_comedi_pci_driver(adv_pci1710_driver, adv_pci1710_pci_driver);
1453
1454MODULE_AUTHOR("Comedi http://www.comedi.org");
1455MODULE_DESCRIPTION("Comedi low-level driver");
1456MODULE_LICENSE("GPL");
1457