2 * comedi/drivers/adv_pci1710.c
4 * Author: Michal Dobes <dobes@tesnet.cz>
6 * Thanks to ZhenGang Shang <ZhenGang.Shang@Advantech.com.cn>
7 * for testing and informations.
9 * hardware driver for Advantech cards:
10 * card: PCI-1710, PCI-1710HG, PCI-1711, PCI-1713, PCI-1720, PCI-1731
11 * driver: pci1710, pci1710hg, pci1711, pci1713, pci1720, pci1731
14 * [0] - PCI bus number - if bus number and slot number are 0,
15 * then driver search for first unused card
16 * [1] - PCI slot number
21 Description: Advantech PCI-1710, PCI-1710HG, PCI-1711, PCI-1713,
22 Advantech PCI-1720, PCI-1731
23 Author: Michal Dobes <dobes@tesnet.cz>
24 Devices: [Advantech] PCI-1710 (adv_pci1710), PCI-1710HG (pci1710hg),
25 PCI-1711 (adv_pci1710), PCI-1713, PCI-1720,
29 This driver supports AI, AO, DI and DO subdevices.
30 AI subdevice supports cmd and insn interface,
31 other subdevices support only insn interface.
33 The PCI-1710 and PCI-1710HG have the same PCI device ID, so the
34 driver cannot distinguish between them, as would be normal for a
37 Configuration options:
38 [0] - PCI bus of device (optional)
39 [1] - PCI slot of device (optional)
40 If bus/slot is not specified, the first available PCI
44 #include <linux/interrupt.h>
46 #include "../comedidev.h"
48 #include "comedi_pci.h"
51 #include "amcc_s5933.h"
53 #define PCI171x_PARANOIDCHECK /* if defined, then is used code which control
54 * correct channel number on every 12 bit
57 #undef PCI171X_EXTDEBUG
59 #define DRV_NAME "adv_pci1710"
62 #ifdef PCI171X_EXTDEBUG
63 #define DPRINTK(fmt, args...) printk(fmt, ## args)
65 #define DPRINTK(fmt, args...)
68 #define PCI_VENDOR_ID_ADVANTECH 0x13fe
70 /* hardware types of the cards */
71 #define TYPE_PCI171X 0
72 #define TYPE_PCI1713 2
73 #define TYPE_PCI1720 3
75 #define IORANGE_171x 32
76 #define IORANGE_1720 16
78 #define PCI171x_AD_DATA 0 /* R: A/D data */
79 #define PCI171x_SOFTTRG 0 /* W: soft trigger for A/D */
80 #define PCI171x_RANGE 2 /* W: A/D gain/range register */
81 #define PCI171x_MUX 4 /* W: A/D multiplexor control */
82 #define PCI171x_STATUS 6 /* R: status register */
83 #define PCI171x_CONTROL 6 /* W: control register */
84 #define PCI171x_CLRINT 8 /* W: clear interrupts request */
85 #define PCI171x_CLRFIFO 9 /* W: clear FIFO */
86 #define PCI171x_DA1 10 /* W: D/A register */
87 #define PCI171x_DA2 12 /* W: D/A register */
88 #define PCI171x_DAREF 14 /* W: D/A reference control */
89 #define PCI171x_DI 16 /* R: digi inputs */
90 #define PCI171x_DO 16 /* R: digi inputs */
91 #define PCI171x_CNT0 24 /* R/W: 8254 counter 0 */
92 #define PCI171x_CNT1 26 /* R/W: 8254 counter 1 */
93 #define PCI171x_CNT2 28 /* R/W: 8254 counter 2 */
94 #define PCI171x_CNTCTRL 30 /* W: 8254 counter control */
96 /* upper bits from status register (PCI171x_STATUS) (lower is same with control
98 #define Status_FE 0x0100 /* 1=FIFO is empty */
99 #define Status_FH 0x0200 /* 1=FIFO is half full */
100 #define Status_FF 0x0400 /* 1=FIFO is full, fatal error */
101 #define Status_IRQ 0x0800 /* 1=IRQ occurred */
102 /* bits from control register (PCI171x_CONTROL) */
103 #define Control_CNT0 0x0040 /* 1=CNT0 have external source,
104 * 0=have internal 100kHz source */
105 #define Control_ONEFH 0x0020 /* 1=IRQ on FIFO is half full, 0=every sample */
106 #define Control_IRQEN 0x0010 /* 1=enable IRQ */
107 #define Control_GATE 0x0008 /* 1=enable external trigger GATE (8254?) */
108 #define Control_EXT 0x0004 /* 1=external trigger source */
109 #define Control_PACER 0x0002 /* 1=enable internal 8254 trigger source */
110 #define Control_SW 0x0001 /* 1=enable software trigger source */
111 /* bits from counter control register (PCI171x_CNTCTRL) */
112 #define Counter_BCD 0x0001 /* 0 = binary counter, 1 = BCD counter */
113 #define Counter_M0 0x0002 /* M0-M2 select modes 0-5 */
114 #define Counter_M1 0x0004 /* 000 = mode 0, 010 = mode 2 ... */
115 #define Counter_M2 0x0008
116 #define Counter_RW0 0x0010 /* RW0/RW1 select read/write mode */
117 #define Counter_RW1 0x0020
118 #define Counter_SC0 0x0040 /* Select Counter. Only 00 or 11 may */
119 #define Counter_SC1 0x0080 /* be used, 00 for CNT0,
120 * 11 for read-back command */
122 #define PCI1720_DA0 0 /* W: D/A register 0 */
123 #define PCI1720_DA1 2 /* W: D/A register 1 */
124 #define PCI1720_DA2 4 /* W: D/A register 2 */
125 #define PCI1720_DA3 6 /* W: D/A register 3 */
126 #define PCI1720_RANGE 8 /* R/W: D/A range register */
127 #define PCI1720_SYNCOUT 9 /* W: D/A synchronized output register */
128 #define PCI1720_SYNCONT 15 /* R/W: D/A synchronized control */
130 /* D/A synchronized control (PCI1720_SYNCONT) */
131 #define Syncont_SC0 1 /* set synchronous output mode */
133 static const struct comedi_lrange range_pci1710_3 = { 9, {
146 static const char range_codes_pci1710_3[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
147 0x10, 0x11, 0x12, 0x13 };
149 static const struct comedi_lrange range_pci1710hg = { 12, {
165 static const char range_codes_pci1710hg[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
166 0x05, 0x06, 0x07, 0x10, 0x11,
169 static const struct comedi_lrange range_pci17x1 = { 5, {
178 static const char range_codes_pci17x1[] = { 0x00, 0x01, 0x02, 0x03, 0x04 };
180 static const struct comedi_lrange range_pci1720 = { 4, {
188 static const struct comedi_lrange range_pci171x_da = { 2, {
194 static int pci1710_attach(struct comedi_device *dev,
195 struct comedi_devconfig *it);
196 static int pci1710_detach(struct comedi_device *dev);
199 const char *name; /* board name */
201 int iorange; /* I/O range len */
202 char have_irq; /* 1=card support IRQ */
203 char cardtype; /* 0=1710& co. 2=1713, ... */
204 int n_aichan; /* num of A/D chans */
205 int n_aichand; /* num of A/D chans in diff mode */
206 int n_aochan; /* num of D/A chans */
207 int n_dichan; /* num of DI chans */
208 int n_dochan; /* num of DO chans */
209 int n_counter; /* num of counters */
210 int ai_maxdata; /* resolution of A/D */
211 int ao_maxdata; /* resolution of D/A */
212 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
213 const char *rangecode_ai; /* range codes for programming */
214 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
215 unsigned int ai_ns_min; /* max sample speed of card v ns */
216 unsigned int fifo_half_size; /* size of FIFO/2 */
219 static DEFINE_PCI_DEVICE_TABLE(pci1710_pci_table) = {
220 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1710) },
221 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1711) },
222 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1713) },
223 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1720) },
224 { PCI_DEVICE(PCI_VENDOR_ID_ADVANTECH, 0x1731) },
228 MODULE_DEVICE_TABLE(pci, pci1710_pci_table);
230 static const struct boardtype boardtypes[] = {
232 IORANGE_171x, 1, TYPE_PCI171X,
233 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
234 &range_pci1710_3, range_codes_pci1710_3,
237 {"pci1710hg", 0x1710,
238 IORANGE_171x, 1, TYPE_PCI171X,
239 16, 8, 2, 16, 16, 1, 0x0fff, 0x0fff,
240 &range_pci1710hg, range_codes_pci1710hg,
244 IORANGE_171x, 1, TYPE_PCI171X,
245 16, 0, 2, 16, 16, 1, 0x0fff, 0x0fff,
246 &range_pci17x1, range_codes_pci17x1, &range_pci171x_da,
249 IORANGE_171x, 1, TYPE_PCI1713,
250 32, 16, 0, 0, 0, 0, 0x0fff, 0x0000,
251 &range_pci1710_3, range_codes_pci1710_3, NULL,
254 IORANGE_1720, 0, TYPE_PCI1720,
255 0, 0, 4, 0, 0, 0, 0x0000, 0x0fff,
256 NULL, NULL, &range_pci1720,
259 IORANGE_171x, 1, TYPE_PCI171X,
260 16, 0, 0, 16, 16, 0, 0x0fff, 0x0000,
261 &range_pci17x1, range_codes_pci17x1, NULL,
263 /* dummy entry corresponding to driver name */
267 static struct comedi_driver driver_pci1710 = {
268 .driver_name = DRV_NAME,
269 .module = THIS_MODULE,
270 .attach = pci1710_attach,
271 .detach = pci1710_detach,
272 .num_names = ARRAY_SIZE(boardtypes),
273 .board_name = &boardtypes[0].name,
274 .offset = sizeof(struct boardtype),
277 struct pci1710_private {
278 struct pci_dev *pcidev; /* ptr to PCI device */
279 char valid; /* card is usable */
280 char neverending_ai; /* we do unlimited AI */
281 unsigned int CntrlReg; /* Control register */
282 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
283 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
284 unsigned int ai_act_scan; /* how many scans we finished */
285 unsigned int ai_act_chan; /* actual position in actual scan */
286 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
287 unsigned char ai_eos; /* 1=EOS wake up */
289 unsigned int ai_et_CntrlReg;
290 unsigned int ai_et_MuxVal;
291 unsigned int ai_et_div1, ai_et_div2;
292 unsigned int act_chanlist[32]; /* list of scaned channel */
293 unsigned char act_chanlist_len; /* len of scanlist */
294 unsigned char act_chanlist_pos; /* actual position in MUX list */
295 unsigned char da_ranges; /* copy of D/A outpit range register */
296 unsigned int ai_scans; /* len of scanlist */
297 unsigned int ai_n_chan; /* how many channels is measured */
298 unsigned int *ai_chanlist; /* actaul chanlist */
299 unsigned int ai_flags; /* flaglist */
300 unsigned int ai_data_len; /* len of data buffer */
301 short *ai_data; /* data buffer */
302 unsigned int ai_timer1; /* timers */
303 unsigned int ai_timer2;
304 short ao_data[4]; /* data output buffer */
305 unsigned int cnt0_write_wait; /* after a write, wait for update of the
309 #define devpriv ((struct pci1710_private *)dev->private)
310 #define this_board ((const struct boardtype *)dev->board_ptr)
313 ==============================================================================
316 static int check_channel_list(struct comedi_device *dev,
317 struct comedi_subdevice *s,
318 unsigned int *chanlist, unsigned int n_chan);
319 static void setup_channel_list(struct comedi_device *dev,
320 struct comedi_subdevice *s,
321 unsigned int *chanlist, unsigned int n_chan,
322 unsigned int seglen);
323 static void start_pacer(struct comedi_device *dev, int mode,
324 unsigned int divisor1, unsigned int divisor2);
325 static int pci1710_reset(struct comedi_device *dev);
326 static int pci171x_ai_cancel(struct comedi_device *dev,
327 struct comedi_subdevice *s);
329 /* used for gain list programming */
330 static const unsigned int muxonechan[] = {
331 0x0000, 0x0101, 0x0202, 0x0303, 0x0404, 0x0505, 0x0606, 0x0707,
332 0x0808, 0x0909, 0x0a0a, 0x0b0b, 0x0c0c, 0x0d0d, 0x0e0e, 0x0f0f,
333 0x1010, 0x1111, 0x1212, 0x1313, 0x1414, 0x1515, 0x1616, 0x1717,
334 0x1818, 0x1919, 0x1a1a, 0x1b1b, 0x1c1c, 0x1d1d, 0x1e1e, 0x1f1f
338 ==============================================================================
340 static int pci171x_insn_read_ai(struct comedi_device *dev,
341 struct comedi_subdevice *s,
342 struct comedi_insn *insn, unsigned int *data)
345 #ifdef PCI171x_PARANOIDCHECK
349 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_insn_read_ai(...)\n");
350 devpriv->CntrlReg &= Control_CNT0;
351 devpriv->CntrlReg |= Control_SW; /* set software trigger */
352 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
353 outb(0, dev->iobase + PCI171x_CLRFIFO);
354 outb(0, dev->iobase + PCI171x_CLRINT);
356 setup_channel_list(dev, s, &insn->chanspec, 1, 1);
358 DPRINTK("adv_pci1710 A ST=%4x IO=%x\n",
359 inw(dev->iobase + PCI171x_STATUS),
360 dev->iobase + PCI171x_STATUS);
361 for (n = 0; n < insn->n; n++) {
362 outw(0, dev->iobase + PCI171x_SOFTTRG); /* start conversion */
363 DPRINTK("adv_pci1710 B n=%d ST=%4x\n", n,
364 inw(dev->iobase + PCI171x_STATUS));
366 DPRINTK("adv_pci1710 C n=%d ST=%4x\n", n,
367 inw(dev->iobase + PCI171x_STATUS));
370 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_FE))
373 DPRINTK("adv_pci1710 D n=%d tm=%d ST=%4x\n", n,
375 inw(dev->iobase + PCI171x_STATUS));
377 comedi_error(dev, "A/D insn timeout");
378 outb(0, dev->iobase + PCI171x_CLRFIFO);
379 outb(0, dev->iobase + PCI171x_CLRINT);
382 ("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n",
387 #ifdef PCI171x_PARANOIDCHECK
388 idata = inw(dev->iobase + PCI171x_AD_DATA);
389 if (this_board->cardtype != TYPE_PCI1713)
390 if ((idata & 0xf000) != devpriv->act_chanlist[0]) {
391 comedi_error(dev, "A/D insn data droput!");
394 data[n] = idata & 0x0fff;
396 data[n] = inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff;
401 outb(0, dev->iobase + PCI171x_CLRFIFO);
402 outb(0, dev->iobase + PCI171x_CLRINT);
404 DPRINTK("adv_pci1710 EDBG: END: pci171x_insn_read_ai(...) n=%d\n", n);
409 ==============================================================================
411 static int pci171x_insn_write_ao(struct comedi_device *dev,
412 struct comedi_subdevice *s,
413 struct comedi_insn *insn, unsigned int *data)
415 int n, chan, range, ofs;
417 chan = CR_CHAN(insn->chanspec);
418 range = CR_RANGE(insn->chanspec);
420 devpriv->da_ranges &= 0xfb;
421 devpriv->da_ranges |= (range << 2);
422 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
425 devpriv->da_ranges &= 0xfe;
426 devpriv->da_ranges |= range;
427 outw(devpriv->da_ranges, dev->iobase + PCI171x_DAREF);
431 for (n = 0; n < insn->n; n++)
432 outw(data[n], dev->iobase + ofs);
434 devpriv->ao_data[chan] = data[n];
441 ==============================================================================
443 static int pci171x_insn_read_ao(struct comedi_device *dev,
444 struct comedi_subdevice *s,
445 struct comedi_insn *insn, unsigned int *data)
449 chan = CR_CHAN(insn->chanspec);
450 for (n = 0; n < insn->n; n++)
451 data[n] = devpriv->ao_data[chan];
457 ==============================================================================
459 static int pci171x_insn_bits_di(struct comedi_device *dev,
460 struct comedi_subdevice *s,
461 struct comedi_insn *insn, unsigned int *data)
463 data[1] = inw(dev->iobase + PCI171x_DI);
469 ==============================================================================
471 static int pci171x_insn_bits_do(struct comedi_device *dev,
472 struct comedi_subdevice *s,
473 struct comedi_insn *insn, unsigned int *data)
476 s->state &= ~data[0];
477 s->state |= (data[0] & data[1]);
478 outw(s->state, dev->iobase + PCI171x_DO);
486 ==============================================================================
488 static int pci171x_insn_counter_read(struct comedi_device *dev,
489 struct comedi_subdevice *s,
490 struct comedi_insn *insn,
493 unsigned int msb, lsb, ccntrl;
496 ccntrl = 0xD2; /* count only */
497 for (i = 0; i < insn->n; i++) {
498 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
500 lsb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
501 msb = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
503 data[0] = lsb | (msb << 8);
510 ==============================================================================
512 static int pci171x_insn_counter_write(struct comedi_device *dev,
513 struct comedi_subdevice *s,
514 struct comedi_insn *insn,
517 uint msb, lsb, ccntrl, status;
519 lsb = data[0] & 0x00FF;
520 msb = (data[0] & 0xFF00) >> 8;
522 /* write lsb, then msb */
523 outw(lsb, dev->iobase + PCI171x_CNT0);
524 outw(msb, dev->iobase + PCI171x_CNT0);
526 if (devpriv->cnt0_write_wait) {
527 /* wait for the new count to be loaded */
530 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
531 status = inw(dev->iobase + PCI171x_CNT0) & 0xFF;
532 } while (status & 0x40);
539 ==============================================================================
541 static int pci171x_insn_counter_config(struct comedi_device *dev,
542 struct comedi_subdevice *s,
543 struct comedi_insn *insn,
547 /* This doesn't work like a normal Comedi counter config */
550 devpriv->cnt0_write_wait = data[0] & 0x20;
552 /* internal or external clock? */
553 if (!(data[0] & 0x10)) { /* internal */
554 devpriv->CntrlReg &= ~Control_CNT0;
556 devpriv->CntrlReg |= Control_CNT0;
558 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
561 ccntrl |= Counter_M0;
563 ccntrl |= Counter_M1;
565 ccntrl |= Counter_M2;
567 ccntrl |= Counter_BCD;
568 ccntrl |= Counter_RW0; /* set read/write mode */
569 ccntrl |= Counter_RW1;
570 outw(ccntrl, dev->iobase + PCI171x_CNTCTRL);
577 ==============================================================================
579 static int pci1720_insn_write_ao(struct comedi_device *dev,
580 struct comedi_subdevice *s,
581 struct comedi_insn *insn, unsigned int *data)
583 int n, rangereg, chan;
585 chan = CR_CHAN(insn->chanspec);
586 rangereg = devpriv->da_ranges & (~(0x03 << (chan << 1)));
587 rangereg |= (CR_RANGE(insn->chanspec) << (chan << 1));
588 if (rangereg != devpriv->da_ranges) {
589 outb(rangereg, dev->iobase + PCI1720_RANGE);
590 devpriv->da_ranges = rangereg;
593 for (n = 0; n < insn->n; n++) {
594 outw(data[n], dev->iobase + PCI1720_DA0 + (chan << 1));
595 outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */
598 devpriv->ao_data[chan] = data[n];
604 ==============================================================================
606 static void interrupt_pci1710_every_sample(void *d)
608 struct comedi_device *dev = d;
609 struct comedi_subdevice *s = dev->subdevices + 0;
611 #ifdef PCI171x_PARANOIDCHECK
615 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_every_sample(...)\n");
616 m = inw(dev->iobase + PCI171x_STATUS);
618 printk("comedi%d: A/D FIFO empty (%4x)\n", dev->minor, m);
619 pci171x_ai_cancel(dev, s);
620 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
621 comedi_event(dev, s);
626 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n",
628 pci171x_ai_cancel(dev, s);
629 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
630 comedi_event(dev, s);
634 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
637 for (; !(inw(dev->iobase + PCI171x_STATUS) & Status_FE);) {
638 #ifdef PCI171x_PARANOIDCHECK
639 sampl = inw(dev->iobase + PCI171x_AD_DATA);
640 DPRINTK("%04x:", sampl);
641 if (this_board->cardtype != TYPE_PCI1713)
642 if ((sampl & 0xf000) !=
643 devpriv->act_chanlist[s->async->cur_chan]) {
645 ("comedi: A/D data dropout: received data from channel %d, expected %d!\n",
646 (sampl & 0xf000) >> 12,
649 async->cur_chan] & 0xf000) >>
651 pci171x_ai_cancel(dev, s);
653 COMEDI_CB_EOA | COMEDI_CB_ERROR;
654 comedi_event(dev, s);
657 DPRINTK("%8d %2d %8d~", s->async->buf_int_ptr,
658 s->async->cur_chan, s->async->buf_int_count);
659 comedi_buf_put(s->async, sampl & 0x0fff);
661 comedi_buf_put(s->async,
662 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff);
664 ++s->async->cur_chan;
666 if (s->async->cur_chan >= devpriv->ai_n_chan)
667 s->async->cur_chan = 0;
670 if (s->async->cur_chan == 0) { /* one scan done */
671 devpriv->ai_act_scan++;
673 ("adv_pci1710 EDBG: EOS1 bic %d bip %d buc %d bup %d\n",
674 s->async->buf_int_count, s->async->buf_int_ptr,
675 s->async->buf_user_count, s->async->buf_user_ptr);
676 DPRINTK("adv_pci1710 EDBG: EOS2\n");
677 if ((!devpriv->neverending_ai) &&
678 (devpriv->ai_act_scan >= devpriv->ai_scans)) {
679 /* all data sampled */
680 pci171x_ai_cancel(dev, s);
681 s->async->events |= COMEDI_CB_EOA;
682 comedi_event(dev, s);
688 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
689 DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_every_sample(...)\n");
691 comedi_event(dev, s);
695 ==============================================================================
697 static int move_block_from_fifo(struct comedi_device *dev,
698 struct comedi_subdevice *s, int n, int turn)
701 #ifdef PCI171x_PARANOIDCHECK
704 DPRINTK("adv_pci1710 EDBG: BGN: move_block_from_fifo(...,%d,%d)\n", n,
706 j = s->async->cur_chan;
707 for (i = 0; i < n; i++) {
708 #ifdef PCI171x_PARANOIDCHECK
709 sampl = inw(dev->iobase + PCI171x_AD_DATA);
710 if (this_board->cardtype != TYPE_PCI1713)
711 if ((sampl & 0xf000) != devpriv->act_chanlist[j]) {
713 ("comedi%d: A/D FIFO data dropout: received data from channel %d, expected %d! (%d/%d/%d/%d/%d/%4x)\n",
714 dev->minor, (sampl & 0xf000) >> 12,
715 (devpriv->act_chanlist[j] & 0xf000) >> 12,
716 i, j, devpriv->ai_act_scan, n, turn,
718 pci171x_ai_cancel(dev, s);
720 COMEDI_CB_EOA | COMEDI_CB_ERROR;
721 comedi_event(dev, s);
724 comedi_buf_put(s->async, sampl & 0x0fff);
726 comedi_buf_put(s->async,
727 inw(dev->iobase + PCI171x_AD_DATA) & 0x0fff);
730 if (j >= devpriv->ai_n_chan) {
732 devpriv->ai_act_scan++;
735 s->async->cur_chan = j;
736 DPRINTK("adv_pci1710 EDBG: END: move_block_from_fifo(...)\n");
741 ==============================================================================
743 static void interrupt_pci1710_half_fifo(void *d)
745 struct comedi_device *dev = d;
746 struct comedi_subdevice *s = dev->subdevices + 0;
749 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_pci1710_half_fifo(...)\n");
750 m = inw(dev->iobase + PCI171x_STATUS);
751 if (!(m & Status_FH)) {
752 printk("comedi%d: A/D FIFO not half full! (%4x)\n",
754 pci171x_ai_cancel(dev, s);
755 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
756 comedi_event(dev, s);
761 ("comedi%d: A/D FIFO Full status (Fatal Error!) (%4x)\n",
763 pci171x_ai_cancel(dev, s);
764 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
765 comedi_event(dev, s);
769 samplesinbuf = this_board->fifo_half_size;
770 if (samplesinbuf * sizeof(short) >= devpriv->ai_data_len) {
771 m = devpriv->ai_data_len / sizeof(short);
772 if (move_block_from_fifo(dev, s, m, 0))
778 if (move_block_from_fifo(dev, s, samplesinbuf, 1))
782 if (!devpriv->neverending_ai)
783 if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data
785 pci171x_ai_cancel(dev, s);
786 s->async->events |= COMEDI_CB_EOA;
787 comedi_event(dev, s);
790 outb(0, dev->iobase + PCI171x_CLRINT); /* clear our INT request */
791 DPRINTK("adv_pci1710 EDBG: END: interrupt_pci1710_half_fifo(...)\n");
793 comedi_event(dev, s);
797 ==============================================================================
799 static irqreturn_t interrupt_service_pci1710(int irq, void *d)
801 struct comedi_device *dev = d;
803 DPRINTK("adv_pci1710 EDBG: BGN: interrupt_service_pci1710(%d,...)\n",
805 if (!dev->attached) /* is device attached? */
806 return IRQ_NONE; /* no, exit */
807 /* is this interrupt from our board? */
808 if (!(inw(dev->iobase + PCI171x_STATUS) & Status_IRQ))
809 return IRQ_NONE; /* no, exit */
811 DPRINTK("adv_pci1710 EDBG: interrupt_service_pci1710() ST: %4x\n",
812 inw(dev->iobase + PCI171x_STATUS));
814 if (devpriv->ai_et) { /* Switch from initial TRIG_EXT to TRIG_xxx. */
816 devpriv->CntrlReg &= Control_CNT0;
817 devpriv->CntrlReg |= Control_SW; /* set software trigger */
818 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
819 devpriv->CntrlReg = devpriv->ai_et_CntrlReg;
820 outb(0, dev->iobase + PCI171x_CLRFIFO);
821 outb(0, dev->iobase + PCI171x_CLRINT);
822 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX);
823 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
825 start_pacer(dev, 1, devpriv->ai_et_div1, devpriv->ai_et_div2);
828 if (devpriv->ai_eos) { /* We use FIFO half full INT or not? */
829 interrupt_pci1710_every_sample(d);
831 interrupt_pci1710_half_fifo(d);
833 DPRINTK("adv_pci1710 EDBG: END: interrupt_service_pci1710(...)\n");
838 ==============================================================================
840 static int pci171x_ai_docmd_and_mode(int mode, struct comedi_device *dev,
841 struct comedi_subdevice *s)
843 unsigned int divisor1 = 0, divisor2 = 0;
846 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_docmd_and_mode(%d,...)\n",
848 start_pacer(dev, -1, 0, 0); /* stop pacer */
850 seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
854 setup_channel_list(dev, s, devpriv->ai_chanlist,
855 devpriv->ai_n_chan, seglen);
857 outb(0, dev->iobase + PCI171x_CLRFIFO);
858 outb(0, dev->iobase + PCI171x_CLRINT);
860 devpriv->ai_do = mode;
862 devpriv->ai_act_scan = 0;
863 s->async->cur_chan = 0;
864 devpriv->ai_buf_ptr = 0;
865 devpriv->neverending_ai = 0;
867 devpriv->CntrlReg &= Control_CNT0;
868 /* don't we want wake up every scan? devpriv->ai_eos=1; */
869 if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
872 devpriv->CntrlReg |= Control_ONEFH;
876 if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
877 devpriv->neverending_ai = 1;
878 /* well, user want neverending */
880 devpriv->neverending_ai = 0;
885 if (devpriv->ai_timer1 < this_board->ai_ns_min)
886 devpriv->ai_timer1 = this_board->ai_ns_min;
887 devpriv->CntrlReg |= Control_PACER | Control_IRQEN;
889 devpriv->ai_et_CntrlReg = devpriv->CntrlReg;
891 ~(Control_PACER | Control_ONEFH | Control_GATE);
892 devpriv->CntrlReg |= Control_EXT;
897 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
898 &divisor2, &devpriv->ai_timer1,
899 devpriv->ai_flags & TRIG_ROUND_MASK);
901 ("adv_pci1710 EDBG: OSC base=%u div1=%u div2=%u timer=%u\n",
902 devpriv->i8254_osc_base, divisor1, divisor2,
904 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
907 start_pacer(dev, mode, divisor1, divisor2);
909 devpriv->ai_et_div1 = divisor1;
910 devpriv->ai_et_div2 = divisor2;
914 devpriv->CntrlReg |= Control_EXT | Control_IRQEN;
915 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL);
919 DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_docmd_and_mode(...)\n");
923 #ifdef PCI171X_EXTDEBUG
925 ==============================================================================
927 static void pci171x_cmdtest_out(int e, struct comedi_cmd *cmd)
929 printk("adv_pci1710 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
930 cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
931 printk("adv_pci1710 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
932 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
933 printk("adv_pci1710 e=%d stopsrc=%x scanend=%x\n", e, cmd->stop_src,
935 printk("adv_pci1710 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
936 e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
941 ==============================================================================
943 static int pci171x_ai_cmdtest(struct comedi_device *dev,
944 struct comedi_subdevice *s,
945 struct comedi_cmd *cmd)
949 unsigned int divisor1 = 0, divisor2 = 0;
951 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...)\n");
952 #ifdef PCI171X_EXTDEBUG
953 pci171x_cmdtest_out(-1, cmd);
955 /* step 1: make sure trigger sources are trivially valid */
957 tmp = cmd->start_src;
958 cmd->start_src &= TRIG_NOW | TRIG_EXT;
959 if (!cmd->start_src || tmp != cmd->start_src)
962 tmp = cmd->scan_begin_src;
963 cmd->scan_begin_src &= TRIG_FOLLOW;
964 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
967 tmp = cmd->convert_src;
968 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
969 if (!cmd->convert_src || tmp != cmd->convert_src)
972 tmp = cmd->scan_end_src;
973 cmd->scan_end_src &= TRIG_COUNT;
974 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
978 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
979 if (!cmd->stop_src || tmp != cmd->stop_src)
983 #ifdef PCI171X_EXTDEBUG
984 pci171x_cmdtest_out(1, cmd);
987 "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=1\n",
992 /* step2: make sure trigger srcs are unique and mutually compatible */
994 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT) {
995 cmd->start_src = TRIG_NOW;
999 if (cmd->scan_begin_src != TRIG_FOLLOW) {
1000 cmd->scan_begin_src = TRIG_FOLLOW;
1004 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1007 if (cmd->scan_end_src != TRIG_COUNT) {
1008 cmd->scan_end_src = TRIG_COUNT;
1012 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1016 #ifdef PCI171X_EXTDEBUG
1017 pci171x_cmdtest_out(2, cmd);
1020 "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=2\n",
1025 /* step 3: make sure arguments are trivially compatible */
1027 if (cmd->start_arg != 0) {
1032 if (cmd->scan_begin_arg != 0) {
1033 cmd->scan_begin_arg = 0;
1037 if (cmd->convert_src == TRIG_TIMER) {
1038 if (cmd->convert_arg < this_board->ai_ns_min) {
1039 cmd->convert_arg = this_board->ai_ns_min;
1042 } else { /* TRIG_FOLLOW */
1043 if (cmd->convert_arg != 0) {
1044 cmd->convert_arg = 0;
1049 if (cmd->scan_end_arg != cmd->chanlist_len) {
1050 cmd->scan_end_arg = cmd->chanlist_len;
1053 if (cmd->stop_src == TRIG_COUNT) {
1054 if (!cmd->stop_arg) {
1058 } else { /* TRIG_NONE */
1059 if (cmd->stop_arg != 0) {
1066 #ifdef PCI171X_EXTDEBUG
1067 pci171x_cmdtest_out(3, cmd);
1070 "adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=3\n",
1075 /* step 4: fix up any arguments */
1077 if (cmd->convert_src == TRIG_TIMER) {
1078 tmp = cmd->convert_arg;
1079 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1080 &divisor2, &cmd->convert_arg,
1081 cmd->flags & TRIG_ROUND_MASK);
1082 if (cmd->convert_arg < this_board->ai_ns_min)
1083 cmd->convert_arg = this_board->ai_ns_min;
1084 if (tmp != cmd->convert_arg)
1090 ("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) err=%d ret=4\n",
1095 /* step 5: complain about special chanlist considerations */
1097 if (cmd->chanlist) {
1098 if (!check_channel_list(dev, s, cmd->chanlist,
1100 return 5; /* incorrect channels list */
1103 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmdtest(...) ret=0\n");
1108 ==============================================================================
1110 static int pci171x_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1112 struct comedi_cmd *cmd = &s->async->cmd;
1114 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cmd(...)\n");
1115 devpriv->ai_n_chan = cmd->chanlist_len;
1116 devpriv->ai_chanlist = cmd->chanlist;
1117 devpriv->ai_flags = cmd->flags;
1118 devpriv->ai_data_len = s->async->prealloc_bufsz;
1119 devpriv->ai_data = s->async->prealloc_buf;
1120 devpriv->ai_timer1 = 0;
1121 devpriv->ai_timer2 = 0;
1123 if (cmd->stop_src == TRIG_COUNT)
1124 devpriv->ai_scans = cmd->stop_arg;
1126 devpriv->ai_scans = 0;
1129 if (cmd->scan_begin_src == TRIG_FOLLOW) { /* mode 1, 2, 3 */
1130 if (cmd->convert_src == TRIG_TIMER) { /* mode 1 and 2 */
1131 devpriv->ai_timer1 = cmd->convert_arg;
1132 return pci171x_ai_docmd_and_mode(cmd->start_src ==
1133 TRIG_EXT ? 2 : 1, dev,
1136 if (cmd->convert_src == TRIG_EXT) { /* mode 3 */
1137 return pci171x_ai_docmd_and_mode(3, dev, s);
1145 ==============================================================================
1146 Check if channel list from user is builded correctly
1147 If it's ok, then program scan/gain logic.
1148 This works for all cards.
1150 static int check_channel_list(struct comedi_device *dev,
1151 struct comedi_subdevice *s,
1152 unsigned int *chanlist, unsigned int n_chan)
1154 unsigned int chansegment[32];
1155 unsigned int i, nowmustbechan, seglen, segpos;
1157 DPRINTK("adv_pci1710 EDBG: check_channel_list(...,%d)\n", n_chan);
1158 /* correct channel and range number check itself comedi/range.c */
1160 comedi_error(dev, "range/channel list is empty!");
1165 chansegment[0] = chanlist[0]; /* first channel is every time ok */
1166 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) { /* build part of chanlist */
1167 /* printk("%d. %d %d\n",i,CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
1168 if (chanlist[0] == chanlist[i])
1169 break; /* we detect loop, this must by finish */
1170 if (CR_CHAN(chanlist[i]) & 1) /* odd channel cann't by differencial */
1171 if (CR_AREF(chanlist[i]) == AREF_DIFF) {
1173 "Odd channel can't be differential input!\n");
1177 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1178 if (CR_AREF(chansegment[i - 1]) == AREF_DIFF)
1179 nowmustbechan = (nowmustbechan + 1) % s->n_chan;
1180 if (nowmustbechan != CR_CHAN(chanlist[i])) { /* channel list isn't continuous :-( */
1182 ("channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
1183 i, CR_CHAN(chanlist[i]), nowmustbechan,
1184 CR_CHAN(chanlist[0]));
1187 chansegment[i] = chanlist[i]; /* well, this is next correct channel in list */
1190 for (i = 0, segpos = 0; i < n_chan; i++) { /* check whole chanlist */
1191 /* printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(chanlist[i]),CR_RANGE(chanlist[i])); */
1192 if (chanlist[i] != chansegment[i % seglen]) {
1194 ("bad channel, reference or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1195 i, CR_CHAN(chansegment[i]),
1196 CR_RANGE(chansegment[i]),
1197 CR_AREF(chansegment[i]),
1198 CR_CHAN(chanlist[i % seglen]),
1199 CR_RANGE(chanlist[i % seglen]),
1200 CR_AREF(chansegment[i % seglen]));
1201 return 0; /* chan/gain list is strange */
1210 static void setup_channel_list(struct comedi_device *dev,
1211 struct comedi_subdevice *s,
1212 unsigned int *chanlist, unsigned int n_chan,
1213 unsigned int seglen)
1215 unsigned int i, range, chanprog;
1217 DPRINTK("adv_pci1710 EDBG: setup_channel_list(...,%d,%d)\n", n_chan,
1219 devpriv->act_chanlist_len = seglen;
1220 devpriv->act_chanlist_pos = 0;
1222 DPRINTK("SegLen: %d\n", seglen);
1223 for (i = 0; i < seglen; i++) { /* store range list to card */
1224 chanprog = muxonechan[CR_CHAN(chanlist[i])];
1225 outw(chanprog, dev->iobase + PCI171x_MUX); /* select channel */
1226 range = this_board->rangecode_ai[CR_RANGE(chanlist[i])];
1227 if (CR_AREF(chanlist[i]) == AREF_DIFF)
1229 outw(range, dev->iobase + PCI171x_RANGE); /* select gain */
1230 #ifdef PCI171x_PARANOIDCHECK
1231 devpriv->act_chanlist[i] =
1232 (CR_CHAN(chanlist[i]) << 12) & 0xf000;
1234 DPRINTK("GS: %2d. [%4x]=%4x %4x\n", i, chanprog, range,
1235 devpriv->act_chanlist[i]);
1237 #ifdef PCI171x_PARANOIDCHECK
1238 for ( ; i < n_chan; i++) { /* store remainder of channel list */
1239 devpriv->act_chanlist[i] =
1240 (CR_CHAN(chanlist[i]) << 12) & 0xf000;
1244 devpriv->ai_et_MuxVal =
1245 CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8);
1246 outw(devpriv->ai_et_MuxVal, dev->iobase + PCI171x_MUX); /* select channel interval to scan */
1247 DPRINTK("MUX: %4x L%4x.H%4x\n",
1248 CR_CHAN(chanlist[0]) | (CR_CHAN(chanlist[seglen - 1]) << 8),
1249 CR_CHAN(chanlist[0]), CR_CHAN(chanlist[seglen - 1]));
1253 ==============================================================================
1255 static void start_pacer(struct comedi_device *dev, int mode,
1256 unsigned int divisor1, unsigned int divisor2)
1258 DPRINTK("adv_pci1710 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
1259 divisor1, divisor2);
1260 outw(0xb4, dev->iobase + PCI171x_CNTCTRL);
1261 outw(0x74, dev->iobase + PCI171x_CNTCTRL);
1264 outw(divisor2 & 0xff, dev->iobase + PCI171x_CNT2);
1265 outw((divisor2 >> 8) & 0xff, dev->iobase + PCI171x_CNT2);
1266 outw(divisor1 & 0xff, dev->iobase + PCI171x_CNT1);
1267 outw((divisor1 >> 8) & 0xff, dev->iobase + PCI171x_CNT1);
1269 DPRINTK("adv_pci1710 EDBG: END: start_pacer(...)\n");
1273 ==============================================================================
1275 static int pci171x_ai_cancel(struct comedi_device *dev,
1276 struct comedi_subdevice *s)
1278 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_ai_cancel(...)\n");
1280 switch (this_board->cardtype) {
1282 devpriv->CntrlReg &= Control_CNT0;
1283 devpriv->CntrlReg |= Control_SW;
1285 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
1286 start_pacer(dev, -1, 0, 0);
1287 outb(0, dev->iobase + PCI171x_CLRFIFO);
1288 outb(0, dev->iobase + PCI171x_CLRINT);
1293 devpriv->ai_act_scan = 0;
1294 s->async->cur_chan = 0;
1295 devpriv->ai_buf_ptr = 0;
1296 devpriv->neverending_ai = 0;
1298 DPRINTK("adv_pci1710 EDBG: END: pci171x_ai_cancel(...)\n");
1303 ==============================================================================
1305 static int pci171x_reset(struct comedi_device *dev)
1307 DPRINTK("adv_pci1710 EDBG: BGN: pci171x_reset(...)\n");
1308 outw(0x30, dev->iobase + PCI171x_CNTCTRL);
1309 devpriv->CntrlReg = Control_SW | Control_CNT0; /* Software trigger, CNT0=external */
1310 outw(devpriv->CntrlReg, dev->iobase + PCI171x_CONTROL); /* reset any operations */
1311 outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */
1312 outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */
1313 start_pacer(dev, -1, 0, 0); /* stop 8254 */
1314 devpriv->da_ranges = 0;
1315 if (this_board->n_aochan) {
1316 outb(devpriv->da_ranges, dev->iobase + PCI171x_DAREF); /* set DACs to 0..5V */
1317 outw(0, dev->iobase + PCI171x_DA1); /* set DA outputs to 0V */
1318 devpriv->ao_data[0] = 0x0000;
1319 if (this_board->n_aochan > 1) {
1320 outw(0, dev->iobase + PCI171x_DA2);
1321 devpriv->ao_data[1] = 0x0000;
1324 outw(0, dev->iobase + PCI171x_DO); /* digital outputs to 0 */
1325 outb(0, dev->iobase + PCI171x_CLRFIFO); /* clear FIFO */
1326 outb(0, dev->iobase + PCI171x_CLRINT); /* clear INT request */
1328 DPRINTK("adv_pci1710 EDBG: END: pci171x_reset(...)\n");
1333 ==============================================================================
1335 static int pci1720_reset(struct comedi_device *dev)
1337 DPRINTK("adv_pci1710 EDBG: BGN: pci1720_reset(...)\n");
1338 outb(Syncont_SC0, dev->iobase + PCI1720_SYNCONT); /* set synchronous output mode */
1339 devpriv->da_ranges = 0xAA;
1340 outb(devpriv->da_ranges, dev->iobase + PCI1720_RANGE); /* set all ranges to +/-5V */
1341 outw(0x0800, dev->iobase + PCI1720_DA0); /* set outputs to 0V */
1342 outw(0x0800, dev->iobase + PCI1720_DA1);
1343 outw(0x0800, dev->iobase + PCI1720_DA2);
1344 outw(0x0800, dev->iobase + PCI1720_DA3);
1345 outb(0, dev->iobase + PCI1720_SYNCOUT); /* update outputs */
1346 devpriv->ao_data[0] = 0x0800;
1347 devpriv->ao_data[1] = 0x0800;
1348 devpriv->ao_data[2] = 0x0800;
1349 devpriv->ao_data[3] = 0x0800;
1350 DPRINTK("adv_pci1710 EDBG: END: pci1720_reset(...)\n");
1355 ==============================================================================
1357 static int pci1710_reset(struct comedi_device *dev)
1359 DPRINTK("adv_pci1710 EDBG: BGN: pci1710_reset(...)\n");
1360 switch (this_board->cardtype) {
1362 return pci1720_reset(dev);
1364 return pci171x_reset(dev);
1366 DPRINTK("adv_pci1710 EDBG: END: pci1710_reset(...)\n");
1370 ==============================================================================
1372 static int pci1710_attach(struct comedi_device *dev,
1373 struct comedi_devconfig *it)
1375 struct comedi_subdevice *s;
1376 int ret, subdev, n_subdevices;
1378 unsigned long iobase;
1379 struct pci_dev *pcidev;
1380 int opt_bus, opt_slot;
1382 unsigned char pci_bus, pci_slot, pci_func;
1386 dev_info(dev->hw_dev, "comedi%d: adv_pci1710:\n", dev->minor);
1388 opt_bus = it->options[0];
1389 opt_slot = it->options[1];
1391 ret = alloc_private(dev, sizeof(struct pci1710_private));
1395 /* Look for matching PCI device */
1396 errstr = "not found!";
1398 board_index = this_board - boardtypes;
1399 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_ADVANTECH,
1400 PCI_ANY_ID, pcidev))) {
1401 if (strcmp(this_board->name, DRV_NAME) == 0) {
1402 for (i = 0; i < ARRAY_SIZE(boardtypes); ++i) {
1403 if (pcidev->device == boardtypes[i].device_id) {
1408 if (i == ARRAY_SIZE(boardtypes))
1411 if (pcidev->device != boardtypes[board_index].device_id)
1415 /* Found matching vendor/device. */
1416 if (opt_bus || opt_slot) {
1417 /* Check bus/slot. */
1418 if (opt_bus != pcidev->bus->number
1419 || opt_slot != PCI_SLOT(pcidev->devfn))
1420 continue; /* no match */
1423 * Look for device that isn't in use.
1424 * Enable PCI device and request regions.
1426 if (comedi_pci_enable(pcidev, DRV_NAME)) {
1428 "failed to enable PCI device and request regions!";
1431 /* fixup board_ptr in case we were using the dummy entry with the driver name */
1432 dev->board_ptr = &boardtypes[board_index];
1437 if (opt_bus || opt_slot) {
1438 dev_err(dev->hw_dev, "- Card at b:s %d:%d %s\n",
1439 opt_bus, opt_slot, errstr);
1441 dev_err(dev->hw_dev, "- Card %s\n", errstr);
1446 pci_bus = pcidev->bus->number;
1447 pci_slot = PCI_SLOT(pcidev->devfn);
1448 pci_func = PCI_FUNC(pcidev->devfn);
1450 iobase = pci_resource_start(pcidev, 2);
1452 dev_dbg(dev->hw_dev, "b:s:f=%d:%d:%d, io=0x%4lx\n", pci_bus, pci_slot,
1455 dev->iobase = iobase;
1457 dev->board_name = this_board->name;
1458 devpriv->pcidev = pcidev;
1461 if (this_board->n_aichan)
1463 if (this_board->n_aochan)
1465 if (this_board->n_dichan)
1467 if (this_board->n_dochan)
1469 if (this_board->n_counter)
1472 ret = alloc_subdevices(dev, n_subdevices);
1478 if (this_board->have_irq) {
1480 if (request_irq(irq, interrupt_service_pci1710,
1481 IRQF_SHARED, "Advantech PCI-1710",
1483 dev_dbg(dev->hw_dev, "unable to allocate IRQ %d, DISABLING IT",
1485 irq = 0; /* Can't use IRQ */
1487 dev_dbg(dev->hw_dev, "irq=%u", irq);
1490 dev_dbg(dev->hw_dev, "IRQ disabled");
1499 if (this_board->n_aichan) {
1500 s = dev->subdevices + subdev;
1501 dev->read_subdev = s;
1502 s->type = COMEDI_SUBD_AI;
1503 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND;
1504 if (this_board->n_aichand)
1505 s->subdev_flags |= SDF_DIFF;
1506 s->n_chan = this_board->n_aichan;
1507 s->maxdata = this_board->ai_maxdata;
1508 s->len_chanlist = this_board->n_aichan;
1509 s->range_table = this_board->rangelist_ai;
1510 s->cancel = pci171x_ai_cancel;
1511 s->insn_read = pci171x_insn_read_ai;
1513 s->subdev_flags |= SDF_CMD_READ;
1514 s->do_cmdtest = pci171x_ai_cmdtest;
1515 s->do_cmd = pci171x_ai_cmd;
1517 devpriv->i8254_osc_base = 100; /* 100ns=10MHz */
1521 if (this_board->n_aochan) {
1522 s = dev->subdevices + subdev;
1523 s->type = COMEDI_SUBD_AO;
1524 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1525 s->n_chan = this_board->n_aochan;
1526 s->maxdata = this_board->ao_maxdata;
1527 s->len_chanlist = this_board->n_aochan;
1528 s->range_table = this_board->rangelist_ao;
1529 switch (this_board->cardtype) {
1531 s->insn_write = pci1720_insn_write_ao;
1534 s->insn_write = pci171x_insn_write_ao;
1537 s->insn_read = pci171x_insn_read_ao;
1541 if (this_board->n_dichan) {
1542 s = dev->subdevices + subdev;
1543 s->type = COMEDI_SUBD_DI;
1544 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
1545 s->n_chan = this_board->n_dichan;
1547 s->len_chanlist = this_board->n_dichan;
1548 s->range_table = &range_digital;
1549 s->io_bits = 0; /* all bits input */
1550 s->insn_bits = pci171x_insn_bits_di;
1554 if (this_board->n_dochan) {
1555 s = dev->subdevices + subdev;
1556 s->type = COMEDI_SUBD_DO;
1557 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1558 s->n_chan = this_board->n_dochan;
1560 s->len_chanlist = this_board->n_dochan;
1561 s->range_table = &range_digital;
1562 /* all bits output */
1563 s->io_bits = (1 << this_board->n_dochan) - 1;
1565 s->insn_bits = pci171x_insn_bits_do;
1569 if (this_board->n_counter) {
1570 s = dev->subdevices + subdev;
1571 s->type = COMEDI_SUBD_COUNTER;
1572 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
1573 s->n_chan = this_board->n_counter;
1574 s->len_chanlist = this_board->n_counter;
1575 s->maxdata = 0xffff;
1576 s->range_table = &range_unknown;
1577 s->insn_read = pci171x_insn_counter_read;
1578 s->insn_write = pci171x_insn_counter_write;
1579 s->insn_config = pci171x_insn_counter_config;
1589 ==============================================================================
1591 static int pci1710_detach(struct comedi_device *dev)
1598 free_irq(dev->irq, dev);
1599 if (devpriv->pcidev) {
1601 comedi_pci_disable(devpriv->pcidev);
1603 pci_dev_put(devpriv->pcidev);
1611 ==============================================================================
1613 static int __devinit driver_pci1710_pci_probe(struct pci_dev *dev,
1614 const struct pci_device_id *ent)
1616 return comedi_pci_auto_config(dev, &driver_pci1710);
1619 static void __devexit driver_pci1710_pci_remove(struct pci_dev *dev)
1621 comedi_pci_auto_unconfig(dev);
1624 static struct pci_driver driver_pci1710_pci_driver = {
1625 .id_table = pci1710_pci_table,
1626 .probe = &driver_pci1710_pci_probe,
1627 .remove = __devexit_p(&driver_pci1710_pci_remove)
1630 static int __init driver_pci1710_init_module(void)
1634 retval = comedi_driver_register(&driver_pci1710);
1638 driver_pci1710_pci_driver.name = (char *)driver_pci1710.driver_name;
1639 return pci_register_driver(&driver_pci1710_pci_driver);
1642 static void __exit driver_pci1710_cleanup_module(void)
1644 pci_unregister_driver(&driver_pci1710_pci_driver);
1645 comedi_driver_unregister(&driver_pci1710);
1648 module_init(driver_pci1710_init_module);
1649 module_exit(driver_pci1710_cleanup_module);
1651 ==============================================================================
1654 MODULE_AUTHOR("Comedi http://www.comedi.org");
1655 MODULE_DESCRIPTION("Comedi low-level driver");
1656 MODULE_LICENSE("GPL");