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