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>
14 * Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
15 * Author: Michal Dobes <dobes@tesnet.cz>
16 * Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
17 * PCI-9118HR (pci9118hr)
20 * This driver supports AI, AO, DI and DO subdevices.
21 * AI subdevice supports cmd and insn interface,
22 * other subdevices support only insn interface.
24 * - If cmd->scan_begin_src=TRIG_EXT then trigger input is TGIN (pin 46).
25 * - If cmd->convert_src=TRIG_EXT then trigger input is EXTTRG (pin 44).
26 * - If cmd->start_src/stop_src=TRIG_EXT then trigger input is TGIN (pin 46).
27 * - It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
28 * cmd.scan_end_arg modulo cmd.chanlist_len must by 0.
29 * - If return value of cmdtest is 5 then you've bad channel list
30 * (it isn't possible mixture S.E. and DIFF inputs or bipolar and unipolar
33 * There are some hardware limitations:
34 * a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
36 * b) DMA transfers must have the length aligned to two samples (32 bit),
37 * so there is some problems if cmd->chanlist_len is odd. This driver tries
38 * bypass this with adding one sample to the end of the every scan and discard
39 * it on output but this cann't be used if cmd->scan_begin_src=TRIG_FOLLOW
40 * and is used flag TRIG_WAKE_EOS, then driver switch to interrupt driven mode
41 * with interrupt after every sample.
42 * c) If isn't used DMA then you can use only mode where
43 * cmd->scan_begin_src=TRIG_FOLLOW.
45 * Configuration options:
46 * [0] - PCI bus of device (optional)
47 * [1] - PCI slot of device (optional)
48 * If bus/slot is not specified, then first available PCI
50 * [2] - 0= standard 8 DIFF/16 SE channels configuration
51 * n = external multiplexer connected, 1 <= n <= 256
52 * [3] - 0=autoselect DMA or EOC interrupts operation
53 * 1 = disable DMA mode
54 * 3 = disable DMA and INT, only insn interface will work
55 * [4] - sample&hold signal - card can generate signal for external S&H board
56 * 0 = use SSHO(pin 45) signal is generated in onboard hardware S&H logic
57 * 0 != use ADCHN7(pin 23) signal is generated from driver, number say how
58 * long delay is requested in ns and sign polarity of the hold
59 * (in this case external multiplexor can serve only 128 channels)
60 * [5] - 0=stop measure on all hardware errors
61 * 2 | = ignore ADOR - A/D Overrun status
62 * 8|=ignore Bover - A/D Burst Mode Overrun status
63 * 256|=ignore nFull - A/D FIFO Full status
70 * All the supported boards have the same PCI vendor and device IDs, so
71 * auto-attachment of PCI devices will always find the first board type.
73 * Perhaps the boards have different subdevice IDs that we could use to
76 * Need some device attributes so the board type can be corrected after
77 * attachment if necessary, and possibly to set other options supported by
81 #include <linux/module.h>
82 #include <linux/pci.h>
83 #include <linux/delay.h>
84 #include <linux/gfp.h>
85 #include <linux/interrupt.h>
88 #include "../comedidev.h"
90 #include "amcc_s5933.h"
92 #include "comedi_fc.h"
94 /* paranoid checks are broken */
95 #undef PCI9118_PARANOIDCHECK /*
96 * if defined, then is used code which control
97 * correct channel number on every 12 bit sample
100 #define IORANGE_9118 64 /* I hope */
101 #define PCI9118_CHANLEN 255 /*
102 * len of chanlist, some source say 256,
103 * but reality looks like 255 :-(
106 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
107 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
108 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
109 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
110 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
111 #define PCI9118_DA1 0x10 /* W: D/A registers */
112 #define PCI9118_DA2 0x14
113 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
114 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
115 #define PCI9118_DI 0x1c /* R: digi input register */
116 #define PCI9118_DO 0x1c /* W: digi output register */
117 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
118 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
119 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
120 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
121 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
122 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
123 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
124 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
126 /* bits from A/D control register (PCI9118_ADCNTRL) */
127 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
128 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
129 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
130 #define AdControl_ExtG 0x10 /*
131 * 1=8254 countrol controlled by TGIN(pin 46),
132 * 0=controlled by SoftG
134 #define AdControl_ExtM 0x08 /*
135 * 1=external hardware trigger (pin 44),
138 #define AdControl_TmrTr 0x04 /*
139 * 1=8254 is iternal trigger source,
140 * 0=software trigger is source
141 * (register PCI9118_SOFTTRG)
143 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
144 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
146 /* bits from A/D function register (PCI9118_ADFUNC) */
147 #define AdFunction_PDTrg 0x80 /*
149 * 0=negative digital trigger
150 * (only positive is correct)
152 #define AdFunction_PETrg 0x40 /*
154 * 0=negative external trigger
155 * (only positive is correct)
157 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
158 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
159 #define AdFunction_BS 0x08 /*
160 * 1=burst mode start,
163 #define AdFunction_PM 0x04 /*
164 * 1=post trigger mode,
167 #define AdFunction_AM 0x02 /*
168 * 1=about trigger mode,
169 * 0=not about trigger
171 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
173 /* bits from A/D status register (PCI9118_ADSTAT) */
174 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
175 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
176 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
177 #define AdStatus_Acmp 0x020 /* */
178 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
179 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
180 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
181 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
182 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
184 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
185 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
186 #define Int_Timer 0x08 /* timer interrupt */
187 #define Int_About 0x04 /* about trigger complete */
188 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
189 #define Int_DTrg 0x01 /* external digital trigger */
191 #define START_AI_EXT 0x01 /* start measure on external trigger */
192 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
193 #define START_AI_INT 0x04 /* start measure on internal trigger */
194 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
196 #define EXTTRG_AI 0 /* ext trg is used by AI */
198 static const struct comedi_lrange range_pci9118dg_hr = {
211 static const struct comedi_lrange range_pci9118hg = {
224 #define PCI9118_BIPOLAR_RANGES 4 /*
225 * used for test on mixture
230 const char *name; /* board name */
231 int device_id; /* PCI device ID of card */
232 int iorange_amcc; /* iorange for own S5933 region */
233 int iorange_9118; /* pass thru card region size */
234 int n_aichan; /* num of A/D chans */
235 int n_aichand; /* num of A/D chans in diff mode */
237 * num of A/D chans with
238 * external multiplexor
240 int n_aichanlist; /* len of chanlist */
241 int n_aochan; /* num of D/A chans */
242 int ai_maxdata; /* resolution of A/D */
243 int ao_maxdata; /* resolution of D/A */
244 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
245 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
246 unsigned int ai_ns_min; /* max sample speed of card v ns */
247 unsigned int ai_pacer_min; /*
248 * minimal pacer value
249 * (c1*c2 or c1 in burst)
251 int half_fifo_size; /* size of FIFO/2 */
255 static const struct boardtype boardtypes[] = {
259 .iorange_amcc = AMCC_OP_REG_SIZE,
260 .iorange_9118 = IORANGE_9118,
264 .n_aichanlist = PCI9118_CHANLEN,
266 .ai_maxdata = 0x0fff,
267 .ao_maxdata = 0x0fff,
268 .rangelist_ai = &range_pci9118dg_hr,
269 .rangelist_ao = &range_bipolar10,
272 .half_fifo_size = 512,
276 .iorange_amcc = AMCC_OP_REG_SIZE,
277 .iorange_9118 = IORANGE_9118,
281 .n_aichanlist = PCI9118_CHANLEN,
283 .ai_maxdata = 0x0fff,
284 .ao_maxdata = 0x0fff,
285 .rangelist_ai = &range_pci9118hg,
286 .rangelist_ao = &range_bipolar10,
289 .half_fifo_size = 512,
293 .iorange_amcc = AMCC_OP_REG_SIZE,
294 .iorange_9118 = IORANGE_9118,
298 .n_aichanlist = PCI9118_CHANLEN,
300 .ai_maxdata = 0xffff,
301 .ao_maxdata = 0x0fff,
302 .rangelist_ai = &range_pci9118dg_hr,
303 .rangelist_ao = &range_bipolar10,
306 .half_fifo_size = 512,
310 struct pci9118_private {
311 unsigned long iobase_a; /* base+size for AMCC chip */
312 unsigned int master; /* master capable */
313 unsigned int usemux; /* we want to use external multiplexor! */
314 #ifdef PCI9118_PARANOIDCHECK
315 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
319 unsigned char chanlistlen; /* number of scanlist */
321 unsigned char AdControlReg; /* A/D control register */
322 unsigned char IntControlReg; /* Interrupt control register */
323 unsigned char AdFunctionReg; /* A/D function register */
324 char ai_neverending; /* we do unlimited AI */
325 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
326 unsigned int ai_act_scan; /* how many scans we finished */
327 unsigned int ai_n_realscanlen; /*
328 * what we must transfer for one
329 * outgoing scan include front/back adds
331 unsigned int ai_act_dmapos; /* position in actual real stream */
332 unsigned int ai_add_front; /*
333 * how many channels we must add
334 * before scan to satisfy S&H?
336 unsigned int ai_add_back; /*
337 * how many channels we must add
338 * before scan to satisfy DMA?
340 unsigned int ai_flags;
341 char ai12_startstop; /*
342 * measure can start/stop
343 * on external trigger
345 unsigned int ai_divisor1, ai_divisor2; /*
346 * divisors for start of measure
349 unsigned short ao_data[2]; /* data output buffer */
350 char dma_doublebuf; /* use double buffering */
351 unsigned int dma_actbuf; /* which buffer is used now */
352 unsigned short *dmabuf_virt[2]; /*
353 * pointers to begin of
356 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
357 unsigned int dmabuf_size[2]; /*
358 * size of dma buffer in bytes
360 unsigned int dmabuf_use_size[2]; /*
361 * which size we may now use
364 unsigned int dmabuf_used_size[2]; /* which size was truly used */
365 unsigned int dmabuf_panic_size[2];
366 int dmabuf_pages[2]; /* number of pages in buffer */
367 unsigned char exttrg_users; /*
368 * bit field of external trigger
369 * users(0-AI, 1-AO, 2-DI, 3-DO)
371 unsigned char usedma; /* =1 use DMA transfer and not INT */
373 * >0 use software S&H,
374 * numer is requested delay in ns
376 unsigned char softsshsample; /*
377 * polarity of S&H signal
380 unsigned char softsshhold; /*
381 * polarity of S&H signal
384 unsigned int ai_maskerr; /* which warning was printed */
385 unsigned int ai_maskharderr; /* on which error bits stops */
388 static int check_channel_list(struct comedi_device *dev,
389 struct comedi_subdevice *s, int n_chan,
390 unsigned int *chanlist, int frontadd, int backadd)
392 const struct boardtype *this_board = comedi_board(dev);
393 struct pci9118_private *devpriv = dev->private;
394 unsigned int i, differencial = 0, bipolar = 0;
396 /* correct channel and range number check itself comedi/range.c */
398 dev_err(dev->class_dev, "range/channel list is empty!\n");
401 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
402 dev_err(dev->class_dev,
403 "range/channel list is too long for actual configuration!\n");
407 if (CR_AREF(chanlist[0]) == AREF_DIFF)
408 differencial = 1; /* all input must be diff */
409 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
410 bipolar = 1; /* all input must be bipolar */
412 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
413 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
415 dev_err(dev->class_dev,
416 "Differential and single ended inputs can't be mixed!\n");
419 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
421 dev_err(dev->class_dev,
422 "Bipolar and unipolar ranges can't be mixed!\n");
425 if (!devpriv->usemux && differencial &&
426 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
427 dev_err(dev->class_dev,
428 "AREF_DIFF is only available for the first 8 channels!\n");
436 static int setup_channel_list(struct comedi_device *dev,
437 struct comedi_subdevice *s, int n_chan,
438 unsigned int *chanlist, int rot, int frontadd,
439 int backadd, int usedma)
441 struct pci9118_private *devpriv = dev->private;
442 unsigned int i, differencial = 0, bipolar = 0;
443 unsigned int scanquad, gain, ssh = 0x00;
450 if (CR_AREF(chanlist[0]) == AREF_DIFF)
451 differencial = 1; /* all input must be diff */
452 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
453 bipolar = 1; /* all input must be bipolar */
455 /* All is ok, so we can setup channel/range list */
458 devpriv->AdControlReg |= AdControl_UniP;
461 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
466 devpriv->AdControlReg |= AdControl_Diff;
467 /* enable diff inputs */
469 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
470 /* set single ended inputs */
473 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
476 outl(2, dev->iobase + PCI9118_SCANMOD);
477 /* gods know why this sequence! */
478 outl(0, dev->iobase + PCI9118_SCANMOD);
479 outl(1, dev->iobase + PCI9118_SCANMOD);
481 #ifdef PCI9118_PARANOIDCHECK
482 devpriv->chanlistlen = n_chan;
483 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
484 devpriv->chanlist[i] = 0x55aa;
487 if (frontadd) { /* insert channels for S&H */
488 ssh = devpriv->softsshsample;
489 for (i = 0; i < frontadd; i++) {
490 /* store range list to card */
491 scanquad = CR_CHAN(chanlist[0]);
492 /* get channel number; */
493 gain = CR_RANGE(chanlist[0]);
494 /* get gain number */
495 scanquad |= ((gain & 0x03) << 8);
496 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
497 ssh = devpriv->softsshhold;
501 for (i = 0; i < n_chan; i++) { /* store range list to card */
502 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
503 #ifdef PCI9118_PARANOIDCHECK
504 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
506 gain = CR_RANGE(chanlist[i]); /* get gain number */
507 scanquad |= ((gain & 0x03) << 8);
508 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
511 if (backadd) { /* insert channels for fit onto 32bit DMA */
512 for (i = 0; i < backadd; i++) { /* store range list to card */
513 scanquad = CR_CHAN(chanlist[0]);
514 /* get channel number */
515 gain = CR_RANGE(chanlist[0]); /* get gain number */
516 scanquad |= ((gain & 0x03) << 8);
517 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
520 #ifdef PCI9118_PARANOIDCHECK
521 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
522 /* for 32bit operations */
524 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
525 /* udelay(100); important delay, or first sample will be crippled */
527 return 1; /* we can serve this with scan logic */
530 static int pci9118_ai_eoc(struct comedi_device *dev,
531 struct comedi_subdevice *s,
532 struct comedi_insn *insn,
533 unsigned long context)
537 status = inl(dev->iobase + PCI9118_ADSTAT);
538 if (status & AdStatus_ADrdy)
543 static int pci9118_insn_read_ai(struct comedi_device *dev,
544 struct comedi_subdevice *s,
545 struct comedi_insn *insn, unsigned int *data)
547 struct pci9118_private *devpriv = dev->private;
551 devpriv->AdControlReg = AdControl_Int & 0xff;
552 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
553 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
555 * positive triggers, no S&H,
556 * no burst, burst stop,
562 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0))
565 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
567 for (n = 0; n < insn->n; n++) {
568 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
571 ret = comedi_timeout(dev, s, insn, pci9118_ai_eoc, 0);
573 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
577 if (s->maxdata == 0xffff) {
580 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
583 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
587 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
592 static int pci9118_insn_write_ao(struct comedi_device *dev,
593 struct comedi_subdevice *s,
594 struct comedi_insn *insn, unsigned int *data)
596 struct pci9118_private *devpriv = dev->private;
599 ch = CR_CHAN(insn->chanspec);
601 chanreg = PCI9118_DA2;
603 chanreg = PCI9118_DA1;
606 for (n = 0; n < insn->n; n++) {
607 outl(data[n], dev->iobase + chanreg);
608 devpriv->ao_data[ch] = data[n];
614 static int pci9118_insn_read_ao(struct comedi_device *dev,
615 struct comedi_subdevice *s,
616 struct comedi_insn *insn, unsigned int *data)
618 struct pci9118_private *devpriv = dev->private;
621 chan = CR_CHAN(insn->chanspec);
622 for (n = 0; n < insn->n; n++)
623 data[n] = devpriv->ao_data[chan];
628 static int pci9118_insn_bits_di(struct comedi_device *dev,
629 struct comedi_subdevice *s,
630 struct comedi_insn *insn, unsigned int *data)
632 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
637 static int pci9118_insn_bits_do(struct comedi_device *dev,
638 struct comedi_subdevice *s,
639 struct comedi_insn *insn,
642 if (comedi_dio_update_state(s, data))
643 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
650 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
652 struct pci9118_private *devpriv = dev->private;
654 devpriv->AdFunctionReg =
655 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
656 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
657 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
658 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
659 dev->iobase + PCI9118_CNT0);
660 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
661 dev->iobase + PCI9118_CNT0);
662 devpriv->AdFunctionReg |= AdFunction_Start;
663 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
666 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
667 struct comedi_subdevice *s,
668 unsigned short *dma_buffer,
669 unsigned int num_samples)
671 struct pci9118_private *devpriv = dev->private;
672 struct comedi_cmd *cmd = &s->async->cmd;
673 unsigned int i = 0, j = 0;
674 unsigned int start_pos = devpriv->ai_add_front,
675 stop_pos = devpriv->ai_add_front + cmd->chanlist_len;
676 unsigned int raw_scanlen = devpriv->ai_add_front + cmd->chanlist_len +
677 devpriv->ai_add_back;
679 for (i = 0; i < num_samples; i++) {
680 if (devpriv->ai_act_dmapos >= start_pos &&
681 devpriv->ai_act_dmapos < stop_pos) {
682 dma_buffer[j++] = dma_buffer[i];
684 devpriv->ai_act_dmapos++;
685 devpriv->ai_act_dmapos %= raw_scanlen;
691 static int move_block_from_dma(struct comedi_device *dev,
692 struct comedi_subdevice *s,
693 unsigned short *dma_buffer,
694 unsigned int num_samples)
696 struct pci9118_private *devpriv = dev->private;
697 struct comedi_cmd *cmd = &s->async->cmd;
698 unsigned int num_bytes;
700 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
701 devpriv->ai_act_scan +=
702 (s->async->cur_chan + num_samples) / cmd->scan_end_arg;
703 s->async->cur_chan += num_samples;
704 s->async->cur_chan %= cmd->scan_end_arg;
706 cfc_write_array_to_buffer(s, dma_buffer,
707 num_samples * sizeof(short));
708 if (num_bytes < num_samples * sizeof(short))
713 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
715 struct pci9118_private *devpriv = dev->private;
718 return -1; /* incorrect source */
719 devpriv->exttrg_users |= (1 << source);
720 devpriv->IntControlReg |= Int_DTrg;
721 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
722 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
723 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
724 /* allow INT in AMCC */
728 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
730 struct pci9118_private *devpriv = dev->private;
733 return -1; /* incorrect source */
734 devpriv->exttrg_users &= ~(1 << source);
735 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
736 devpriv->IntControlReg &= ~Int_DTrg;
737 if (!devpriv->IntControlReg) /* all IRQ disabled */
738 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
740 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
741 /* disable int in AMCC */
742 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
747 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
748 struct comedi_subdevice *s,
749 unsigned int *tim1, unsigned int *tim2,
750 unsigned int flags, int chans,
751 unsigned int *div1, unsigned int *div2,
752 unsigned int chnsshfront)
754 const struct boardtype *this_board = comedi_board(dev);
755 struct comedi_cmd *cmd = &s->async->cmd;
760 if (*tim2 < this_board->ai_ns_min)
761 *tim2 = this_board->ai_ns_min;
762 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
764 tim2, flags & TRIG_ROUND_NEAREST);
767 if (*tim2 < this_board->ai_ns_min)
768 *tim2 = this_board->ai_ns_min;
769 *div1 = *tim2 / I8254_OSC_BASE_4MHZ;
770 /* convert timer (burst) */
771 if (*div1 < this_board->ai_pacer_min)
772 *div1 = this_board->ai_pacer_min;
773 *div2 = *tim1 / I8254_OSC_BASE_4MHZ; /* scan timer */
774 *div2 = *div2 / *div1; /* major timer is c1*c2 */
778 *tim2 = *div1 * I8254_OSC_BASE_4MHZ; /* real convert timer */
780 if (cmd->convert_src == TRIG_NOW && !chnsshfront) {
781 /* use BSSH signal */
782 if (*div2 < (chans + 2))
786 *tim1 = *div1 * *div2 * I8254_OSC_BASE_4MHZ;
791 static void pci9118_start_pacer(struct comedi_device *dev, int mode)
793 struct pci9118_private *devpriv = dev->private;
794 unsigned int divisor1 = devpriv->ai_divisor1;
795 unsigned int divisor2 = devpriv->ai_divisor2;
797 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
798 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
799 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
802 if ((mode == 1) || (mode == 2) || (mode == 4)) {
803 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
804 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
805 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
806 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
810 static int pci9118_ai_cancel(struct comedi_device *dev,
811 struct comedi_subdevice *s)
813 struct pci9118_private *devpriv = dev->private;
816 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
818 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
819 pci9118_exttrg_del(dev, EXTTRG_AI);
820 pci9118_start_pacer(dev, 0); /* stop 8254 counters */
821 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
822 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
824 * positive triggers, no S&H, no burst,
825 * burst stop, no post trigger,
826 * no about trigger, trigger stop
828 devpriv->AdControlReg = 0x00;
829 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
831 * bipolar, S.E., use 8254, stop 8354,
832 * internal trigger, soft trigger,
833 * disable INT and DMA
835 outl(0, dev->iobase + PCI9118_BURST);
836 outl(1, dev->iobase + PCI9118_SCANMOD);
837 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
838 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
843 devpriv->ai_act_scan = 0;
844 devpriv->ai_act_dmapos = 0;
845 s->async->cur_chan = 0;
846 s->async->inttrig = NULL;
847 devpriv->ai_neverending = 0;
848 devpriv->dma_actbuf = 0;
850 if (!devpriv->IntControlReg)
851 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
852 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
853 /* allow INT in AMCC */
858 static char pci9118_decode_error_status(struct comedi_device *dev,
859 struct comedi_subdevice *s,
862 struct pci9118_private *devpriv = dev->private;
865 dev_err(dev->class_dev,
866 "A/D FIFO Full status (Fatal Error!)\n");
867 devpriv->ai_maskerr &= ~0x100L;
870 dev_err(dev->class_dev,
871 "A/D Burst Mode Overrun Status (Fatal Error!)\n");
872 devpriv->ai_maskerr &= ~0x008L;
875 dev_err(dev->class_dev, "A/D Over Speed Status (Warning!)\n");
876 devpriv->ai_maskerr &= ~0x004L;
879 dev_err(dev->class_dev, "A/D Overrun Status (Fatal Error!)\n");
880 devpriv->ai_maskerr &= ~0x002L;
882 if (m & devpriv->ai_maskharderr) {
883 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
884 cfc_handle_events(dev, s);
891 static void pci9118_ai_munge(struct comedi_device *dev,
892 struct comedi_subdevice *s, void *data,
893 unsigned int num_bytes,
894 unsigned int start_chan_index)
896 struct pci9118_private *devpriv = dev->private;
897 unsigned int i, num_samples = num_bytes / sizeof(short);
898 unsigned short *array = data;
900 for (i = 0; i < num_samples; i++) {
902 array[i] = be16_to_cpu(array[i]);
903 if (s->maxdata == 0xffff)
906 array[i] = (array[i] >> 4) & 0x0fff;
911 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
912 struct comedi_subdevice *s,
913 unsigned short int_adstat,
914 unsigned int int_amcc,
915 unsigned short int_daq)
917 struct pci9118_private *devpriv = dev->private;
918 struct comedi_cmd *cmd = &s->async->cmd;
919 unsigned short sampl;
921 if (int_adstat & devpriv->ai_maskerr)
922 if (pci9118_decode_error_status(dev, s, int_adstat))
925 sampl = inw(dev->iobase + PCI9118_AD_DATA);
927 #ifdef PCI9118_PARANOIDCHECK
928 if (s->maxdata != 0xffff) {
929 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
931 dev_info(dev->class_dev,
932 "A/D SAMPL - data dropout: received channel %d, expected %d!\n",
934 devpriv->chanlist[s->async->cur_chan]);
935 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
936 cfc_handle_events(dev, s);
941 cfc_write_to_buffer(s, sampl);
942 s->async->cur_chan++;
943 if (s->async->cur_chan >= cmd->scan_end_arg) {
945 s->async->cur_chan %= cmd->scan_end_arg;
946 devpriv->ai_act_scan++;
947 if (!devpriv->ai_neverending) {
948 /* all data sampled? */
949 if (devpriv->ai_act_scan >= cmd->stop_arg)
950 s->async->events |= COMEDI_CB_EOA;
954 cfc_handle_events(dev, s);
957 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
958 struct comedi_subdevice *s,
959 unsigned short int_adstat,
960 unsigned int int_amcc,
961 unsigned short int_daq)
963 struct pci9118_private *devpriv = dev->private;
964 struct comedi_cmd *cmd = &s->async->cmd;
965 unsigned int next_dma_buf, samplesinbuf, sampls, m;
967 if (int_amcc & MASTER_ABORT_INT) {
968 dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
969 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
970 cfc_handle_events(dev, s);
974 if (int_amcc & TARGET_ABORT_INT) {
975 dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
976 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
977 cfc_handle_events(dev, s);
980 if (int_adstat & devpriv->ai_maskerr)
981 /* if (int_adstat & 0x106) */
982 if (pci9118_decode_error_status(dev, s, int_adstat))
985 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
986 /* number of received real samples */
988 if (devpriv->dma_doublebuf) { /*
989 * switch DMA buffers if is used
992 next_dma_buf = 1 - devpriv->dma_actbuf;
993 outl(devpriv->dmabuf_hw[next_dma_buf],
994 devpriv->iobase_a + AMCC_OP_REG_MWAR);
995 outl(devpriv->dmabuf_use_size[next_dma_buf],
996 devpriv->iobase_a + AMCC_OP_REG_MWTC);
997 devpriv->dmabuf_used_size[next_dma_buf] =
998 devpriv->dmabuf_use_size[next_dma_buf];
999 if (devpriv->ai_do == 4)
1000 interrupt_pci9118_ai_mode4_switch(dev);
1004 /* how many samples is to end of buffer */
1005 m = s->async->prealloc_bufsz >> 1;
1007 move_block_from_dma(dev, s,
1008 devpriv->dmabuf_virt[devpriv->dma_actbuf],
1010 m = m - sampls; /* m=how many samples was transferred */
1013 if (!devpriv->ai_neverending) {
1014 /* all data sampled? */
1015 if (devpriv->ai_act_scan >= cmd->stop_arg)
1016 s->async->events |= COMEDI_CB_EOA;
1019 if (devpriv->dma_doublebuf) { /* switch dma buffers */
1020 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
1021 } else { /* restart DMA if is not used double buffering */
1022 outl(devpriv->dmabuf_hw[0],
1023 devpriv->iobase_a + AMCC_OP_REG_MWAR);
1024 outl(devpriv->dmabuf_use_size[0],
1025 devpriv->iobase_a + AMCC_OP_REG_MWTC);
1026 if (devpriv->ai_do == 4)
1027 interrupt_pci9118_ai_mode4_switch(dev);
1030 cfc_handle_events(dev, s);
1033 static irqreturn_t pci9118_interrupt(int irq, void *d)
1035 struct comedi_device *dev = d;
1036 struct comedi_subdevice *s = dev->read_subdev;
1037 struct pci9118_private *devpriv = dev->private;
1038 unsigned int intsrc; /* IRQ reasons from card */
1039 unsigned int intcsr; /* INT register from AMCC chip */
1040 unsigned int adstat; /* STATUS register */
1045 intsrc = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
1046 intcsr = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1048 if (!intsrc && !(intcsr & ANY_S593X_INT))
1051 outl(intcsr | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1053 adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
1055 if (!devpriv->ai_do)
1058 if (devpriv->ai12_startstop) {
1059 if ((adstat & AdStatus_DTH) && (intsrc & Int_DTrg)) {
1060 /* start/stop of measure */
1061 if (devpriv->ai12_startstop & START_AI_EXT) {
1062 /* deactivate EXT trigger */
1063 devpriv->ai12_startstop &= ~START_AI_EXT;
1064 if (!(devpriv->ai12_startstop & STOP_AI_EXT))
1065 pci9118_exttrg_del(dev, EXTTRG_AI);
1068 pci9118_start_pacer(dev, devpriv->ai_do);
1069 outl(devpriv->AdControlReg,
1070 dev->iobase + PCI9118_ADCNTRL);
1071 } else if (devpriv->ai12_startstop & STOP_AI_EXT) {
1072 /* deactivate EXT trigger */
1073 devpriv->ai12_startstop &= ~STOP_AI_EXT;
1074 pci9118_exttrg_del(dev, EXTTRG_AI);
1076 /* on next interrupt measure will stop */
1077 devpriv->ai_neverending = 0;
1082 if (devpriv->usedma)
1083 interrupt_pci9118_ai_dma(dev, s, adstat, intcsr, intsrc);
1085 interrupt_pci9118_ai_onesample(dev, s, adstat, intcsr, intsrc);
1090 static int pci9118_ai_inttrig(struct comedi_device *dev,
1091 struct comedi_subdevice *s,
1092 unsigned int trig_num)
1094 struct pci9118_private *devpriv = dev->private;
1095 struct comedi_cmd *cmd = &s->async->cmd;
1097 if (trig_num != cmd->start_arg)
1100 devpriv->ai12_startstop &= ~START_AI_INT;
1101 s->async->inttrig = NULL;
1103 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1104 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1105 if (devpriv->ai_do != 3) {
1106 pci9118_start_pacer(dev, devpriv->ai_do);
1107 devpriv->AdControlReg |= AdControl_SoftG;
1109 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1114 static int pci9118_ai_cmdtest(struct comedi_device *dev,
1115 struct comedi_subdevice *s,
1116 struct comedi_cmd *cmd)
1118 const struct boardtype *this_board = comedi_board(dev);
1119 struct pci9118_private *devpriv = dev->private;
1123 unsigned int divisor1 = 0, divisor2 = 0;
1125 /* Step 1 : check if triggers are trivially valid */
1127 err |= cfc_check_trigger_src(&cmd->start_src,
1128 TRIG_NOW | TRIG_EXT | TRIG_INT);
1130 flags = TRIG_FOLLOW;
1131 if (devpriv->master)
1132 flags |= TRIG_TIMER | TRIG_EXT;
1133 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1135 flags = TRIG_TIMER | TRIG_EXT;
1136 if (devpriv->master)
1138 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
1140 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1141 err |= cfc_check_trigger_src(&cmd->stop_src,
1142 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1147 /* Step 2a : make sure trigger sources are unique */
1149 err |= cfc_check_trigger_is_unique(cmd->start_src);
1150 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1151 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1152 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1154 /* Step 2b : and mutually compatible */
1156 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1159 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
1162 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1163 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1166 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1167 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1170 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1176 /* Step 3: check if arguments are trivially valid */
1178 switch (cmd->start_src) {
1181 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1184 /* start_arg is the internal trigger (any value) */
1188 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1189 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1191 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1192 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1193 cmd->scan_begin_src = TRIG_FOLLOW;
1194 cmd->convert_arg = cmd->scan_begin_arg;
1195 cmd->scan_begin_arg = 0;
1198 if (cmd->scan_begin_src == TRIG_TIMER)
1199 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1200 this_board->ai_ns_min);
1202 if (cmd->scan_begin_src == TRIG_EXT)
1203 if (cmd->scan_begin_arg) {
1204 cmd->scan_begin_arg = 0;
1206 err |= cfc_check_trigger_arg_max(&cmd->scan_end_arg,
1210 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1211 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1212 this_board->ai_ns_min);
1214 if (cmd->convert_src == TRIG_EXT)
1215 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1217 if (cmd->stop_src == TRIG_COUNT)
1218 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1219 else /* TRIG_NONE */
1220 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1222 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
1224 err |= cfc_check_trigger_arg_min(&cmd->scan_end_arg,
1227 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1229 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1236 /* step 4: fix up any arguments */
1238 if (cmd->scan_begin_src == TRIG_TIMER) {
1239 arg = cmd->scan_begin_arg;
1240 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
1241 &divisor1, &divisor2,
1243 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
1246 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1247 arg = cmd->convert_arg;
1248 i8253_cascade_ns_to_timer(I8254_OSC_BASE_4MHZ,
1249 &divisor1, &divisor2,
1251 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, arg);
1253 if (cmd->scan_begin_src == TRIG_TIMER &&
1254 cmd->convert_src == TRIG_NOW) {
1255 if (cmd->convert_arg == 0) {
1256 arg = this_board->ai_ns_min *
1257 (cmd->scan_end_arg + 2);
1259 arg = cmd->convert_arg * cmd->chanlist_len;
1261 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
1270 if (!check_channel_list(dev, s, cmd->chanlist_len,
1271 cmd->chanlist, 0, 0))
1272 return 5; /* incorrect channels list */
1277 static int Compute_and_setup_dma(struct comedi_device *dev,
1278 struct comedi_subdevice *s)
1280 struct pci9118_private *devpriv = dev->private;
1281 struct comedi_cmd *cmd = &s->async->cmd;
1282 unsigned int dmalen0, dmalen1, i;
1284 dmalen0 = devpriv->dmabuf_size[0];
1285 dmalen1 = devpriv->dmabuf_size[1];
1286 /* isn't output buff smaller that our DMA buff? */
1287 if (dmalen0 > s->async->prealloc_bufsz) {
1288 /* align to 32bit down */
1289 dmalen0 = s->async->prealloc_bufsz & ~3L;
1291 if (dmalen1 > s->async->prealloc_bufsz) {
1292 /* align to 32bit down */
1293 dmalen1 = s->async->prealloc_bufsz & ~3L;
1296 /* we want wake up every scan? */
1297 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1298 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1299 /* uff, too short DMA buffer, disable EOS support! */
1300 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1301 dev_info(dev->class_dev,
1302 "WAR: DMA0 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1303 dmalen0, devpriv->ai_n_realscanlen << 1);
1305 /* short first DMA buffer to one scan */
1306 dmalen0 = devpriv->ai_n_realscanlen << 1;
1308 dev_info(dev->class_dev,
1309 "ERR: DMA0 buf len bug? (%d<4)\n",
1315 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1316 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1317 /* uff, too short DMA buffer, disable EOS support! */
1318 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1319 dev_info(dev->class_dev,
1320 "WAR: DMA1 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1321 dmalen1, devpriv->ai_n_realscanlen << 1);
1323 /* short second DMA buffer to one scan */
1324 dmalen1 = devpriv->ai_n_realscanlen << 1;
1326 dev_info(dev->class_dev,
1327 "ERR: DMA1 buf len bug? (%d<4)\n",
1334 /* transfer without TRIG_WAKE_EOS */
1335 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1336 /* if it's possible then align DMA buffers to length of scan */
1339 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1340 (devpriv->ai_n_realscanlen << 1);
1343 dmalen0 = i; /* uff. very long scan? */
1346 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1347 (devpriv->ai_n_realscanlen << 1);
1350 dmalen1 = i; /* uff. very long scan? */
1352 * if measure isn't neverending then test, if it fits whole
1353 * into one or two DMA buffers
1355 if (!devpriv->ai_neverending) {
1356 /* fits whole measure into one DMA buffer? */
1358 ((devpriv->ai_n_realscanlen << 1) *
1361 (devpriv->ai_n_realscanlen << 1) *
1365 * fits whole measure into
1369 ((devpriv->ai_n_realscanlen << 1) *
1370 cmd->stop_arg - dmalen0))
1372 (devpriv->ai_n_realscanlen << 1) *
1373 cmd->stop_arg - dmalen0;
1379 /* these DMA buffer size will be used */
1380 devpriv->dma_actbuf = 0;
1381 devpriv->dmabuf_use_size[0] = dmalen0;
1382 devpriv->dmabuf_use_size[1] = dmalen1;
1385 if (cmd->scan_end_arg < this_board->half_fifo_size) {
1386 devpriv->dmabuf_panic_size[0] =
1387 (this_board->half_fifo_size / cmd->scan_end_arg +
1388 1) * cmd->scan_end_arg * sizeof(short);
1389 devpriv->dmabuf_panic_size[1] =
1390 (this_board->half_fifo_size / cmd->scan_end_arg +
1391 1) * cmd->scan_end_arg * sizeof(short);
1393 devpriv->dmabuf_panic_size[0] =
1394 (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[0];
1395 devpriv->dmabuf_panic_size[1] =
1396 (cmd->scan_end_arg << 1) % devpriv->dmabuf_size[1];
1400 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1401 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1402 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1403 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1404 /* init DMA transfer */
1405 outl(0x00000000 | AINT_WRITE_COMPL,
1406 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1407 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1409 outl(inl(devpriv->iobase_a +
1410 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1411 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1412 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1413 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1414 /* allow bus mastering */
1419 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1420 struct comedi_subdevice *s)
1422 struct pci9118_private *devpriv = dev->private;
1424 switch (devpriv->ai_do) {
1426 devpriv->AdControlReg |= AdControl_TmrTr;
1429 dev_err(dev->class_dev, "%s mode 2 bug!\n", __func__);
1432 devpriv->AdControlReg |= AdControl_ExtM;
1435 dev_err(dev->class_dev, "%s mode 4 bug!\n", __func__);
1438 dev_err(dev->class_dev, "%s mode number bug!\n", __func__);
1442 if (devpriv->ai12_startstop)
1443 pci9118_exttrg_add(dev, EXTTRG_AI);
1444 /* activate EXT trigger */
1446 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1447 devpriv->IntControlReg |= Int_Timer;
1449 devpriv->AdControlReg |= AdControl_Int;
1451 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1452 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1453 /* allow INT in AMCC */
1455 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1456 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1457 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1458 if (devpriv->ai_do != 3) {
1459 pci9118_start_pacer(dev, devpriv->ai_do);
1460 devpriv->AdControlReg |= AdControl_SoftG;
1462 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1468 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1469 struct comedi_subdevice *s)
1471 struct pci9118_private *devpriv = dev->private;
1472 struct comedi_cmd *cmd = &s->async->cmd;
1474 Compute_and_setup_dma(dev, s);
1476 switch (devpriv->ai_do) {
1478 devpriv->AdControlReg |=
1479 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1482 devpriv->AdControlReg |=
1483 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1484 devpriv->AdFunctionReg =
1485 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1487 if (cmd->convert_src == TRIG_NOW && !devpriv->softsshdelay)
1488 devpriv->AdFunctionReg |= AdFunction_BSSH;
1489 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1492 devpriv->AdControlReg |=
1493 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1494 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1497 devpriv->AdControlReg |=
1498 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1499 devpriv->AdFunctionReg =
1500 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1501 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1502 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1503 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1504 dev->iobase + PCI9118_CNT0);
1505 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1506 dev->iobase + PCI9118_CNT0);
1507 devpriv->AdFunctionReg |= AdFunction_Start;
1510 dev_err(dev->class_dev, "%s mode number bug!\n", __func__);
1514 if (devpriv->ai12_startstop) {
1515 pci9118_exttrg_add(dev, EXTTRG_AI);
1516 /* activate EXT trigger */
1519 outl(0x02000000 | AINT_WRITE_COMPL,
1520 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1522 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1523 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1524 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1525 if (devpriv->ai_do != 3) {
1526 pci9118_start_pacer(dev, devpriv->ai_do);
1527 devpriv->AdControlReg |= AdControl_SoftG;
1529 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1535 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1537 const struct boardtype *this_board = comedi_board(dev);
1538 struct pci9118_private *devpriv = dev->private;
1539 struct comedi_cmd *cmd = &s->async->cmd;
1540 unsigned int addchans = 0;
1543 devpriv->ai12_startstop = 0;
1544 devpriv->ai_flags = cmd->flags;
1545 devpriv->ai_add_front = 0;
1546 devpriv->ai_add_back = 0;
1547 devpriv->ai_maskerr = 0x10e;
1549 /* prepare for start/stop conditions */
1550 if (cmd->start_src == TRIG_EXT)
1551 devpriv->ai12_startstop |= START_AI_EXT;
1552 if (cmd->stop_src == TRIG_EXT) {
1553 devpriv->ai_neverending = 1;
1554 devpriv->ai12_startstop |= STOP_AI_EXT;
1556 if (cmd->start_src == TRIG_INT) {
1557 devpriv->ai12_startstop |= START_AI_INT;
1558 s->async->inttrig = pci9118_ai_inttrig;
1560 if (cmd->stop_src == TRIG_NONE)
1561 devpriv->ai_neverending = 1;
1562 if (cmd->stop_src == TRIG_COUNT)
1563 devpriv->ai_neverending = 0;
1566 * use additional sample at end of every scan
1567 * to satisty DMA 32 bit transfer?
1569 devpriv->ai_add_front = 0;
1570 devpriv->ai_add_back = 0;
1571 if (devpriv->master) {
1572 devpriv->usedma = 1;
1573 if ((cmd->flags & TRIG_WAKE_EOS) &&
1574 (cmd->scan_end_arg == 1)) {
1575 if (cmd->convert_src == TRIG_NOW)
1576 devpriv->ai_add_back = 1;
1577 if (cmd->convert_src == TRIG_TIMER) {
1578 devpriv->usedma = 0;
1580 * use INT transfer if scanlist
1581 * have only one channel
1585 if ((cmd->flags & TRIG_WAKE_EOS) &&
1586 (cmd->scan_end_arg & 1) &&
1587 (cmd->scan_end_arg > 1)) {
1588 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1589 devpriv->usedma = 0;
1591 * XXX maybe can be corrected to use 16 bit DMA
1594 * well, we must insert one sample
1595 * to end of EOS to meet 32 bit transfer
1597 devpriv->ai_add_back = 1;
1600 } else { /* interrupt transfer don't need any correction */
1601 devpriv->usedma = 0;
1605 * we need software S&H signal?
1606 * It adds two samples before every scan as minimum
1608 if (cmd->convert_src == TRIG_NOW && devpriv->softsshdelay) {
1609 devpriv->ai_add_front = 2;
1610 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1611 /* move it to front */
1612 devpriv->ai_add_front++;
1613 devpriv->ai_add_back = 0;
1615 if (cmd->convert_arg < this_board->ai_ns_min)
1616 cmd->convert_arg = this_board->ai_ns_min;
1617 addchans = devpriv->softsshdelay / cmd->convert_arg;
1618 if (devpriv->softsshdelay % cmd->convert_arg)
1620 if (addchans > (devpriv->ai_add_front - 1)) {
1621 /* uff, still short */
1622 devpriv->ai_add_front = addchans + 1;
1623 if (devpriv->usedma == 1)
1624 if ((devpriv->ai_add_front +
1626 devpriv->ai_add_back) & 1)
1627 devpriv->ai_add_front++;
1628 /* round up to 32 bit */
1631 /* well, we now know what must be all added */
1632 devpriv->ai_n_realscanlen = /*
1633 * what we must take from card in real
1634 * to have cmd->scan_end_arg on output?
1636 (devpriv->ai_add_front + cmd->chanlist_len +
1637 devpriv->ai_add_back) * (cmd->scan_end_arg /
1640 /* check and setup channel list */
1641 if (!check_channel_list(dev, s, cmd->chanlist_len,
1642 cmd->chanlist, devpriv->ai_add_front,
1643 devpriv->ai_add_back))
1645 if (!setup_channel_list(dev, s, cmd->chanlist_len,
1646 cmd->chanlist, 0, devpriv->ai_add_front,
1647 devpriv->ai_add_back, devpriv->usedma))
1650 /* compute timers settings */
1652 * simplest way, fr=4Mhz/(tim1*tim2),
1653 * channel manipulation without timers effect
1655 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1656 (cmd->scan_begin_src == TRIG_EXT) ||
1657 (cmd->scan_begin_src == TRIG_INT)) &&
1658 (cmd->convert_src == TRIG_TIMER)) {
1659 /* both timer is used for one time */
1660 if (cmd->scan_begin_src == TRIG_EXT)
1664 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1665 &cmd->scan_begin_arg, &cmd->convert_arg,
1667 devpriv->ai_n_realscanlen,
1668 &devpriv->ai_divisor1,
1669 &devpriv->ai_divisor2,
1670 devpriv->ai_add_front);
1673 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1674 ((cmd->convert_src == TRIG_TIMER) ||
1675 (cmd->convert_src == TRIG_NOW))) {
1676 /* double timed action */
1677 if (!devpriv->usedma) {
1678 dev_err(dev->class_dev,
1679 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!\n");
1684 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1685 &cmd->scan_begin_arg, &cmd->convert_arg,
1687 devpriv->ai_n_realscanlen,
1688 &devpriv->ai_divisor1,
1689 &devpriv->ai_divisor2,
1690 devpriv->ai_add_front);
1693 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1694 && (cmd->convert_src == TRIG_EXT)) {
1698 pci9118_start_pacer(dev, -1); /* stop pacer */
1700 devpriv->AdControlReg = 0; /*
1701 * bipolar, S.E., use 8254, stop 8354,
1702 * internal trigger, soft trigger,
1705 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1706 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1708 * positive triggers, no S&H, no burst,
1709 * burst stop, no post trigger,
1710 * no about trigger, trigger stop
1712 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1714 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1715 inl(dev->iobase + PCI9118_ADSTAT); /*
1719 inl(dev->iobase + PCI9118_INTSRC);
1721 devpriv->ai_act_scan = 0;
1722 devpriv->ai_act_dmapos = 0;
1723 s->async->cur_chan = 0;
1725 if (devpriv->usedma)
1726 ret = pci9118_ai_docmd_dma(dev, s);
1728 ret = pci9118_ai_docmd_sampl(dev, s);
1733 static int pci9118_reset(struct comedi_device *dev)
1735 struct pci9118_private *devpriv = dev->private;
1737 devpriv->IntControlReg = 0;
1738 devpriv->exttrg_users = 0;
1739 inl(dev->iobase + PCI9118_INTCTRL);
1740 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1741 /* disable interrupts source */
1742 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1743 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1744 pci9118_start_pacer(dev, 0); /* stop 8254 counters */
1745 devpriv->AdControlReg = 0;
1746 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1748 * bipolar, S.E., use 8254,
1749 * stop 8354, internal trigger,
1751 * disable INT and DMA
1753 outl(0, dev->iobase + PCI9118_BURST);
1754 outl(1, dev->iobase + PCI9118_SCANMOD);
1755 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1756 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1757 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1759 * positive triggers, no S&H,
1760 * no burst, burst stop,
1766 devpriv->ao_data[0] = 2047;
1767 devpriv->ao_data[1] = 2047;
1768 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
1769 /* reset A/D outs to 0V */
1770 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1771 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
1773 inl(dev->iobase + PCI9118_AD_DATA);
1774 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1775 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1776 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1777 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
1778 devpriv->AdControlReg = 0;
1779 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1781 * bipolar, S.E., use 8254,
1782 * stop 8354, internal trigger,
1784 * disable INT and DMA
1787 devpriv->exttrg_users = 0;
1793 * FIXME - this is pretty ineffective because all the supported board types
1794 * have the same device ID!
1796 static const struct boardtype *pci9118_find_boardinfo(struct pci_dev *pcidev)
1800 for (i = 0; i < ARRAY_SIZE(boardtypes); i++)
1801 if (pcidev->device == boardtypes[i].device_id)
1802 return &boardtypes[i];
1806 static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1807 struct comedi_devconfig *it)
1809 const struct boardtype *this_board = comedi_board(dev);
1810 struct pci_dev *pcidev = NULL;
1811 int bus = it->options[0];
1812 int slot = it->options[1];
1814 for_each_pci_dev(pcidev) {
1815 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1817 if (pcidev->device != this_board->device_id)
1820 /* requested particular bus/slot */
1821 if (pcidev->bus->number != bus ||
1822 PCI_SLOT(pcidev->devfn) != slot)
1827 dev_err(dev->class_dev,
1828 "no supported board found! (req. bus/slot : %d/%d)\n",
1833 static int pci9118_common_attach(struct comedi_device *dev, int disable_irq,
1834 int master, int ext_mux, int softsshdelay,
1837 const struct boardtype *this_board = comedi_board(dev);
1838 struct pci9118_private *devpriv = dev->private;
1839 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1840 struct comedi_subdevice *s;
1844 dev->board_name = this_board->name;
1845 ret = comedi_pci_enable(dev);
1849 pci_set_master(pcidev);
1851 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1852 dev->iobase = pci_resource_start(pcidev, 2);
1856 if (master) { /* alloc DMA buffers */
1857 devpriv->dma_doublebuf = 0;
1858 for (i = 0; i < 2; i++) {
1859 for (pages = 4; pages >= 0; pages--) {
1860 devpriv->dmabuf_virt[i] =
1862 __get_free_pages(GFP_KERNEL, pages);
1863 if (devpriv->dmabuf_virt[i])
1866 if (devpriv->dmabuf_virt[i]) {
1867 devpriv->dmabuf_pages[i] = pages;
1868 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
1869 devpriv->dmabuf_hw[i] =
1870 virt_to_bus((void *)
1871 devpriv->dmabuf_virt[i]);
1874 if (!devpriv->dmabuf_virt[0]) {
1875 dev_warn(dev->class_dev,
1876 "Can't allocate DMA buffer, DMA disabled!\n");
1879 if (devpriv->dmabuf_virt[1])
1880 devpriv->dma_doublebuf = 1;
1882 devpriv->master = master;
1886 ext_mux = 256; /* max 256 channels! */
1887 if (softsshdelay > 0)
1890 devpriv->usemux = ext_mux;
1892 devpriv->usemux = 0;
1895 if (softsshdelay < 0) {
1896 /* select sample&hold signal polarity */
1897 devpriv->softsshdelay = -softsshdelay;
1898 devpriv->softsshsample = 0x80;
1899 devpriv->softsshhold = 0x00;
1901 devpriv->softsshdelay = softsshdelay;
1902 devpriv->softsshsample = 0x00;
1903 devpriv->softsshhold = 0x80;
1906 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
1907 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
1908 /* Enable parity check for parity error */
1910 if (!disable_irq && pcidev->irq) {
1911 ret = request_irq(pcidev->irq, pci9118_interrupt, IRQF_SHARED,
1912 dev->board_name, dev);
1914 dev->irq = pcidev->irq;
1917 ret = comedi_alloc_subdevices(dev, 4);
1921 s = &dev->subdevices[0];
1922 s->type = COMEDI_SUBD_AI;
1923 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
1924 if (devpriv->usemux)
1925 s->n_chan = devpriv->usemux;
1927 s->n_chan = this_board->n_aichan;
1929 s->maxdata = this_board->ai_maxdata;
1930 s->range_table = this_board->rangelist_ai;
1931 s->insn_read = pci9118_insn_read_ai;
1933 dev->read_subdev = s;
1934 s->subdev_flags |= SDF_CMD_READ;
1935 s->len_chanlist = this_board->n_aichanlist;
1936 s->do_cmdtest = pci9118_ai_cmdtest;
1937 s->do_cmd = pci9118_ai_cmd;
1938 s->cancel = pci9118_ai_cancel;
1939 s->munge = pci9118_ai_munge;
1942 s = &dev->subdevices[1];
1943 s->type = COMEDI_SUBD_AO;
1944 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1945 s->n_chan = this_board->n_aochan;
1946 s->maxdata = this_board->ao_maxdata;
1947 s->len_chanlist = this_board->n_aochan;
1948 s->range_table = this_board->rangelist_ao;
1949 s->insn_write = pci9118_insn_write_ao;
1950 s->insn_read = pci9118_insn_read_ao;
1952 s = &dev->subdevices[2];
1953 s->type = COMEDI_SUBD_DI;
1954 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
1957 s->len_chanlist = 4;
1958 s->range_table = &range_digital;
1959 s->insn_bits = pci9118_insn_bits_di;
1961 s = &dev->subdevices[3];
1962 s->type = COMEDI_SUBD_DO;
1963 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
1966 s->len_chanlist = 4;
1967 s->range_table = &range_digital;
1968 s->insn_bits = pci9118_insn_bits_do;
1970 devpriv->ai_maskharderr = 0x10a;
1971 /* default measure crash condition */
1972 if (hw_err_mask) /* disable some requested */
1973 devpriv->ai_maskharderr &= ~hw_err_mask;
1978 static int pci9118_attach(struct comedi_device *dev,
1979 struct comedi_devconfig *it)
1981 struct pci9118_private *devpriv;
1982 struct pci_dev *pcidev;
1983 int ext_mux, disable_irq, master, softsshdelay, hw_err_mask;
1985 ext_mux = it->options[2];
1986 master = ((it->options[3] & 1) == 0);
1987 disable_irq = ((it->options[3] & 2) != 0);
1988 softsshdelay = it->options[4];
1989 hw_err_mask = it->options[5];
1991 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1995 pcidev = pci9118_find_pci(dev, it);
1998 comedi_set_hw_dev(dev, &pcidev->dev);
2000 return pci9118_common_attach(dev, disable_irq, master, ext_mux,
2001 softsshdelay, hw_err_mask);
2004 static int pci9118_auto_attach(struct comedi_device *dev,
2005 unsigned long context_unused)
2007 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2008 struct pci9118_private *devpriv;
2010 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
2014 dev->board_ptr = pci9118_find_boardinfo(pcidev);
2015 if (dev->board_ptr == NULL) {
2016 dev_err(dev->class_dev,
2017 "adl_pci9118: cannot determine board type for pci %s\n",
2022 * Need to 'get' the PCI device to match the 'put' in pci9118_detach().
2023 * (The 'put' also matches the implicit 'get' by pci9118_find_pci().)
2025 pci_dev_get(pcidev);
2026 /* Don't disable irq, use bus master, no external mux,
2027 * no sample-hold delay, no error mask. */
2028 return pci9118_common_attach(dev, 0, 1, 0, 0, 0);
2031 static void pci9118_detach(struct comedi_device *dev)
2033 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2034 struct pci9118_private *devpriv = dev->private;
2040 free_irq(dev->irq, dev);
2041 if (devpriv->dmabuf_virt[0])
2042 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2043 devpriv->dmabuf_pages[0]);
2044 if (devpriv->dmabuf_virt[1])
2045 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2046 devpriv->dmabuf_pages[1]);
2048 comedi_pci_disable(dev);
2050 pci_dev_put(pcidev);
2053 static struct comedi_driver adl_pci9118_driver = {
2054 .driver_name = "adl_pci9118",
2055 .module = THIS_MODULE,
2056 .attach = pci9118_attach,
2057 .auto_attach = pci9118_auto_attach,
2058 .detach = pci9118_detach,
2059 .num_names = ARRAY_SIZE(boardtypes),
2060 .board_name = &boardtypes[0].name,
2061 .offset = sizeof(struct boardtype),
2064 static int adl_pci9118_pci_probe(struct pci_dev *dev,
2065 const struct pci_device_id *id)
2067 return comedi_pci_auto_config(dev, &adl_pci9118_driver,
2071 static const struct pci_device_id adl_pci9118_pci_table[] = {
2072 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2075 MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2077 static struct pci_driver adl_pci9118_pci_driver = {
2078 .name = "adl_pci9118",
2079 .id_table = adl_pci9118_pci_table,
2080 .probe = adl_pci9118_pci_probe,
2081 .remove = comedi_pci_auto_unconfig,
2083 module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
2085 MODULE_AUTHOR("Comedi http://www.comedi.org");
2086 MODULE_DESCRIPTION("Comedi low-level driver");
2087 MODULE_LICENSE("GPL");