2 * comedi/drivers/adl_pci9118.c
4 * hardware driver for ADLink cards:
5 * card: PCI-9118DG, PCI-9118HG, PCI-9118HR
6 * driver: pci9118dg, pci9118hg, pci9118hr
8 * Author: Michal Dobes <dobes@tesnet.cz>
13 Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
14 Author: Michal Dobes <dobes@tesnet.cz>
15 Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
16 PCI-9118HR (pci9118hr)
19 This driver supports AI, AO, DI and DO subdevices.
20 AI subdevice supports cmd and insn interface,
21 other subdevices support only insn interface.
23 - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
24 - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
25 - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
26 - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
27 cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
28 - If return value of cmdtest is 5 then you've bad channel list
29 (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
32 There are some hardware limitations:
33 a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
35 b) DMA transfers must have the length aligned to two samples (32 bit),
36 so there is some problems if cmd->chanlist_len is odd. This driver tries
37 bypass this with adding one sample to the end of the every scan and discard
38 it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
39 and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
40 with interrupt after every sample.
41 c) If isn't used DMA then you can use only mode where
42 cmd->scan_begin_src=TRIG_FOLLOW.
44 Configuration options:
45 [0] - PCI bus of device (optional)
46 [1] - PCI slot of device (optional)
47 If bus/slot is not specified, then first available PCI
49 [2] - 0= standard 8 DIFF/16 SE channels configuration
50 n = external multiplexer connected, 1 <= n <= 256
51 [3] - 0=autoselect DMA or EOC interrupts operation
53 3 = disable DMA and INT, only insn interface will work
54 [4] - sample&hold signal - card can generate signal for external S&H board
55 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
56 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
57 long delay is requested in ns and sign polarity of the hold
58 (in this case external multiplexor can serve only 128 channels)
59 [5] - 0=stop measure on all hardware errors
60 2 | = ignore ADOR - A/D Overrun status
61 8|=ignore Bover - A/D Burst Mode Overrun status
62 256|=ignore nFull - A/D FIFO Full status
69 * All the supported boards have the same PCI vendor and device IDs, so
70 * auto-attachment of PCI devices will always find the first board type.
72 * Perhaps the boards have different subdevice IDs that we could use to
75 * Need some device attributes so the board type can be corrected after
76 * attachment if necessary, and possibly to set other options supported by
80 #include <linux/module.h>
81 #include <linux/pci.h>
82 #include <linux/delay.h>
83 #include <linux/gfp.h>
84 #include <linux/interrupt.h>
87 #include "../comedidev.h"
89 #include "amcc_s5933.h"
91 #include "comedi_fc.h"
93 /* paranoid checks are broken */
94 #undef PCI9118_PARANOIDCHECK /*
95 * if defined, then is used code which control
96 * correct channel number on every 12 bit sample
99 #define IORANGE_9118 64 /* I hope */
100 #define PCI9118_CHANLEN 255 /*
101 * len of chanlist, some source say 256,
102 * but reality looks like 255 :-(
105 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
106 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
107 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
108 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
109 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
110 #define PCI9118_DA1 0x10 /* W: D/A registers */
111 #define PCI9118_DA2 0x14
112 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
113 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
114 #define PCI9118_DI 0x1c /* R: digi input register */
115 #define PCI9118_DO 0x1c /* W: digi output register */
116 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
117 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
118 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
119 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
120 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
121 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
122 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
123 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
125 /* bits from A/D control register (PCI9118_ADCNTRL) */
126 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
127 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
128 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
129 #define AdControl_ExtG 0x10 /*
130 * 1=8254 countrol controlled by TGIN(pin 46),
131 * 0=controlled by SoftG
133 #define AdControl_ExtM 0x08 /*
134 * 1=external hardware trigger (pin 44),
137 #define AdControl_TmrTr 0x04 /*
138 * 1=8254 is iternal trigger source,
139 * 0=software trigger is source
140 * (register PCI9118_SOFTTRG)
142 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
143 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
145 /* bits from A/D function register (PCI9118_ADFUNC) */
146 #define AdFunction_PDTrg 0x80 /*
148 * 0=negative digital trigger
149 * (only positive is correct)
151 #define AdFunction_PETrg 0x40 /*
153 * 0=negative external trigger
154 * (only positive is correct)
156 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
157 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
158 #define AdFunction_BS 0x08 /*
159 * 1=burst mode start,
162 #define AdFunction_PM 0x04 /*
163 * 1=post trigger mode,
166 #define AdFunction_AM 0x02 /*
167 * 1=about trigger mode,
168 * 0=not about trigger
170 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
172 /* bits from A/D status register (PCI9118_ADSTAT) */
173 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
174 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
175 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
176 #define AdStatus_Acmp 0x020 /* */
177 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
178 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
179 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
180 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
181 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
183 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
184 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
185 #define Int_Timer 0x08 /* timer interrupt */
186 #define Int_About 0x04 /* about trigger complete */
187 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
188 #define Int_DTrg 0x01 /* external digital trigger */
190 #define START_AI_EXT 0x01 /* start measure on external trigger */
191 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
192 #define START_AI_INT 0x04 /* start measure on internal trigger */
193 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
195 #define EXTTRG_AI 0 /* ext trg is used by AI */
197 static const struct comedi_lrange range_pci9118dg_hr = {
210 static const struct comedi_lrange range_pci9118hg = {
223 #define PCI9118_BIPOLAR_RANGES 4 /*
224 * used for test on mixture
229 const char *name; /* board name */
230 int device_id; /* PCI device ID of card */
231 int iorange_amcc; /* iorange for own S5933 region */
232 int iorange_9118; /* pass thru card region size */
233 int n_aichan; /* num of A/D chans */
234 int n_aichand; /* num of A/D chans in diff mode */
236 * num of A/D chans with
237 * external multiplexor
239 int n_aichanlist; /* len of chanlist */
240 int n_aochan; /* num of D/A chans */
241 int ai_maxdata; /* resolution of A/D */
242 int ao_maxdata; /* resolution of D/A */
243 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
244 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
245 unsigned int ai_ns_min; /* max sample speed of card v ns */
246 unsigned int ai_pacer_min; /*
247 * minimal pacer value
248 * (c1*c2 or c1 in burst)
250 int half_fifo_size; /* size of FIFO/2 */
254 static const struct boardtype boardtypes[] = {
258 .iorange_amcc = AMCC_OP_REG_SIZE,
259 .iorange_9118 = IORANGE_9118,
263 .n_aichanlist = PCI9118_CHANLEN,
265 .ai_maxdata = 0x0fff,
266 .ao_maxdata = 0x0fff,
267 .rangelist_ai = &range_pci9118dg_hr,
268 .rangelist_ao = &range_bipolar10,
271 .half_fifo_size = 512,
275 .iorange_amcc = AMCC_OP_REG_SIZE,
276 .iorange_9118 = IORANGE_9118,
280 .n_aichanlist = PCI9118_CHANLEN,
282 .ai_maxdata = 0x0fff,
283 .ao_maxdata = 0x0fff,
284 .rangelist_ai = &range_pci9118hg,
285 .rangelist_ao = &range_bipolar10,
288 .half_fifo_size = 512,
292 .iorange_amcc = AMCC_OP_REG_SIZE,
293 .iorange_9118 = IORANGE_9118,
297 .n_aichanlist = PCI9118_CHANLEN,
299 .ai_maxdata = 0xffff,
300 .ao_maxdata = 0x0fff,
301 .rangelist_ai = &range_pci9118dg_hr,
302 .rangelist_ao = &range_bipolar10,
305 .half_fifo_size = 512,
309 struct pci9118_private {
310 unsigned long iobase_a; /* base+size for AMCC chip */
311 unsigned int master; /* master capable */
312 unsigned int usemux; /* we want to use external multiplexor! */
313 #ifdef PCI9118_PARANOIDCHECK
314 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
318 unsigned char chanlistlen; /* number of scanlist */
320 unsigned char AdControlReg; /* A/D control register */
321 unsigned char IntControlReg; /* Interrupt control register */
322 unsigned char AdFunctionReg; /* A/D function register */
323 char ai_neverending; /* we do unlimited AI */
324 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
325 unsigned int ai_act_scan; /* how many scans we finished */
326 unsigned int ai_n_realscanlen; /*
327 * what we must transfer for one
328 * outgoing scan include front/back adds
330 unsigned int ai_act_dmapos; /* position in actual real stream */
331 unsigned int ai_add_front; /*
332 * how many channels we must add
333 * before scan to satisfy S&H?
335 unsigned int ai_add_back; /*
336 * how many channels we must add
337 * before scan to satisfy DMA?
339 unsigned int ai_flags;
340 char ai12_startstop; /*
341 * measure can start/stop
342 * on external trigger
344 unsigned int ai_divisor1, ai_divisor2; /*
345 * divisors for start of measure
348 unsigned short ao_data[2]; /* data output buffer */
349 char dma_doublebuf; /* we can use double buffering */
350 unsigned int dma_actbuf; /* which buffer is used now */
351 unsigned short *dmabuf_virt[2]; /*
352 * pointers to begin of
355 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
356 unsigned int dmabuf_size[2]; /*
357 * size of dma buffer in bytes
359 unsigned int dmabuf_use_size[2]; /*
360 * which size we may now use
363 unsigned int dmabuf_used_size[2]; /* which size was truly used */
364 unsigned int dmabuf_panic_size[2];
365 int dmabuf_pages[2]; /* number of pages in buffer */
366 unsigned char exttrg_users; /*
367 * bit field of external trigger
368 * users(0-AI, 1-AO, 2-DI, 3-DO)
370 unsigned char usedma; /* =1 use DMA transfer and not INT */
372 * >0 use software S&H,
373 * numer is requested delay in ns
375 unsigned char softsshsample; /*
376 * polarity of S&H signal
379 unsigned char softsshhold; /*
380 * polarity of S&H signal
383 unsigned int ai_maskerr; /* which warning was printed */
384 unsigned int ai_maskharderr; /* on which error bits stops */
387 static int check_channel_list(struct comedi_device *dev,
388 struct comedi_subdevice *s, int n_chan,
389 unsigned int *chanlist, int frontadd, int backadd)
391 const struct boardtype *this_board = comedi_board(dev);
392 struct pci9118_private *devpriv = dev->private;
393 unsigned int i, differencial = 0, bipolar = 0;
395 /* correct channel and range number check itself comedi/range.c */
397 comedi_error(dev, "range/channel list is empty!");
400 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
402 "range/channel list is too long for actual configuration!\n");
406 if (CR_AREF(chanlist[0]) == AREF_DIFF)
407 differencial = 1; /* all input must be diff */
408 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
409 bipolar = 1; /* all input must be bipolar */
411 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
412 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
415 "Differencial and single ended "
416 "inputs can't be mixtured!");
419 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
422 "Bipolar and unipolar ranges "
423 "can't be mixtured!");
426 if (!devpriv->usemux && differencial &&
427 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
429 "If AREF_DIFF is used then is "
430 "available only first 8 channels!");
438 static int setup_channel_list(struct comedi_device *dev,
439 struct comedi_subdevice *s, int n_chan,
440 unsigned int *chanlist, int rot, int frontadd,
441 int backadd, int usedma)
443 struct pci9118_private *devpriv = dev->private;
444 unsigned int i, differencial = 0, bipolar = 0;
445 unsigned int scanquad, gain, ssh = 0x00;
452 if (CR_AREF(chanlist[0]) == AREF_DIFF)
453 differencial = 1; /* all input must be diff */
454 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
455 bipolar = 1; /* all input must be bipolar */
457 /* All is ok, so we can setup channel/range list */
460 devpriv->AdControlReg |= AdControl_UniP;
463 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
468 devpriv->AdControlReg |= AdControl_Diff;
469 /* enable diff inputs */
471 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
472 /* set single ended inputs */
475 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
478 outl(2, dev->iobase + PCI9118_SCANMOD);
479 /* gods know why this sequence! */
480 outl(0, dev->iobase + PCI9118_SCANMOD);
481 outl(1, dev->iobase + PCI9118_SCANMOD);
483 #ifdef PCI9118_PARANOIDCHECK
484 devpriv->chanlistlen = n_chan;
485 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
486 devpriv->chanlist[i] = 0x55aa;
489 if (frontadd) { /* insert channels for S&H */
490 ssh = devpriv->softsshsample;
491 for (i = 0; i < frontadd; i++) {
492 /* store range list to card */
493 scanquad = CR_CHAN(chanlist[0]);
494 /* get channel number; */
495 gain = CR_RANGE(chanlist[0]);
496 /* get gain number */
497 scanquad |= ((gain & 0x03) << 8);
498 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
499 ssh = devpriv->softsshhold;
503 for (i = 0; i < n_chan; i++) { /* store range list to card */
504 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
505 #ifdef PCI9118_PARANOIDCHECK
506 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
508 gain = CR_RANGE(chanlist[i]); /* get gain number */
509 scanquad |= ((gain & 0x03) << 8);
510 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
513 if (backadd) { /* insert channels for fit onto 32bit DMA */
514 for (i = 0; i < backadd; i++) { /* store range list to card */
515 scanquad = CR_CHAN(chanlist[0]);
516 /* get channel number */
517 gain = CR_RANGE(chanlist[0]); /* get gain number */
518 scanquad |= ((gain & 0x03) << 8);
519 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
522 #ifdef PCI9118_PARANOIDCHECK
523 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
524 /* for 32bit operations */
526 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
527 /* udelay(100); important delay, or first sample will be crippled */
529 return 1; /* we can serve this with scan logic */
532 static int pci9118_ai_eoc(struct comedi_device *dev,
533 struct comedi_subdevice *s,
534 struct comedi_insn *insn,
535 unsigned long context)
539 status = inl(dev->iobase + PCI9118_ADSTAT);
540 if (status & AdStatus_ADrdy)
545 static int pci9118_insn_read_ai(struct comedi_device *dev,
546 struct comedi_subdevice *s,
547 struct comedi_insn *insn, unsigned int *data)
549 struct pci9118_private *devpriv = dev->private;
553 devpriv->AdControlReg = AdControl_Int & 0xff;
554 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
555 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
557 * positive triggers, no S&H,
558 * no burst, burst stop,
564 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0))
567 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
569 for (n = 0; n < insn->n; n++) {
570 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
573 ret = comedi_timeout(dev, s, insn, pci9118_ai_eoc, 0);
575 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
579 if (s->maxdata == 0xffff) {
582 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
585 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
589 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
594 static int pci9118_insn_write_ao(struct comedi_device *dev,
595 struct comedi_subdevice *s,
596 struct comedi_insn *insn, unsigned int *data)
598 struct pci9118_private *devpriv = dev->private;
601 ch = CR_CHAN(insn->chanspec);
603 chanreg = PCI9118_DA2;
605 chanreg = PCI9118_DA1;
608 for (n = 0; n < insn->n; n++) {
609 outl(data[n], dev->iobase + chanreg);
610 devpriv->ao_data[ch] = data[n];
616 static int pci9118_insn_read_ao(struct comedi_device *dev,
617 struct comedi_subdevice *s,
618 struct comedi_insn *insn, unsigned int *data)
620 struct pci9118_private *devpriv = dev->private;
623 chan = CR_CHAN(insn->chanspec);
624 for (n = 0; n < insn->n; n++)
625 data[n] = devpriv->ao_data[chan];
630 static int pci9118_insn_bits_di(struct comedi_device *dev,
631 struct comedi_subdevice *s,
632 struct comedi_insn *insn, unsigned int *data)
634 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
639 static int pci9118_insn_bits_do(struct comedi_device *dev,
640 struct comedi_subdevice *s,
641 struct comedi_insn *insn,
644 if (comedi_dio_update_state(s, data))
645 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
652 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
654 struct pci9118_private *devpriv = dev->private;
656 devpriv->AdFunctionReg =
657 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
658 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
659 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
660 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
661 dev->iobase + PCI9118_CNT0);
662 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
663 dev->iobase + PCI9118_CNT0);
664 devpriv->AdFunctionReg |= AdFunction_Start;
665 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
668 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
669 struct comedi_subdevice *s,
670 unsigned short *dma_buffer,
671 unsigned int num_samples)
673 struct pci9118_private *devpriv = dev->private;
674 struct comedi_cmd *cmd = &s->async->cmd;
675 unsigned int i = 0, j = 0;
676 unsigned int start_pos = devpriv->ai_add_front,
677 stop_pos = devpriv->ai_add_front + cmd->chanlist_len;
678 unsigned int raw_scanlen = devpriv->ai_add_front + cmd->chanlist_len +
679 devpriv->ai_add_back;
681 for (i = 0; i < num_samples; i++) {
682 if (devpriv->ai_act_dmapos >= start_pos &&
683 devpriv->ai_act_dmapos < stop_pos) {
684 dma_buffer[j++] = dma_buffer[i];
686 devpriv->ai_act_dmapos++;
687 devpriv->ai_act_dmapos %= raw_scanlen;
693 static int move_block_from_dma(struct comedi_device *dev,
694 struct comedi_subdevice *s,
695 unsigned short *dma_buffer,
696 unsigned int num_samples)
698 struct pci9118_private *devpriv = dev->private;
699 struct comedi_cmd *cmd = &s->async->cmd;
700 unsigned int num_bytes;
702 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
703 devpriv->ai_act_scan +=
704 (s->async->cur_chan + num_samples) / cmd->scan_end_arg;
705 s->async->cur_chan += num_samples;
706 s->async->cur_chan %= cmd->scan_end_arg;
708 cfc_write_array_to_buffer(s, dma_buffer,
709 num_samples * sizeof(short));
710 if (num_bytes < num_samples * sizeof(short))
715 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
717 struct pci9118_private *devpriv = dev->private;
720 return -1; /* incorrect source */
721 devpriv->exttrg_users |= (1 << source);
722 devpriv->IntControlReg |= Int_DTrg;
723 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
724 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
725 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
726 /* allow INT in AMCC */
730 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
732 struct pci9118_private *devpriv = dev->private;
735 return -1; /* incorrect source */
736 devpriv->exttrg_users &= ~(1 << source);
737 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
738 devpriv->IntControlReg &= ~Int_DTrg;
739 if (!devpriv->IntControlReg) /* all IRQ disabled */
740 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
742 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
743 /* disable int in AMCC */
744 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
749 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
750 struct comedi_subdevice *s,
751 unsigned int *tim1, unsigned int *tim2,
752 unsigned int flags, int chans,
753 unsigned int *div1, unsigned int *div2,
754 unsigned int chnsshfront)
756 const struct boardtype *this_board = comedi_board(dev);
757 struct comedi_cmd *cmd = &s->async->cmd;
762 if (*tim2 < this_board->ai_ns_min)
763 *tim2 = this_board->ai_ns_min;
764 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
766 tim2, flags & TRIG_ROUND_NEAREST);
769 if (*tim2 < this_board->ai_ns_min)
770 *tim2 = this_board->ai_ns_min;
771 *div1 = *tim2 / I8254_OSC_BASE_4MHZ;
772 /* convert timer (burst) */
773 if (*div1 < this_board->ai_pacer_min)
774 *div1 = this_board->ai_pacer_min;
775 *div2 = *tim1 / I8254_OSC_BASE_4MHZ; /* scan timer */
776 *div2 = *div2 / *div1; /* major timer is c1*c2 */
780 *tim2 = *div1 * I8254_OSC_BASE_4MHZ; /* real convert timer */
782 if (cmd->convert_src == TRIG_NOW && !chnsshfront) {
783 /* use BSSH signal */
784 if (*div2 < (chans + 2))
788 *tim1 = *div1 * *div2 * I8254_OSC_BASE_4MHZ;
793 static void pci9118_start_pacer(struct comedi_device *dev, int mode)
795 struct pci9118_private *devpriv = dev->private;
796 unsigned int divisor1 = devpriv->ai_divisor1;
797 unsigned int divisor2 = devpriv->ai_divisor2;
799 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
800 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
801 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
804 if ((mode == 1) || (mode == 2) || (mode == 4)) {
805 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
806 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
807 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
808 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
812 static int pci9118_ai_cancel(struct comedi_device *dev,
813 struct comedi_subdevice *s)
815 struct pci9118_private *devpriv = dev->private;
818 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
820 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
821 pci9118_exttrg_del(dev, EXTTRG_AI);
822 pci9118_start_pacer(dev, 0); /* stop 8254 counters */
823 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
824 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
826 * positive triggers, no S&H, no burst,
827 * burst stop, no post trigger,
828 * no about trigger, trigger stop
830 devpriv->AdControlReg = 0x00;
831 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
833 * bipolar, S.E., use 8254, stop 8354,
834 * internal trigger, soft trigger,
835 * disable INT and DMA
837 outl(0, dev->iobase + PCI9118_BURST);
838 outl(1, dev->iobase + PCI9118_SCANMOD);
839 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
840 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
845 devpriv->ai_act_scan = 0;
846 devpriv->ai_act_dmapos = 0;
847 s->async->cur_chan = 0;
848 s->async->inttrig = NULL;
849 devpriv->ai_neverending = 0;
850 devpriv->dma_actbuf = 0;
852 if (!devpriv->IntControlReg)
853 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
854 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
855 /* allow INT in AMCC */
860 static char pci9118_decode_error_status(struct comedi_device *dev,
861 struct comedi_subdevice *s,
864 struct pci9118_private *devpriv = dev->private;
867 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
868 devpriv->ai_maskerr &= ~0x100L;
872 "A/D Burst Mode Overrun Status (Fatal Error!)");
873 devpriv->ai_maskerr &= ~0x008L;
876 comedi_error(dev, "A/D Over Speed Status (Warning!)");
877 devpriv->ai_maskerr &= ~0x004L;
880 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
881 devpriv->ai_maskerr &= ~0x002L;
883 if (m & devpriv->ai_maskharderr) {
884 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
885 cfc_handle_events(dev, s);
892 static void pci9118_ai_munge(struct comedi_device *dev,
893 struct comedi_subdevice *s, void *data,
894 unsigned int num_bytes,
895 unsigned int start_chan_index)
897 struct pci9118_private *devpriv = dev->private;
898 unsigned int i, num_samples = num_bytes / sizeof(short);
899 unsigned short *array = data;
901 for (i = 0; i < num_samples; i++) {
903 array[i] = be16_to_cpu(array[i]);
904 if (s->maxdata == 0xffff)
907 array[i] = (array[i] >> 4) & 0x0fff;
912 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
913 struct comedi_subdevice *s,
914 unsigned short int_adstat,
915 unsigned int int_amcc,
916 unsigned short int_daq)
918 struct pci9118_private *devpriv = dev->private;
919 struct comedi_cmd *cmd = &s->async->cmd;
920 unsigned short sampl;
922 if (int_adstat & devpriv->ai_maskerr)
923 if (pci9118_decode_error_status(dev, s, int_adstat))
926 sampl = inw(dev->iobase + PCI9118_AD_DATA);
928 #ifdef PCI9118_PARANOIDCHECK
929 if (s->maxdata != 0xffff) {
930 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
932 dev_info(dev->class_dev,
933 "A/D SAMPL - data dropout: received channel %d, expected %d!\n",
935 devpriv->chanlist[s->async->cur_chan]);
936 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
937 cfc_handle_events(dev, s);
942 cfc_write_to_buffer(s, sampl);
943 s->async->cur_chan++;
944 if (s->async->cur_chan >= cmd->scan_end_arg) {
946 s->async->cur_chan %= cmd->scan_end_arg;
947 devpriv->ai_act_scan++;
948 if (!devpriv->ai_neverending) {
949 /* all data sampled? */
950 if (devpriv->ai_act_scan >= cmd->stop_arg)
951 s->async->events |= COMEDI_CB_EOA;
955 cfc_handle_events(dev, s);
958 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
959 struct comedi_subdevice *s,
960 unsigned short int_adstat,
961 unsigned int int_amcc,
962 unsigned short int_daq)
964 struct pci9118_private *devpriv = dev->private;
965 struct comedi_cmd *cmd = &s->async->cmd;
966 unsigned int next_dma_buf, samplesinbuf, sampls, m;
968 if (int_amcc & MASTER_ABORT_INT) {
969 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
970 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
971 cfc_handle_events(dev, s);
975 if (int_amcc & TARGET_ABORT_INT) {
976 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
977 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
978 cfc_handle_events(dev, s);
981 if (int_adstat & devpriv->ai_maskerr)
982 /* if (int_adstat & 0x106) */
983 if (pci9118_decode_error_status(dev, s, int_adstat))
986 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
987 /* number of received real samples */
989 if (devpriv->dma_doublebuf) { /*
990 * switch DMA buffers if is used
993 next_dma_buf = 1 - devpriv->dma_actbuf;
994 outl(devpriv->dmabuf_hw[next_dma_buf],
995 devpriv->iobase_a + AMCC_OP_REG_MWAR);
996 outl(devpriv->dmabuf_use_size[next_dma_buf],
997 devpriv->iobase_a + AMCC_OP_REG_MWTC);
998 devpriv->dmabuf_used_size[next_dma_buf] =
999 devpriv->dmabuf_use_size[next_dma_buf];
1000 if (devpriv->ai_do == 4)
1001 interrupt_pci9118_ai_mode4_switch(dev);
1005 /* how many samples is to end of buffer */
1006 m = s->async->prealloc_bufsz >> 1;
1008 move_block_from_dma(dev, s,
1009 devpriv->dmabuf_virt[devpriv->dma_actbuf],
1011 m = m - sampls; /* m=how many samples was transferred */
1014 if (!devpriv->ai_neverending) {
1015 /* all data sampled? */
1016 if (devpriv->ai_act_scan >= cmd->stop_arg)
1017 s->async->events |= COMEDI_CB_EOA;
1020 if (devpriv->dma_doublebuf) { /* switch dma buffers */
1021 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
1022 } else { /* restart DMA if is not used double buffering */
1023 outl(devpriv->dmabuf_hw[0],
1024 devpriv->iobase_a + AMCC_OP_REG_MWAR);
1025 outl(devpriv->dmabuf_use_size[0],
1026 devpriv->iobase_a + AMCC_OP_REG_MWTC);
1027 if (devpriv->ai_do == 4)
1028 interrupt_pci9118_ai_mode4_switch(dev);
1031 cfc_handle_events(dev, s);
1034 static irqreturn_t pci9118_interrupt(int irq, void *d)
1036 struct comedi_device *dev = d;
1037 struct comedi_subdevice *s = dev->read_subdev;
1038 struct pci9118_private *devpriv = dev->private;
1039 unsigned int intsrc; /* IRQ reasons from card */
1040 unsigned int intcsr; /* INT register from AMCC chip */
1041 unsigned int adstat; /* STATUS register */
1046 intsrc = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
1047 intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1049 if (!intsrc && !(intcsr & ANY_S593X_INT))
1052 outl(intcsr | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1054 adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
1056 if (!devpriv->ai_do)
1059 if (devpriv->ai12_startstop) {
1060 if ((adstat & AdStatus_DTH) && (intsrc & Int_DTrg)) {
1061 /* start/stop of measure */
1062 if (devpriv->ai12_startstop & START_AI_EXT) {
1063 /* deactivate EXT trigger */
1064 devpriv->ai12_startstop &= ~START_AI_EXT;
1065 if (!(devpriv->ai12_startstop & STOP_AI_EXT))
1066 pci9118_exttrg_del(dev, EXTTRG_AI);
1069 pci9118_start_pacer(dev, devpriv->ai_do);
1070 outl(devpriv->AdControlReg,
1071 dev->iobase + PCI9118_ADCNTRL);
1072 } else if (devpriv->ai12_startstop & STOP_AI_EXT) {
1073 /* deactivate EXT trigger */
1074 devpriv->ai12_startstop &= ~STOP_AI_EXT;
1075 pci9118_exttrg_del(dev, EXTTRG_AI);
1077 /* on next interrupt measure will stop */
1078 devpriv->ai_neverending = 0;
1083 if (devpriv->usedma)
1084 interrupt_pci9118_ai_dma(dev, s, adstat, intcsr, intsrc);
1086 interrupt_pci9118_ai_onesample(dev, s, adstat, intcsr, intsrc);
1091 static int pci9118_ai_inttrig(struct comedi_device *dev,
1092 struct comedi_subdevice *s,
1093 unsigned int trig_num)
1095 struct pci9118_private *devpriv = dev->private;
1096 struct comedi_cmd *cmd = &s->async->cmd;
1098 if (trig_num != cmd->start_arg)
1101 devpriv->ai12_startstop &= ~START_AI_INT;
1102 s->async->inttrig = NULL;
1104 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1105 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1106 if (devpriv->ai_do != 3) {
1107 pci9118_start_pacer(dev, devpriv->ai_do);
1108 devpriv->AdControlReg |= AdControl_SoftG;
1110 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1115 static int pci9118_ai_cmdtest(struct comedi_device *dev,
1116 struct comedi_subdevice *s,
1117 struct comedi_cmd *cmd)
1119 const struct boardtype *this_board = comedi_board(dev);
1120 struct pci9118_private *devpriv = dev->private;
1124 unsigned int divisor1 = 0, divisor2 = 0;
1126 /* Step 1 : check if triggers are trivially valid */
1128 err |= cfc_check_trigger_src(&cmd->start_src,
1129 TRIG_NOW | TRIG_EXT | TRIG_INT);
1131 flags = TRIG_FOLLOW;
1132 if (devpriv->master)
1133 flags |= TRIG_TIMER | TRIG_EXT;
1134 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1136 flags = TRIG_TIMER | TRIG_EXT;
1137 if (devpriv->master)
1139 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
1141 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1142 err |= cfc_check_trigger_src(&cmd->stop_src,
1143 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1148 /* Step 2a : make sure trigger sources are unique */
1150 err |= cfc_check_trigger_is_unique(cmd->start_src);
1151 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1152 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1153 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1155 /* Step 2b : and mutually compatible */
1157 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1160 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
1163 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1164 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1167 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1168 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1171 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1177 /* Step 3: check if arguments are trivially valid */
1179 switch (cmd->start_src) {
1182 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1185 /* start_arg is the internal trigger (any value) */
1189 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1190 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1192 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1193 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1194 cmd->scan_begin_src = TRIG_FOLLOW;
1195 cmd->convert_arg = cmd->scan_begin_arg;
1196 cmd->scan_begin_arg = 0;
1199 if (cmd->scan_begin_src == TRIG_TIMER)
1200 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1201 this_board->ai_ns_min);
1203 if (cmd->scan_begin_src == TRIG_EXT)
1204 if (cmd->scan_begin_arg) {
1205 cmd->scan_begin_arg = 0;
1207 err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg,
1211 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1212 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1213 this_board->ai_ns_min);
1215 if (cmd->convert_src == TRIG_EXT)
1216 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1218 if (cmd->stop_src == TRIG_COUNT)
1219 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1220 else /* TRIG_NONE */
1221 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1223 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
1225 err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg,
1228 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1230 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1237 /* step 4: fix up any arguments */
1239 if (cmd->scan_begin_src == TRIG_TIMER) {
1240 arg = cmd->scan_begin_arg;
1241 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
1242 &divisor1, &divisor2,
1244 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
1247 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1248 arg = cmd->convert_arg;
1249 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
1250 &divisor1, &divisor2,
1252 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
1254 if (cmd->scan_begin_src == TRIG_TIMER &&
1255 cmd->convert_src == TRIG_NOW) {
1256 if (cmd->convert_arg == 0) {
1257 arg = this_board->ai_ns_min *
1258 (cmd->scan_end_arg + 2);
1260 arg = cmd->convert_arg * cmd->chanlist_len;
1262 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1271 if (!check_channel_list(dev, s, cmd->chanlist_len,
1272 cmd->chanlist, 0, 0))
1273 return 5; /* incorrect channels list */
1278 static int Compute_and_setup_dma(struct comedi_device *dev,
1279 struct comedi_subdevice *s)
1281 struct pci9118_private *devpriv = dev->private;
1282 struct comedi_cmd *cmd = &s->async->cmd;
1283 unsigned int dmalen0, dmalen1, i;
1285 dmalen0 = devpriv->dmabuf_size[0];
1286 dmalen1 = devpriv->dmabuf_size[1];
1287 /* isn't output buff smaller that our DMA buff? */
1288 if (dmalen0 > s->async->prealloc_bufsz) {
1289 /* align to 32bit down */
1290 dmalen0 = s->async->prealloc_bufsz & ~3L;
1292 if (dmalen1 > s->async->prealloc_bufsz) {
1293 /* align to 32bit down */
1294 dmalen1 = s->async->prealloc_bufsz & ~3L;
1297 /* we want wake up every scan? */
1298 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1299 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1300 /* uff, too short DMA buffer, disable EOS support! */
1301 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1302 dev_info(dev->class_dev,
1303 "WAR: DMA0 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1304 dmalen0, devpriv->ai_n_realscanlen << 1);
1306 /* short first DMA buffer to one scan */
1307 dmalen0 = devpriv->ai_n_realscanlen << 1;
1309 dev_info(dev->class_dev,
1310 "ERR: DMA0 buf len bug? (%d<4)\n",
1316 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1317 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1318 /* uff, too short DMA buffer, disable EOS support! */
1319 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1320 dev_info(dev->class_dev,
1321 "WAR: DMA1 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1322 dmalen1, devpriv->ai_n_realscanlen << 1);
1324 /* short second DMA buffer to one scan */
1325 dmalen1 = devpriv->ai_n_realscanlen << 1;
1327 dev_info(dev->class_dev,
1328 "ERR: DMA1 buf len bug? (%d<4)\n",
1335 /* transfer without TRIG_WAKE_EOS */
1336 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1337 /* if it's possible then align DMA buffers to length of scan */
1340 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1341 (devpriv->ai_n_realscanlen << 1);
1344 dmalen0 = i; /* uff. very long scan? */
1347 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1348 (devpriv->ai_n_realscanlen << 1);
1351 dmalen1 = i; /* uff. very long scan? */
1353 * if measure isn't neverending then test, if it fits whole
1354 * into one or two DMA buffers
1356 if (!devpriv->ai_neverending) {
1357 /* fits whole measure into one DMA buffer? */
1359 ((devpriv->ai_n_realscanlen << 1) *
1362 (devpriv->ai_n_realscanlen << 1) *
1366 * fits whole measure into
1370 ((devpriv->ai_n_realscanlen << 1) *
1371 cmd->stop_arg - dmalen0))
1373 (devpriv->ai_n_realscanlen << 1) *
1374 cmd->stop_arg - dmalen0;
1380 /* these DMA buffer size will be used */
1381 devpriv->dma_actbuf = 0;
1382 devpriv->dmabuf_use_size[0] = dmalen0;
1383 devpriv->dmabuf_use_size[1] = dmalen1;
1386 if (cmd->scan_end_arg < this_board->half_fifo_size) {
1387 devpriv->dmabuf_panic_size[0] =
1388 (this_board->half_fifo_size / cmd->scan_end_arg +
1389 1) * cmd->scan_end_arg * sizeof(short);
1390 devpriv->dmabuf_panic_size[1] =
1391 (this_board->half_fifo_size / cmd->scan_end_arg +
1392 1) * cmd->scan_end_arg * sizeof(short);
1394 devpriv->dmabuf_panic_size[0] =
1395 (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[0];
1396 devpriv->dmabuf_panic_size[1] =
1397 (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[1];
1401 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1402 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1403 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1404 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1405 /* init DMA transfer */
1406 outl(0x00000000 | AINT_WRITE_COMPL,
1407 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1408 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1410 outl(inl(devpriv->iobase_a +
1411 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1412 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1413 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1414 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1415 /* allow bus mastering */
1420 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1421 struct comedi_subdevice *s)
1423 struct pci9118_private *devpriv = dev->private;
1425 switch (devpriv->ai_do) {
1427 devpriv->AdControlReg |= AdControl_TmrTr;
1430 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1433 devpriv->AdControlReg |= AdControl_ExtM;
1436 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1440 "pci9118_ai_docmd_sampl() mode number bug!\n");
1444 if (devpriv->ai12_startstop)
1445 pci9118_exttrg_add(dev, EXTTRG_AI);
1446 /* activate EXT trigger */
1448 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1449 devpriv->IntControlReg |= Int_Timer;
1451 devpriv->AdControlReg |= AdControl_Int;
1453 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1454 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1455 /* allow INT in AMCC */
1457 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1458 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1459 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1460 if (devpriv->ai_do != 3) {
1461 pci9118_start_pacer(dev, devpriv->ai_do);
1462 devpriv->AdControlReg |= AdControl_SoftG;
1464 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1470 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1471 struct comedi_subdevice *s)
1473 struct pci9118_private *devpriv = dev->private;
1474 struct comedi_cmd *cmd = &s->async->cmd;
1476 Compute_and_setup_dma(dev, s);
1478 switch (devpriv->ai_do) {
1480 devpriv->AdControlReg |=
1481 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1484 devpriv->AdControlReg |=
1485 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1486 devpriv->AdFunctionReg =
1487 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1489 if (cmd->convert_src == TRIG_NOW && !devpriv->softsshdelay)
1490 devpriv->AdFunctionReg |= AdFunction_BSSH;
1491 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1494 devpriv->AdControlReg |=
1495 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1496 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1499 devpriv->AdControlReg |=
1500 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1501 devpriv->AdFunctionReg =
1502 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1503 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1504 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1505 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1506 dev->iobase + PCI9118_CNT0);
1507 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1508 dev->iobase + PCI9118_CNT0);
1509 devpriv->AdFunctionReg |= AdFunction_Start;
1512 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1516 if (devpriv->ai12_startstop) {
1517 pci9118_exttrg_add(dev, EXTTRG_AI);
1518 /* activate EXT trigger */
1521 outl(0x02000000 | AINT_WRITE_COMPL,
1522 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1524 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1525 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1526 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1527 if (devpriv->ai_do != 3) {
1528 pci9118_start_pacer(dev, devpriv->ai_do);
1529 devpriv->AdControlReg |= AdControl_SoftG;
1531 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1537 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1539 const struct boardtype *this_board = comedi_board(dev);
1540 struct pci9118_private *devpriv = dev->private;
1541 struct comedi_cmd *cmd = &s->async->cmd;
1542 unsigned int addchans = 0;
1545 devpriv->ai12_startstop = 0;
1546 devpriv->ai_flags = cmd->flags;
1547 devpriv->ai_add_front = 0;
1548 devpriv->ai_add_back = 0;
1549 devpriv->ai_maskerr = 0x10e;
1551 /* prepare for start/stop conditions */
1552 if (cmd->start_src == TRIG_EXT)
1553 devpriv->ai12_startstop |= START_AI_EXT;
1554 if (cmd->stop_src == TRIG_EXT) {
1555 devpriv->ai_neverending = 1;
1556 devpriv->ai12_startstop |= STOP_AI_EXT;
1558 if (cmd->start_src == TRIG_INT) {
1559 devpriv->ai12_startstop |= START_AI_INT;
1560 s->async->inttrig = pci9118_ai_inttrig;
1562 if (cmd->stop_src == TRIG_NONE)
1563 devpriv->ai_neverending = 1;
1564 if (cmd->stop_src == TRIG_COUNT)
1565 devpriv->ai_neverending = 0;
1568 * use additional sample at end of every scan
1569 * to satisty DMA 32 bit transfer?
1571 devpriv->ai_add_front = 0;
1572 devpriv->ai_add_back = 0;
1573 if (devpriv->master) {
1574 devpriv->usedma = 1;
1575 if ((cmd->flags & TRIG_WAKE_EOS) &&
1576 (cmd->scan_end_arg == 1)) {
1577 if (cmd->convert_src == TRIG_NOW)
1578 devpriv->ai_add_back = 1;
1579 if (cmd->convert_src == TRIG_TIMER) {
1580 devpriv->usedma = 0;
1582 * use INT transfer if scanlist
1583 * have only one channel
1587 if ((cmd->flags & TRIG_WAKE_EOS) &&
1588 (cmd->scan_end_arg & 1) &&
1589 (cmd->scan_end_arg > 1)) {
1590 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1591 devpriv->usedma = 0;
1593 * XXX maybe can be corrected to use 16 bit DMA
1596 * well, we must insert one sample
1597 * to end of EOS to meet 32 bit transfer
1599 devpriv->ai_add_back = 1;
1602 } else { /* interrupt transfer don't need any correction */
1603 devpriv->usedma = 0;
1607 * we need software S&H signal?
1608 * It adds two samples before every scan as minimum
1610 if (cmd->convert_src == TRIG_NOW && devpriv->softsshdelay) {
1611 devpriv->ai_add_front = 2;
1612 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1613 /* move it to front */
1614 devpriv->ai_add_front++;
1615 devpriv->ai_add_back = 0;
1617 if (cmd->convert_arg < this_board->ai_ns_min)
1618 cmd->convert_arg = this_board->ai_ns_min;
1619 addchans = devpriv->softsshdelay / cmd->convert_arg;
1620 if (devpriv->softsshdelay % cmd->convert_arg)
1622 if (addchans > (devpriv->ai_add_front - 1)) {
1623 /* uff, still short */
1624 devpriv->ai_add_front = addchans + 1;
1625 if (devpriv->usedma == 1)
1626 if ((devpriv->ai_add_front +
1628 devpriv->ai_add_back) & 1)
1629 devpriv->ai_add_front++;
1630 /* round up to 32 bit */
1633 /* well, we now know what must be all added */
1634 devpriv->ai_n_realscanlen = /*
1635 * what we must take from card in real
1636 * to have cmd->scan_end_arg on output?
1638 (devpriv->ai_add_front + cmd->chanlist_len +
1639 devpriv->ai_add_back) * (cmd->scan_end_arg /
1642 /* check and setup channel list */
1643 if (!check_channel_list(dev, s, cmd->chanlist_len,
1644 cmd->chanlist, devpriv->ai_add_front,
1645 devpriv->ai_add_back))
1647 if (!setup_channel_list(dev, s, cmd->chanlist_len,
1648 cmd->chanlist, 0, devpriv->ai_add_front,
1649 devpriv->ai_add_back, devpriv->usedma))
1652 /* compute timers settings */
1654 * simplest way, fr=4Mhz/(tim1*tim2),
1655 * channel manipulation without timers effect
1657 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1658 (cmd->scan_begin_src == TRIG_EXT) ||
1659 (cmd->scan_begin_src == TRIG_INT)) &&
1660 (cmd->convert_src == TRIG_TIMER)) {
1661 /* both timer is used for one time */
1662 if (cmd->scan_begin_src == TRIG_EXT)
1666 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1667 &cmd->scan_begin_arg, &cmd->convert_arg,
1669 devpriv->ai_n_realscanlen,
1670 &devpriv->ai_divisor1,
1671 &devpriv->ai_divisor2,
1672 devpriv->ai_add_front);
1675 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1676 ((cmd->convert_src == TRIG_TIMER) ||
1677 (cmd->convert_src == TRIG_NOW))) {
1678 /* double timed action */
1679 if (!devpriv->usedma) {
1681 "cmd->scan_begin_src=TRIG_TIMER works "
1682 "only with bus mastering!");
1687 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1688 &cmd->scan_begin_arg, &cmd->convert_arg,
1690 devpriv->ai_n_realscanlen,
1691 &devpriv->ai_divisor1,
1692 &devpriv->ai_divisor2,
1693 devpriv->ai_add_front);
1696 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1697 && (cmd->convert_src == TRIG_EXT)) {
1701 pci9118_start_pacer(dev, -1); /* stop pacer */
1703 devpriv->AdControlReg = 0; /*
1704 * bipolar, S.E., use 8254, stop 8354,
1705 * internal trigger, soft trigger,
1708 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1709 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1711 * positive triggers, no S&H, no burst,
1712 * burst stop, no post trigger,
1713 * no about trigger, trigger stop
1715 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1717 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1718 inl(dev->iobase + PCI9118_ADSTAT); /*
1722 inl(dev->iobase + PCI9118_INTSRC);
1724 devpriv->ai_act_scan = 0;
1725 devpriv->ai_act_dmapos = 0;
1726 s->async->cur_chan = 0;
1728 if (devpriv->usedma)
1729 ret = pci9118_ai_docmd_dma(dev, s);
1731 ret = pci9118_ai_docmd_sampl(dev, s);
1736 static int pci9118_reset(struct comedi_device *dev)
1738 struct pci9118_private *devpriv = dev->private;
1740 devpriv->IntControlReg = 0;
1741 devpriv->exttrg_users = 0;
1742 inl(dev->iobase + PCI9118_INTCTRL);
1743 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1744 /* disable interrupts source */
1745 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1746 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1747 pci9118_start_pacer(dev, 0); /* stop 8254 counters */
1748 devpriv->AdControlReg = 0;
1749 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1751 * bipolar, S.E., use 8254,
1752 * stop 8354, internal trigger,
1754 * disable INT and DMA
1756 outl(0, dev->iobase + PCI9118_BURST);
1757 outl(1, dev->iobase + PCI9118_SCANMOD);
1758 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1759 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1760 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1762 * positive triggers, no S&H,
1763 * no burst, burst stop,
1769 devpriv->ao_data[0] = 2047;
1770 devpriv->ao_data[1] = 2047;
1771 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
1772 /* reset A/D outs to 0V */
1773 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1774 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
1776 inl(dev->iobase + PCI9118_AD_DATA);
1777 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1778 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1779 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1780 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
1781 devpriv->AdControlReg = 0;
1782 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1784 * bipolar, S.E., use 8254,
1785 * stop 8354, internal trigger,
1787 * disable INT and DMA
1790 devpriv->exttrg_users = 0;
1796 * FIXME - this is pretty ineffective because all the supported board types
1797 * have the same device ID!
1799 static const struct boardtype *pci9118_find_boardinfo(struct pci_dev *pcidev)
1803 for (i = 0; i < ARRAY_SIZE(boardtypes); i++)
1804 if (pcidev->device == boardtypes[i].device_id)
1805 return &boardtypes[i];
1809 static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1810 struct comedi_devconfig *it)
1812 const struct boardtype *this_board = comedi_board(dev);
1813 struct pci_dev *pcidev = NULL;
1814 int bus = it->options[0];
1815 int slot = it->options[1];
1817 for_each_pci_dev(pcidev) {
1818 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1820 if (pcidev->device != this_board->device_id)
1823 /* requested particular bus/slot */
1824 if (pcidev->bus->number != bus ||
1825 PCI_SLOT(pcidev->devfn) != slot)
1830 dev_err(dev->class_dev,
1831 "no supported board found! (req. bus/slot : %d/%d)\n",
1836 static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
1837 int master, int ext_mux, int softsshdelay,
1840 const struct boardtype *this_board = comedi_board(dev);
1841 struct pci9118_private *devpriv = dev->private;
1842 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1843 struct comedi_subdevice *s;
1847 dev->board_name = this_board->name;
1848 ret = comedi_pci_enable(dev);
1852 pci_set_master(pcidev);
1854 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1855 dev->iobase = pci_resource_start(pcidev, 2);
1859 if (master) { /* alloc DMA buffers */
1860 devpriv->dma_doublebuf = 0;
1861 for (i = 0; i < 2; i++) {
1862 for (pages = 4; pages >= 0; pages--) {
1863 devpriv->dmabuf_virt[i] =
1865 __get_free_pages(GFP_KERNEL, pages);
1866 if (devpriv->dmabuf_virt[i])
1869 if (devpriv->dmabuf_virt[i]) {
1870 devpriv->dmabuf_pages[i] = pages;
1871 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
1872 devpriv->dmabuf_hw[i] =
1873 virt_to_bus((void *)
1874 devpriv->dmabuf_virt[i]);
1877 if (!devpriv->dmabuf_virt[0]) {
1878 dev_warn(dev->class_dev,
1879 "Can't allocate DMA buffer, DMA disabled!\n");
1882 if (devpriv->dmabuf_virt[1])
1883 devpriv->dma_doublebuf = 1;
1885 devpriv->master = master;
1889 ext_mux = 256; /* max 256 channels! */
1890 if (softsshdelay > 0)
1893 devpriv->usemux = ext_mux;
1895 devpriv->usemux = 0;
1898 if (softsshdelay < 0) {
1899 /* select sample&hold signal polarity */
1900 devpriv->softsshdelay = -softsshdelay;
1901 devpriv->softsshsample = 0x80;
1902 devpriv->softsshhold = 0x00;
1904 devpriv->softsshdelay = softsshdelay;
1905 devpriv->softsshsample = 0x00;
1906 devpriv->softsshhold = 0x80;
1909 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
1910 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
1911 /* Enable parity check for parity error */
1913 if (!disable_irq && pcidev->irq) {
1914 ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
1915 dev->board_name, dev);
1917 dev->irq = pcidev->irq;
1920 ret = comedi_alloc_subdevices(dev, 4);
1924 s = &dev->subdevices[0];
1925 s->type = COMEDI_SUBD_AI;
1926 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1927 if (devpriv->usemux)
1928 s->n_chan = devpriv->usemux;
1930 s->n_chan = this_board->n_aichan;
1932 s->maxdata = this_board->ai_maxdata;
1933 s->range_table = this_board->rangelist_ai;
1934 s->insn_read = pci9118_insn_read_ai;
1936 dev->read_subdev = s;
1937 s->subdev_flags |= SDF_CMD_READ;
1938 s->len_chanlist = this_board->n_aichanlist;
1939 s->do_cmdtest = pci9118_ai_cmdtest;
1940 s->do_cmd = pci9118_ai_cmd;
1941 s->cancel = pci9118_ai_cancel;
1942 s->munge = pci9118_ai_munge;
1945 s = &dev->subdevices[1];
1946 s->type = COMEDI_SUBD_AO;
1947 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1948 s->n_chan = this_board->n_aochan;
1949 s->maxdata = this_board->ao_maxdata;
1950 s->len_chanlist = this_board->n_aochan;
1951 s->range_table = this_board->rangelist_ao;
1952 s->insn_write = pci9118_insn_write_ao;
1953 s->insn_read = pci9118_insn_read_ao;
1955 s = &dev->subdevices[2];
1956 s->type = COMEDI_SUBD_DI;
1957 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
1960 s->len_chanlist = 4;
1961 s->range_table = &range_digital;
1962 s->insn_bits = pci9118_insn_bits_di;
1964 s = &dev->subdevices[3];
1965 s->type = COMEDI_SUBD_DO;
1966 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1969 s->len_chanlist = 4;
1970 s->range_table = &range_digital;
1971 s->insn_bits = pci9118_insn_bits_do;
1973 devpriv->ai_maskharderr = 0x10a;
1974 /* default measure crash condition */
1975 if (hw_err_mask) /* disable some requested */
1976 devpriv->ai_maskharderr &= ~hw_err_mask;
1981 static int pci9118_attach(struct comedi_device *dev,
1982 struct comedi_devconfig *it)
1984 struct pci9118_private *devpriv;
1985 struct pci_dev *pcidev;
1986 int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;
1988 ext_mux = it->options[2];
1989 master = ((it->options[3] & 1) == 0);
1990 disable_irq = ((it->options[3] & 2) != 0);
1991 softsshdelay = it->options[4];
1992 hw_err_mask = it->options[5];
1994 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1998 pcidev = pci9118_find_pci(dev, it);
2001 comedi_set_hw_dev(dev, &pcidev->dev);
2003 return pci9118_common_attach(dev, disable_irq, master, ext_mux,
2004 softsshdelay, hw_err_mask);
2007 static int pci9118_auto_attach(struct comedi_device *dev,
2008 unsigned long context_unused)
2010 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2011 struct pci9118_private *devpriv;
2013 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2017 dev->board_ptr = pci9118_find_boardinfo(pcidev);
2018 if (dev->board_ptr == NULL) {
2019 dev_err(dev->class_dev,
2020 "adl_pci9118: cannot determine board type for pci %s\n",
2025 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
2026 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
2028 pci_dev_get(pcidev);
2029 /* Don't disable irq, use bus master, no external mux,
2030 * no sample-hold delay, no error mask. */
2031 return pci9118_common_attach(dev, 0, 1, 0, 0, 0);
2034 static void pci9118_detach(struct comedi_device *dev)
2036 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2037 struct pci9118_private *devpriv = dev->private;
2043 free_irq(dev->irq, dev);
2044 if (devpriv->dmabuf_virt[0])
2045 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2046 devpriv->dmabuf_pages[0]);
2047 if (devpriv->dmabuf_virt[1])
2048 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2049 devpriv->dmabuf_pages[1]);
2051 comedi_pci_disable(dev);
2053 pci_dev_put(pcidev);
2056 static struct comedi_driver adl_pci9118_driver = {
2057 .driver_name = "adl_pci9118",
2058 .module = THIS_MODULE,
2059 .attach = pci9118_attach,
2060 .auto_attach = pci9118_auto_attach,
2061 .detach = pci9118_detach,
2062 .num_names = ARRAY_SIZE(boardtypes),
2063 .board_name = &boardtypes[0].name,
2064 .offset = sizeof(struct boardtype),
2067 static int adl_pci9118_pci_probe(struct pci_dev *dev,
2068 const struct pci_device_id *id)
2070 return comedi_pci_auto_config(dev, &adl_pci9118_driver,
2074 static const struct pci_device_id adl_pci9118_pci_table[] = {
2075 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2078 MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2080 static struct pci_driver adl_pci9118_pci_driver = {
2081 .name = "adl_pci9118",
2082 .id_table = adl_pci9118_pci_table,
2083 .probe = adl_pci9118_pci_probe,
2084 .remove = comedi_pci_auto_unconfig,
2086 module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
2088 MODULE_AUTHOR("Comedi http://www.comedi.org");
2089 MODULE_DESCRIPTION("Comedi low-level driver");
2090 MODULE_LICENSE("GPL");