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
65 #include "../comedidev.h"
67 #include <linux/delay.h>
68 #include <linux/gfp.h>
69 #include <linux/interrupt.h>
72 #include "amcc_s5933.h"
74 #include "comedi_fc.h"
76 /* paranoid checks are broken */
77 #undef PCI9118_PARANOIDCHECK /*
78 * if defined, then is used code which control
79 * correct channel number on every 12 bit sample
82 #define IORANGE_9118 64 /* I hope */
83 #define PCI9118_CHANLEN 255 /*
84 * len of chanlist, some source say 256,
85 * but reality looks like 255 :-(
88 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
89 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
90 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
91 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
92 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
93 #define PCI9118_DA1 0x10 /* W: D/A registers */
94 #define PCI9118_DA2 0x14
95 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
96 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
97 #define PCI9118_DI 0x1c /* R: digi input register */
98 #define PCI9118_DO 0x1c /* W: digi output register */
99 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
100 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
101 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
102 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
103 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
104 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
105 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
106 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
108 /* bits from A/D control register (PCI9118_ADCNTRL) */
109 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
110 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
111 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
112 #define AdControl_ExtG 0x10 /*
113 * 1=8254 countrol controlled by TGIN(pin 46),
114 * 0=controlled by SoftG
116 #define AdControl_ExtM 0x08 /*
117 * 1=external hardware trigger (pin 44),
120 #define AdControl_TmrTr 0x04 /*
121 * 1=8254 is iternal trigger source,
122 * 0=software trigger is source
123 * (register PCI9118_SOFTTRG)
125 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
126 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
128 /* bits from A/D function register (PCI9118_ADFUNC) */
129 #define AdFunction_PDTrg 0x80 /*
131 * 0=negative digital trigger
132 * (only positive is correct)
134 #define AdFunction_PETrg 0x40 /*
136 * 0=negative external trigger
137 * (only positive is correct)
139 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
140 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
141 #define AdFunction_BS 0x08 /*
142 * 1=burst mode start,
145 #define AdFunction_PM 0x04 /*
146 * 1=post trigger mode,
149 #define AdFunction_AM 0x02 /*
150 * 1=about trigger mode,
151 * 0=not about trigger
153 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
155 /* bits from A/D status register (PCI9118_ADSTAT) */
156 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
157 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
158 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
159 #define AdStatus_Acmp 0x020 /* */
160 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
161 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
162 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
163 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
164 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
166 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
167 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
168 #define Int_Timer 0x08 /* timer interrupt */
169 #define Int_About 0x04 /* about trigger complete */
170 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
171 #define Int_DTrg 0x01 /* external digital trigger */
173 #define START_AI_EXT 0x01 /* start measure on external trigger */
174 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
175 #define START_AI_INT 0x04 /* start measure on internal trigger */
176 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
178 #define EXTTRG_AI 0 /* ext trg is used by AI */
180 static const struct comedi_lrange range_pci9118dg_hr = { 8, {
192 static const struct comedi_lrange range_pci9118hg = { 8, {
204 #define PCI9118_BIPOLAR_RANGES 4 /*
205 * used for test on mixture
210 const char *name; /* board name */
211 int vendor_id; /* PCI vendor a device ID of card */
213 int iorange_amcc; /* iorange for own S5933 region */
214 int iorange_9118; /* pass thru card region size */
215 int n_aichan; /* num of A/D chans */
216 int n_aichand; /* num of A/D chans in diff mode */
218 * num of A/D chans with
219 * external multiplexor
221 int n_aichanlist; /* len of chanlist */
222 int n_aochan; /* num of D/A chans */
223 int ai_maxdata; /* resolution of A/D */
224 int ao_maxdata; /* resolution of D/A */
225 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
226 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
227 unsigned int ai_ns_min; /* max sample speed of card v ns */
228 unsigned int ai_pacer_min; /*
229 * minimal pacer value
230 * (c1*c2 or c1 in burst)
232 int half_fifo_size; /* size of FIFO/2 */
236 struct pci9118_private {
237 unsigned long iobase_a; /* base+size for AMCC chip */
238 unsigned int master; /* master capable */
239 unsigned int usemux; /* we want to use external multiplexor! */
240 #ifdef PCI9118_PARANOIDCHECK
241 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
245 unsigned char chanlistlen; /* number of scanlist */
247 unsigned char AdControlReg; /* A/D control register */
248 unsigned char IntControlReg; /* Interrupt control register */
249 unsigned char AdFunctionReg; /* A/D function register */
250 char valid; /* driver is ok */
251 char ai_neverending; /* we do unlimited AI */
252 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
253 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
254 unsigned int ai_act_scan; /* how many scans we finished */
255 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
256 unsigned int ai_n_chan; /* how many channels is measured */
257 unsigned int ai_n_scanlen; /* len of actual scanlist */
258 unsigned int ai_n_realscanlen; /*
259 * what we must transfer for one
260 * outgoing scan include front/back adds
262 unsigned int ai_act_dmapos; /* position in actual real stream */
263 unsigned int ai_add_front; /*
264 * how many channels we must add
265 * before scan to satisfy S&H?
267 unsigned int ai_add_back; /*
268 * how many channels we must add
269 * before scan to satisfy DMA?
271 unsigned int *ai_chanlist; /* actual chanlist */
272 unsigned int ai_timer1;
273 unsigned int ai_timer2;
274 unsigned int ai_flags;
275 char ai12_startstop; /*
276 * measure can start/stop
277 * on external trigger
279 unsigned int ai_divisor1, ai_divisor2; /*
280 * divisors for start of measure
283 unsigned int ai_data_len;
285 short ao_data[2]; /* data output buffer */
286 unsigned int ai_scans; /* number of scans to do */
287 char dma_doublebuf; /* we can use double buffering */
288 unsigned int dma_actbuf; /* which buffer is used now */
289 short *dmabuf_virt[2]; /*
290 * pointers to begin of
293 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
294 unsigned int dmabuf_size[2]; /*
295 * size of dma buffer in bytes
297 unsigned int dmabuf_use_size[2]; /*
298 * which size we may now use
301 unsigned int dmabuf_used_size[2]; /* which size was truly used */
302 unsigned int dmabuf_panic_size[2];
303 unsigned int dmabuf_samples[2]; /* size in samples */
304 int dmabuf_pages[2]; /* number of pages in buffer */
305 unsigned char cnt0_users; /*
306 * bit field of 8254 CNT0 users
307 * (0-unused, 1-AO, 2-DI, 3-DO)
309 unsigned char exttrg_users; /*
310 * bit field of external trigger
311 * users(0-AI, 1-AO, 2-DI, 3-DO)
313 unsigned int cnt0_divisor; /* actual CNT0 divisor */
314 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
318 * ptr to actual interrupt
321 unsigned char ai16bits; /* =1 16 bit card */
322 unsigned char usedma; /* =1 use DMA transfer and not INT */
323 unsigned char useeoshandle; /*
324 * =1 change WAKE_EOS DMA transfer
325 * to fit on every second
327 unsigned char usessh; /* =1 turn on S&H support */
329 * >0 use software S&H,
330 * numer is requested delay in ns
332 unsigned char softsshsample; /*
333 * polarity of S&H signal
336 unsigned char softsshhold; /*
337 * polarity of S&H signal
340 unsigned int ai_maskerr; /* which warning was printed */
341 unsigned int ai_maskharderr; /* on which error bits stops */
342 unsigned int ai_inttrig_start; /* TRIG_INT for start */
345 static int check_channel_list(struct comedi_device *dev,
346 struct comedi_subdevice *s, int n_chan,
347 unsigned int *chanlist, int frontadd, int backadd)
349 const struct boardtype *this_board = comedi_board(dev);
350 struct pci9118_private *devpriv = dev->private;
351 unsigned int i, differencial = 0, bipolar = 0;
353 /* correct channel and range number check itself comedi/range.c */
355 comedi_error(dev, "range/channel list is empty!");
358 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
360 "range/channel list is too long for actual configuration!\n");
364 if (CR_AREF(chanlist[0]) == AREF_DIFF)
365 differencial = 1; /* all input must be diff */
366 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
367 bipolar = 1; /* all input must be bipolar */
369 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
370 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
373 "Differencial and single ended "
374 "inputs can't be mixtured!");
377 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
380 "Bipolar and unipolar ranges "
381 "can't be mixtured!");
384 if (!devpriv->usemux && differencial &&
385 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
387 "If AREF_DIFF is used then is "
388 "available only first 8 channels!");
396 static int setup_channel_list(struct comedi_device *dev,
397 struct comedi_subdevice *s, int n_chan,
398 unsigned int *chanlist, int rot, int frontadd,
399 int backadd, int usedma, char useeos)
401 struct pci9118_private *devpriv = dev->private;
402 unsigned int i, differencial = 0, bipolar = 0;
403 unsigned int scanquad, gain, ssh = 0x00;
410 if (CR_AREF(chanlist[0]) == AREF_DIFF)
411 differencial = 1; /* all input must be diff */
412 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
413 bipolar = 1; /* all input must be bipolar */
415 /* All is ok, so we can setup channel/range list */
418 devpriv->AdControlReg |= AdControl_UniP;
421 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
426 devpriv->AdControlReg |= AdControl_Diff;
427 /* enable diff inputs */
429 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
430 /* set single ended inputs */
433 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
436 outl(2, dev->iobase + PCI9118_SCANMOD);
437 /* gods know why this sequence! */
438 outl(0, dev->iobase + PCI9118_SCANMOD);
439 outl(1, dev->iobase + PCI9118_SCANMOD);
441 #ifdef PCI9118_PARANOIDCHECK
442 devpriv->chanlistlen = n_chan;
443 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
444 devpriv->chanlist[i] = 0x55aa;
447 if (frontadd) { /* insert channels for S&H */
448 ssh = devpriv->softsshsample;
449 for (i = 0; i < frontadd; i++) {
450 /* store range list to card */
451 scanquad = CR_CHAN(chanlist[0]);
452 /* get channel number; */
453 gain = CR_RANGE(chanlist[0]);
454 /* get gain number */
455 scanquad |= ((gain & 0x03) << 8);
456 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
457 ssh = devpriv->softsshhold;
461 for (i = 0; i < n_chan; i++) { /* store range list to card */
462 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
463 #ifdef PCI9118_PARANOIDCHECK
464 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
466 gain = CR_RANGE(chanlist[i]); /* get gain number */
467 scanquad |= ((gain & 0x03) << 8);
468 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
471 if (backadd) { /* insert channels for fit onto 32bit DMA */
472 for (i = 0; i < backadd; i++) { /* store range list to card */
473 scanquad = CR_CHAN(chanlist[0]);
474 /* get channel number */
475 gain = CR_RANGE(chanlist[0]); /* get gain number */
476 scanquad |= ((gain & 0x03) << 8);
477 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
480 #ifdef PCI9118_PARANOIDCHECK
481 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
482 /* for 32bit operations */
484 for (i = 1; i < n_chan; i++) { /* store range list to card */
485 devpriv->chanlist[(n_chan + i) ^ usedma] =
486 (CR_CHAN(chanlist[i]) & 0xf) << rot;
488 devpriv->chanlist[(2 * n_chan) ^ usedma] =
489 devpriv->chanlist[0 ^ usedma];
490 /* for 32bit operations */
496 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
497 /* udelay(100); important delay, or first sample will be crippled */
499 return 1; /* we can serve this with scan logic */
502 static int pci9118_insn_read_ai(struct comedi_device *dev,
503 struct comedi_subdevice *s,
504 struct comedi_insn *insn, unsigned int *data)
506 struct pci9118_private *devpriv = dev->private;
509 devpriv->AdControlReg = AdControl_Int & 0xff;
510 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
511 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
513 * positive triggers, no S&H,
514 * no burst, burst stop,
520 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
523 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
525 for (n = 0; n < insn->n; n++) {
526 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
530 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
535 comedi_error(dev, "A/D insn timeout");
537 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
541 if (devpriv->ai16bits) {
544 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
547 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
551 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
556 static int pci9118_insn_write_ao(struct comedi_device *dev,
557 struct comedi_subdevice *s,
558 struct comedi_insn *insn, unsigned int *data)
560 struct pci9118_private *devpriv = dev->private;
563 ch = CR_CHAN(insn->chanspec);
565 chanreg = PCI9118_DA2;
567 chanreg = PCI9118_DA1;
570 for (n = 0; n < insn->n; n++) {
571 outl(data[n], dev->iobase + chanreg);
572 devpriv->ao_data[ch] = data[n];
578 static int pci9118_insn_read_ao(struct comedi_device *dev,
579 struct comedi_subdevice *s,
580 struct comedi_insn *insn, unsigned int *data)
582 struct pci9118_private *devpriv = dev->private;
585 chan = CR_CHAN(insn->chanspec);
586 for (n = 0; n < insn->n; n++)
587 data[n] = devpriv->ao_data[chan];
592 static int pci9118_insn_bits_di(struct comedi_device *dev,
593 struct comedi_subdevice *s,
594 struct comedi_insn *insn, unsigned int *data)
596 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
601 static int pci9118_insn_bits_do(struct comedi_device *dev,
602 struct comedi_subdevice *s,
603 struct comedi_insn *insn, unsigned int *data)
606 s->state &= ~data[0];
607 s->state |= (data[0] & data[1]);
608 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
615 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
617 struct pci9118_private *devpriv = dev->private;
619 devpriv->AdFunctionReg =
620 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
621 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
622 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
623 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
624 dev->iobase + PCI9118_CNT0);
625 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
626 dev->iobase + PCI9118_CNT0);
627 devpriv->AdFunctionReg |= AdFunction_Start;
628 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
631 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
632 struct comedi_subdevice *s,
634 unsigned int num_samples)
636 struct pci9118_private *devpriv = dev->private;
637 unsigned int i = 0, j = 0;
638 unsigned int start_pos = devpriv->ai_add_front,
639 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
640 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
641 devpriv->ai_add_back;
643 for (i = 0; i < num_samples; i++) {
644 if (devpriv->ai_act_dmapos >= start_pos &&
645 devpriv->ai_act_dmapos < stop_pos) {
646 dma_buffer[j++] = dma_buffer[i];
648 devpriv->ai_act_dmapos++;
649 devpriv->ai_act_dmapos %= raw_scanlen;
655 static int move_block_from_dma(struct comedi_device *dev,
656 struct comedi_subdevice *s,
658 unsigned int num_samples)
660 struct pci9118_private *devpriv = dev->private;
661 unsigned int num_bytes;
663 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
664 devpriv->ai_act_scan +=
665 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
666 s->async->cur_chan += num_samples;
667 s->async->cur_chan %= devpriv->ai_n_scanlen;
669 cfc_write_array_to_buffer(s, dma_buffer,
670 num_samples * sizeof(short));
671 if (num_bytes < num_samples * sizeof(short))
676 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
678 struct pci9118_private *devpriv = dev->private;
681 return -1; /* incorrect source */
682 devpriv->exttrg_users |= (1 << source);
683 devpriv->IntControlReg |= Int_DTrg;
684 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
685 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
686 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
687 /* allow INT in AMCC */
691 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
693 struct pci9118_private *devpriv = dev->private;
696 return -1; /* incorrect source */
697 devpriv->exttrg_users &= ~(1 << source);
698 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
699 devpriv->IntControlReg &= ~Int_DTrg;
700 if (!devpriv->IntControlReg) /* all IRQ disabled */
701 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
703 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
704 /* disable int in AMCC */
705 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
710 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
711 struct comedi_subdevice *s,
712 unsigned int *tim1, unsigned int *tim2,
713 unsigned int flags, int chans,
714 unsigned int *div1, unsigned int *div2,
715 char usessh, unsigned int chnsshfront)
717 const struct boardtype *this_board = comedi_board(dev);
718 struct pci9118_private *devpriv = dev->private;
723 if (*tim2 < this_board->ai_ns_min)
724 *tim2 = this_board->ai_ns_min;
725 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
726 tim2, flags & TRIG_ROUND_NEAREST);
729 if (*tim2 < this_board->ai_ns_min)
730 *tim2 = this_board->ai_ns_min;
731 *div1 = *tim2 / devpriv->i8254_osc_base;
732 /* convert timer (burst) */
733 if (*div1 < this_board->ai_pacer_min)
734 *div1 = this_board->ai_pacer_min;
735 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
736 *div2 = *div2 / *div1; /* major timer is c1*c2 */
740 *tim2 = *div1 * devpriv->i8254_osc_base;
741 /* real convert timer */
743 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
744 if (*div2 < (chans + 2))
747 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
752 static void start_pacer(struct comedi_device *dev, int mode,
753 unsigned int divisor1, unsigned int divisor2)
755 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
756 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
757 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
760 if ((mode == 1) || (mode == 2) || (mode == 4)) {
761 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
762 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
763 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
764 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
768 static int pci9118_ai_cancel(struct comedi_device *dev,
769 struct comedi_subdevice *s)
771 struct pci9118_private *devpriv = dev->private;
774 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
776 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
777 pci9118_exttrg_del(dev, EXTTRG_AI);
778 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
779 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
780 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
782 * positive triggers, no S&H, no burst,
783 * burst stop, no post trigger,
784 * no about trigger, trigger stop
786 devpriv->AdControlReg = 0x00;
787 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
789 * bipolar, S.E., use 8254, stop 8354,
790 * internal trigger, soft trigger,
791 * disable INT and DMA
793 outl(0, dev->iobase + PCI9118_BURST);
794 outl(1, dev->iobase + PCI9118_SCANMOD);
795 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
796 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
801 devpriv->ai_act_scan = 0;
802 devpriv->ai_act_dmapos = 0;
803 s->async->cur_chan = 0;
804 s->async->inttrig = NULL;
805 devpriv->ai_buf_ptr = 0;
806 devpriv->ai_neverending = 0;
807 devpriv->dma_actbuf = 0;
809 if (!devpriv->IntControlReg)
810 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
811 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
812 /* allow INT in AMCC */
817 static char pci9118_decode_error_status(struct comedi_device *dev,
818 struct comedi_subdevice *s,
821 struct pci9118_private *devpriv = dev->private;
824 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
825 devpriv->ai_maskerr &= ~0x100L;
829 "A/D Burst Mode Overrun Status (Fatal Error!)");
830 devpriv->ai_maskerr &= ~0x008L;
833 comedi_error(dev, "A/D Over Speed Status (Warning!)");
834 devpriv->ai_maskerr &= ~0x004L;
837 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
838 devpriv->ai_maskerr &= ~0x002L;
840 if (m & devpriv->ai_maskharderr) {
841 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
842 pci9118_ai_cancel(dev, s);
843 comedi_event(dev, s);
850 static void pci9118_ai_munge(struct comedi_device *dev,
851 struct comedi_subdevice *s, void *data,
852 unsigned int num_bytes,
853 unsigned int start_chan_index)
855 struct pci9118_private *devpriv = dev->private;
856 unsigned int i, num_samples = num_bytes / sizeof(short);
859 for (i = 0; i < num_samples; i++) {
861 array[i] = be16_to_cpu(array[i]);
862 if (devpriv->ai16bits)
865 array[i] = (array[i] >> 4) & 0x0fff;
870 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
871 struct comedi_subdevice *s,
872 unsigned short int_adstat,
873 unsigned int int_amcc,
874 unsigned short int_daq)
876 struct pci9118_private *devpriv = dev->private;
877 register short sampl;
879 s->async->events = 0;
881 if (int_adstat & devpriv->ai_maskerr)
882 if (pci9118_decode_error_status(dev, s, int_adstat))
885 sampl = inw(dev->iobase + PCI9118_AD_DATA);
887 #ifdef PCI9118_PARANOIDCHECK
888 if (devpriv->ai16bits == 0) {
889 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
891 dev_info(dev->class_dev,
892 "A/D SAMPL - data dropout: received channel %d, expected %d!\n",
894 devpriv->chanlist[s->async->cur_chan]);
895 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
896 pci9118_ai_cancel(dev, s);
897 comedi_event(dev, s);
902 cfc_write_to_buffer(s, sampl);
903 s->async->cur_chan++;
904 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
906 s->async->cur_chan %= devpriv->ai_n_scanlen;
907 devpriv->ai_act_scan++;
908 if (!(devpriv->ai_neverending))
909 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
910 /* all data sampled */
911 pci9118_ai_cancel(dev, s);
912 s->async->events |= COMEDI_CB_EOA;
916 if (s->async->events)
917 comedi_event(dev, s);
920 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
921 struct comedi_subdevice *s,
922 unsigned short int_adstat,
923 unsigned int int_amcc,
924 unsigned short int_daq)
926 struct pci9118_private *devpriv = dev->private;
927 unsigned int next_dma_buf, samplesinbuf, sampls, m;
929 if (int_amcc & MASTER_ABORT_INT) {
930 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
931 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
932 pci9118_ai_cancel(dev, s);
933 comedi_event(dev, s);
937 if (int_amcc & TARGET_ABORT_INT) {
938 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
939 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
940 pci9118_ai_cancel(dev, s);
941 comedi_event(dev, s);
944 if (int_adstat & devpriv->ai_maskerr)
945 /* if (int_adstat & 0x106) */
946 if (pci9118_decode_error_status(dev, s, int_adstat))
949 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
950 /* number of received real samples */
952 if (devpriv->dma_doublebuf) { /*
953 * switch DMA buffers if is used
956 next_dma_buf = 1 - devpriv->dma_actbuf;
957 outl(devpriv->dmabuf_hw[next_dma_buf],
958 devpriv->iobase_a + AMCC_OP_REG_MWAR);
959 outl(devpriv->dmabuf_use_size[next_dma_buf],
960 devpriv->iobase_a + AMCC_OP_REG_MWTC);
961 devpriv->dmabuf_used_size[next_dma_buf] =
962 devpriv->dmabuf_use_size[next_dma_buf];
963 if (devpriv->ai_do == 4)
964 interrupt_pci9118_ai_mode4_switch(dev);
968 m = devpriv->ai_data_len >> 1; /*
969 * how many samples is to
973 move_block_from_dma(dev, s,
974 devpriv->dmabuf_virt[devpriv->dma_actbuf],
976 m = m - sampls; /* m= how many samples was transferred */
979 if (!devpriv->ai_neverending)
980 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
981 /* all data sampled */
982 pci9118_ai_cancel(dev, s);
983 s->async->events |= COMEDI_CB_EOA;
986 if (devpriv->dma_doublebuf) { /* switch dma buffers */
987 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
988 } else { /* restart DMA if is not used double buffering */
989 outl(devpriv->dmabuf_hw[0],
990 devpriv->iobase_a + AMCC_OP_REG_MWAR);
991 outl(devpriv->dmabuf_use_size[0],
992 devpriv->iobase_a + AMCC_OP_REG_MWTC);
993 if (devpriv->ai_do == 4)
994 interrupt_pci9118_ai_mode4_switch(dev);
997 comedi_event(dev, s);
1000 static irqreturn_t interrupt_pci9118(int irq, void *d)
1002 struct comedi_device *dev = d;
1003 struct pci9118_private *devpriv = dev->private;
1004 unsigned int int_daq = 0, int_amcc, int_adstat;
1007 return IRQ_NONE; /* not fully initialized */
1009 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
1010 /* get IRQ reasons from card */
1011 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1012 /* get INT register from AMCC chip */
1014 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
1015 return IRQ_NONE; /* interrupt from other source */
1017 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1018 /* shutdown IRQ reasons in AMCC */
1020 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
1021 /* get STATUS register */
1023 if (devpriv->ai_do) {
1024 if (devpriv->ai12_startstop)
1025 if ((int_adstat & AdStatus_DTH) &&
1026 (int_daq & Int_DTrg)) {
1027 /* start stop of measure */
1028 if (devpriv->ai12_startstop & START_AI_EXT) {
1029 devpriv->ai12_startstop &=
1031 if (!(devpriv->ai12_startstop &
1035 /* deactivate EXT trigger */
1036 start_pacer(dev, devpriv->ai_do,
1037 devpriv->ai_divisor1,
1038 devpriv->ai_divisor2);
1040 outl(devpriv->AdControlReg,
1041 dev->iobase + PCI9118_ADCNTRL);
1043 if (devpriv->ai12_startstop &
1045 devpriv->ai12_startstop &=
1049 /* deactivate EXT trigger */
1050 devpriv->ai_neverending = 0;
1052 * well, on next interrupt from
1053 * DMA/EOC measure will stop
1059 (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat,
1066 static int pci9118_ai_inttrig(struct comedi_device *dev,
1067 struct comedi_subdevice *s, unsigned int trignum)
1069 struct pci9118_private *devpriv = dev->private;
1071 if (trignum != devpriv->ai_inttrig_start)
1074 devpriv->ai12_startstop &= ~START_AI_INT;
1075 s->async->inttrig = NULL;
1077 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1078 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1079 if (devpriv->ai_do != 3) {
1080 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1081 devpriv->ai_divisor2);
1082 devpriv->AdControlReg |= AdControl_SoftG;
1084 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1089 static int pci9118_ai_cmdtest(struct comedi_device *dev,
1090 struct comedi_subdevice *s,
1091 struct comedi_cmd *cmd)
1093 const struct boardtype *this_board = comedi_board(dev);
1094 struct pci9118_private *devpriv = dev->private;
1098 unsigned int divisor1 = 0, divisor2 = 0;
1100 /* Step 1 : check if triggers are trivially valid */
1102 err |= cfc_check_trigger_src(&cmd->start_src,
1103 TRIG_NOW | TRIG_EXT | TRIG_INT);
1105 flags = TRIG_FOLLOW;
1106 if (devpriv->master)
1107 flags |= TRIG_TIMER | TRIG_EXT;
1108 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1110 flags = TRIG_TIMER | TRIG_EXT;
1111 if (devpriv->master)
1113 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
1115 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1116 err |= cfc_check_trigger_src(&cmd->stop_src,
1117 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1122 /* Step 2a : make sure trigger sources are unique */
1124 err |= cfc_check_trigger_is_unique(cmd->start_src);
1125 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1126 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1127 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1129 /* Step 2b : and mutually compatible */
1131 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1134 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
1137 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1138 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1141 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1142 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1145 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1151 /* step 3: make sure arguments are trivially compatible */
1153 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1154 if (cmd->start_arg != 0) {
1159 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1160 if (cmd->scan_begin_arg != 0) {
1161 cmd->scan_begin_arg = 0;
1165 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1166 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1167 cmd->scan_begin_src = TRIG_FOLLOW;
1168 cmd->convert_arg = cmd->scan_begin_arg;
1169 cmd->scan_begin_arg = 0;
1172 if (cmd->scan_begin_src == TRIG_TIMER)
1173 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1174 cmd->scan_begin_arg = this_board->ai_ns_min;
1178 if (cmd->scan_begin_src == TRIG_EXT)
1179 if (cmd->scan_begin_arg) {
1180 cmd->scan_begin_arg = 0;
1182 if (cmd->scan_end_arg > 65535) {
1183 cmd->scan_end_arg = 65535;
1188 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1189 if (cmd->convert_arg < this_board->ai_ns_min) {
1190 cmd->convert_arg = this_board->ai_ns_min;
1194 if (cmd->convert_src == TRIG_EXT)
1195 if (cmd->convert_arg) {
1196 cmd->convert_arg = 0;
1200 if (cmd->stop_src == TRIG_COUNT) {
1201 if (!cmd->stop_arg) {
1205 } else { /* TRIG_NONE */
1206 if (cmd->stop_arg != 0) {
1212 if (!cmd->chanlist_len) {
1213 cmd->chanlist_len = 1;
1217 if (cmd->chanlist_len > this_board->n_aichanlist) {
1218 cmd->chanlist_len = this_board->n_aichanlist;
1222 if (cmd->scan_end_arg < cmd->chanlist_len) {
1223 cmd->scan_end_arg = cmd->chanlist_len;
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 tmp = cmd->scan_begin_arg;
1240 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1241 &divisor2, &cmd->scan_begin_arg,
1242 cmd->flags & TRIG_ROUND_MASK);
1243 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1244 cmd->scan_begin_arg = this_board->ai_ns_min;
1245 if (tmp != cmd->scan_begin_arg)
1249 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1250 tmp = cmd->convert_arg;
1251 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1252 &divisor2, &cmd->convert_arg,
1253 cmd->flags & TRIG_ROUND_MASK);
1254 if (cmd->convert_arg < this_board->ai_ns_min)
1255 cmd->convert_arg = this_board->ai_ns_min;
1256 if (tmp != cmd->convert_arg)
1258 if (cmd->scan_begin_src == TRIG_TIMER
1259 && cmd->convert_src == TRIG_NOW) {
1260 if (cmd->convert_arg == 0) {
1261 if (cmd->scan_begin_arg <
1262 this_board->ai_ns_min *
1263 (cmd->scan_end_arg + 2)) {
1264 cmd->scan_begin_arg =
1265 this_board->ai_ns_min *
1266 (cmd->scan_end_arg + 2);
1270 if (cmd->scan_begin_arg <
1271 cmd->convert_arg * cmd->chanlist_len) {
1272 cmd->scan_begin_arg =
1285 if (!check_channel_list(dev, s, cmd->chanlist_len,
1286 cmd->chanlist, 0, 0))
1287 return 5; /* incorrect channels list */
1292 static int Compute_and_setup_dma(struct comedi_device *dev)
1294 struct pci9118_private *devpriv = dev->private;
1295 unsigned int dmalen0, dmalen1, i;
1297 dmalen0 = devpriv->dmabuf_size[0];
1298 dmalen1 = devpriv->dmabuf_size[1];
1299 /* isn't output buff smaller that our DMA buff? */
1300 if (dmalen0 > (devpriv->ai_data_len)) {
1301 dmalen0 = devpriv->ai_data_len & ~3L; /*
1302 * align to 32bit down
1305 if (dmalen1 > (devpriv->ai_data_len)) {
1306 dmalen1 = devpriv->ai_data_len & ~3L; /*
1307 * align to 32bit down
1311 /* we want wake up every scan? */
1312 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1313 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1314 /* uff, too short DMA buffer, disable EOS support! */
1315 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1316 dev_info(dev->class_dev,
1317 "WAR: DMA0 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1318 dmalen0, devpriv->ai_n_realscanlen << 1);
1320 /* short first DMA buffer to one scan */
1321 dmalen0 = devpriv->ai_n_realscanlen << 1;
1322 if (devpriv->useeoshandle)
1325 dev_info(dev->class_dev,
1326 "ERR: DMA0 buf len bug? (%d<4)\n",
1332 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1333 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1334 /* uff, too short DMA buffer, disable EOS support! */
1335 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1336 dev_info(dev->class_dev,
1337 "WAR: DMA1 buf too short, can't support TRIG_WAKE_EOS (%d<%d)\n",
1338 dmalen1, devpriv->ai_n_realscanlen << 1);
1340 /* short second DMA buffer to one scan */
1341 dmalen1 = devpriv->ai_n_realscanlen << 1;
1342 if (devpriv->useeoshandle)
1345 dev_info(dev->class_dev,
1346 "ERR: DMA1 buf len bug? (%d<4)\n",
1353 /* transfer without TRIG_WAKE_EOS */
1354 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1355 /* if it's possible then align DMA buffers to length of scan */
1358 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1359 (devpriv->ai_n_realscanlen << 1);
1362 dmalen0 = i; /* uff. very long scan? */
1365 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1366 (devpriv->ai_n_realscanlen << 1);
1369 dmalen1 = i; /* uff. very long scan? */
1371 * if measure isn't neverending then test, if it fits whole
1372 * into one or two DMA buffers
1374 if (!devpriv->ai_neverending) {
1375 /* fits whole measure into one DMA buffer? */
1377 ((devpriv->ai_n_realscanlen << 1) *
1378 devpriv->ai_scans)) {
1380 (devpriv->ai_n_realscanlen << 1) *
1384 * fits whole measure into
1388 ((devpriv->ai_n_realscanlen << 1) *
1389 devpriv->ai_scans - dmalen0))
1391 (devpriv->ai_n_realscanlen << 1) *
1392 devpriv->ai_scans - dmalen0;
1398 /* these DMA buffer size will be used */
1399 devpriv->dma_actbuf = 0;
1400 devpriv->dmabuf_use_size[0] = dmalen0;
1401 devpriv->dmabuf_use_size[1] = dmalen1;
1404 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1405 devpriv->dmabuf_panic_size[0] =
1406 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1407 1) * devpriv->ai_n_scanlen * sizeof(short);
1408 devpriv->dmabuf_panic_size[1] =
1409 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1410 1) * devpriv->ai_n_scanlen * sizeof(short);
1412 devpriv->dmabuf_panic_size[0] =
1413 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1414 devpriv->dmabuf_panic_size[1] =
1415 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1419 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1420 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1421 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1422 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1423 /* init DMA transfer */
1424 outl(0x00000000 | AINT_WRITE_COMPL,
1425 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1426 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1428 outl(inl(devpriv->iobase_a +
1429 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1430 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1431 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1432 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1433 /* allow bus mastering */
1438 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1439 struct comedi_subdevice *s)
1441 struct pci9118_private *devpriv = dev->private;
1443 switch (devpriv->ai_do) {
1445 devpriv->AdControlReg |= AdControl_TmrTr;
1448 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1451 devpriv->AdControlReg |= AdControl_ExtM;
1454 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1458 "pci9118_ai_docmd_sampl() mode number bug!\n");
1462 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1463 /* transfer function */
1465 if (devpriv->ai12_startstop)
1466 pci9118_exttrg_add(dev, EXTTRG_AI);
1467 /* activate EXT trigger */
1469 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1470 devpriv->IntControlReg |= Int_Timer;
1472 devpriv->AdControlReg |= AdControl_Int;
1474 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1475 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1476 /* allow INT in AMCC */
1478 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1479 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1480 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1481 if (devpriv->ai_do != 3) {
1482 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1483 devpriv->ai_divisor2);
1484 devpriv->AdControlReg |= AdControl_SoftG;
1486 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1492 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1493 struct comedi_subdevice *s)
1495 struct pci9118_private *devpriv = dev->private;
1497 Compute_and_setup_dma(dev);
1499 switch (devpriv->ai_do) {
1501 devpriv->AdControlReg |=
1502 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1505 devpriv->AdControlReg |=
1506 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1507 devpriv->AdFunctionReg =
1508 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1510 if (devpriv->usessh && (!devpriv->softsshdelay))
1511 devpriv->AdFunctionReg |= AdFunction_BSSH;
1512 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1515 devpriv->AdControlReg |=
1516 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1517 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1520 devpriv->AdControlReg |=
1521 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1522 devpriv->AdFunctionReg =
1523 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1524 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1525 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1526 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1527 dev->iobase + PCI9118_CNT0);
1528 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1529 dev->iobase + PCI9118_CNT0);
1530 devpriv->AdFunctionReg |= AdFunction_Start;
1533 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1537 if (devpriv->ai12_startstop) {
1538 pci9118_exttrg_add(dev, EXTTRG_AI);
1539 /* activate EXT trigger */
1542 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1543 /* transfer function */
1545 outl(0x02000000 | AINT_WRITE_COMPL,
1546 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1548 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1549 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1550 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1551 if (devpriv->ai_do != 3) {
1552 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1553 devpriv->ai_divisor2);
1554 devpriv->AdControlReg |= AdControl_SoftG;
1556 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1562 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1564 const struct boardtype *this_board = comedi_board(dev);
1565 struct pci9118_private *devpriv = dev->private;
1566 struct comedi_cmd *cmd = &s->async->cmd;
1567 unsigned int addchans = 0;
1570 devpriv->ai12_startstop = 0;
1571 devpriv->ai_flags = cmd->flags;
1572 devpriv->ai_n_chan = cmd->chanlist_len;
1573 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1574 devpriv->ai_chanlist = cmd->chanlist;
1575 devpriv->ai_data = s->async->prealloc_buf;
1576 devpriv->ai_data_len = s->async->prealloc_bufsz;
1577 devpriv->ai_timer1 = 0;
1578 devpriv->ai_timer2 = 0;
1579 devpriv->ai_add_front = 0;
1580 devpriv->ai_add_back = 0;
1581 devpriv->ai_maskerr = 0x10e;
1583 /* prepare for start/stop conditions */
1584 if (cmd->start_src == TRIG_EXT)
1585 devpriv->ai12_startstop |= START_AI_EXT;
1586 if (cmd->stop_src == TRIG_EXT) {
1587 devpriv->ai_neverending = 1;
1588 devpriv->ai12_startstop |= STOP_AI_EXT;
1590 if (cmd->start_src == TRIG_INT) {
1591 devpriv->ai12_startstop |= START_AI_INT;
1592 devpriv->ai_inttrig_start = cmd->start_arg;
1593 s->async->inttrig = pci9118_ai_inttrig;
1596 if (cmd->stop_src == TRIG_INT) {
1597 devpriv->ai_neverending = 1;
1598 devpriv->ai12_startstop |= STOP_AI_INT;
1601 if (cmd->stop_src == TRIG_NONE)
1602 devpriv->ai_neverending = 1;
1603 if (cmd->stop_src == TRIG_COUNT) {
1604 devpriv->ai_scans = cmd->stop_arg;
1605 devpriv->ai_neverending = 0;
1607 devpriv->ai_scans = 0;
1610 /* use sample&hold signal? */
1611 if (cmd->convert_src == TRIG_NOW)
1612 devpriv->usessh = 1;
1615 devpriv->usessh = 0;
1619 * use additional sample at end of every scan
1620 * to satisty DMA 32 bit transfer?
1622 devpriv->ai_add_front = 0;
1623 devpriv->ai_add_back = 0;
1624 devpriv->useeoshandle = 0;
1625 if (devpriv->master) {
1626 devpriv->usedma = 1;
1627 if ((cmd->flags & TRIG_WAKE_EOS) &&
1628 (devpriv->ai_n_scanlen == 1)) {
1629 if (cmd->convert_src == TRIG_NOW)
1630 devpriv->ai_add_back = 1;
1631 if (cmd->convert_src == TRIG_TIMER) {
1632 devpriv->usedma = 0;
1634 * use INT transfer if scanlist
1635 * have only one channel
1639 if ((cmd->flags & TRIG_WAKE_EOS) &&
1640 (devpriv->ai_n_scanlen & 1) &&
1641 (devpriv->ai_n_scanlen > 1)) {
1642 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1644 * vpriv->useeoshandle=1; // change DMA transfer
1645 * block to fit EOS on every second call
1647 devpriv->usedma = 0;
1649 * XXX maybe can be corrected to use 16 bit DMA
1652 * well, we must insert one sample
1653 * to end of EOS to meet 32 bit transfer
1655 devpriv->ai_add_back = 1;
1658 } else { /* interrupt transfer don't need any correction */
1659 devpriv->usedma = 0;
1663 * we need software S&H signal?
1664 * It adds two samples before every scan as minimum
1666 if (devpriv->usessh && devpriv->softsshdelay) {
1667 devpriv->ai_add_front = 2;
1668 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1669 /* move it to front */
1670 devpriv->ai_add_front++;
1671 devpriv->ai_add_back = 0;
1673 if (cmd->convert_arg < this_board->ai_ns_min)
1674 cmd->convert_arg = this_board->ai_ns_min;
1675 addchans = devpriv->softsshdelay / cmd->convert_arg;
1676 if (devpriv->softsshdelay % cmd->convert_arg)
1678 if (addchans > (devpriv->ai_add_front - 1)) {
1679 /* uff, still short */
1680 devpriv->ai_add_front = addchans + 1;
1681 if (devpriv->usedma == 1)
1682 if ((devpriv->ai_add_front +
1683 devpriv->ai_n_chan +
1684 devpriv->ai_add_back) & 1)
1685 devpriv->ai_add_front++;
1686 /* round up to 32 bit */
1689 /* well, we now know what must be all added */
1690 devpriv->ai_n_realscanlen = /*
1691 * what we must take from card in real
1692 * to have ai_n_scanlen on output?
1694 (devpriv->ai_add_front + devpriv->ai_n_chan +
1695 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1696 devpriv->ai_n_chan);
1698 /* check and setup channel list */
1699 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1700 devpriv->ai_chanlist, devpriv->ai_add_front,
1701 devpriv->ai_add_back))
1703 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1704 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1705 devpriv->ai_add_back, devpriv->usedma,
1706 devpriv->useeoshandle))
1709 /* compute timers settings */
1711 * simplest way, fr=4Mhz/(tim1*tim2),
1712 * channel manipulation without timers effect
1714 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1715 (cmd->scan_begin_src == TRIG_EXT) ||
1716 (cmd->scan_begin_src == TRIG_INT)) &&
1717 (cmd->convert_src == TRIG_TIMER)) {
1718 /* both timer is used for one time */
1719 if (cmd->scan_begin_src == TRIG_EXT)
1723 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1724 &cmd->scan_begin_arg, &cmd->convert_arg,
1726 devpriv->ai_n_realscanlen,
1727 &devpriv->ai_divisor1,
1728 &devpriv->ai_divisor2, devpriv->usessh,
1729 devpriv->ai_add_front);
1730 devpriv->ai_timer2 = cmd->convert_arg;
1733 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1734 ((cmd->convert_src == TRIG_TIMER) ||
1735 (cmd->convert_src == TRIG_NOW))) {
1736 /* double timed action */
1737 if (!devpriv->usedma) {
1739 "cmd->scan_begin_src=TRIG_TIMER works "
1740 "only with bus mastering!");
1745 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1746 &cmd->scan_begin_arg, &cmd->convert_arg,
1748 devpriv->ai_n_realscanlen,
1749 &devpriv->ai_divisor1,
1750 &devpriv->ai_divisor2, devpriv->usessh,
1751 devpriv->ai_add_front);
1752 devpriv->ai_timer1 = cmd->scan_begin_arg;
1753 devpriv->ai_timer2 = cmd->convert_arg;
1756 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1757 && (cmd->convert_src == TRIG_EXT)) {
1761 start_pacer(dev, -1, 0, 0); /* stop pacer */
1763 devpriv->AdControlReg = 0; /*
1764 * bipolar, S.E., use 8254, stop 8354,
1765 * internal trigger, soft trigger,
1768 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1769 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1771 * positive triggers, no S&H, no burst,
1772 * burst stop, no post trigger,
1773 * no about trigger, trigger stop
1775 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1777 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1778 inl(dev->iobase + PCI9118_ADSTAT); /*
1782 inl(dev->iobase + PCI9118_INTSRC);
1784 devpriv->ai_act_scan = 0;
1785 devpriv->ai_act_dmapos = 0;
1786 s->async->cur_chan = 0;
1787 devpriv->ai_buf_ptr = 0;
1789 if (devpriv->usedma)
1790 ret = pci9118_ai_docmd_dma(dev, s);
1792 ret = pci9118_ai_docmd_sampl(dev, s);
1797 static int pci9118_reset(struct comedi_device *dev)
1799 struct pci9118_private *devpriv = dev->private;
1801 devpriv->IntControlReg = 0;
1802 devpriv->exttrg_users = 0;
1803 inl(dev->iobase + PCI9118_INTCTRL);
1804 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1805 /* disable interrupts source */
1806 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1807 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1808 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
1809 devpriv->AdControlReg = 0;
1810 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1812 * bipolar, S.E., use 8254,
1813 * stop 8354, internal trigger,
1815 * disable INT and DMA
1817 outl(0, dev->iobase + PCI9118_BURST);
1818 outl(1, dev->iobase + PCI9118_SCANMOD);
1819 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1820 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1821 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1823 * positive triggers, no S&H,
1824 * no burst, burst stop,
1830 devpriv->ao_data[0] = 2047;
1831 devpriv->ao_data[1] = 2047;
1832 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
1833 /* reset A/D outs to 0V */
1834 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1835 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
1837 inl(dev->iobase + PCI9118_AD_DATA);
1838 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1839 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1840 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1841 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
1842 devpriv->AdControlReg = 0;
1843 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1845 * bipolar, S.E., use 8254,
1846 * stop 8354, internal trigger,
1848 * disable INT and DMA
1851 devpriv->cnt0_users = 0;
1852 devpriv->exttrg_users = 0;
1857 static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1858 struct comedi_devconfig *it)
1860 const struct boardtype *this_board = comedi_board(dev);
1861 struct pci_dev *pcidev = NULL;
1862 int bus = it->options[0];
1863 int slot = it->options[1];
1865 for_each_pci_dev(pcidev) {
1866 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1868 if (pcidev->device != this_board->device_id)
1871 /* requested particular bus/slot */
1872 if (pcidev->bus->number != bus ||
1873 PCI_SLOT(pcidev->devfn) != slot)
1877 * Look for device that isn't in use.
1878 * Enable PCI device and request regions.
1880 if (comedi_pci_enable(pcidev, "adl_pci9118"))
1884 dev_err(dev->class_dev,
1885 "no supported board found! (req. bus/slot : %d/%d)\n",
1890 static void pci9118_report_attach(struct comedi_device *dev, unsigned int irq)
1892 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1893 struct pci9118_private *devpriv = dev->private;
1898 snprintf(irqbuf, sizeof(irqbuf), "irq %u%s", irq,
1899 (dev->irq ? "" : " UNAVAILABLE"));
1901 snprintf(irqbuf, sizeof(irqbuf), "irq DISABLED");
1902 if (devpriv->usemux)
1903 snprintf(muxbuf, sizeof(muxbuf), "ext mux %u chans",
1906 snprintf(muxbuf, sizeof(muxbuf), "no ext mux");
1907 dev_info(dev->class_dev, "%s (pci %s, %s, %sbus master, %s) attached\n",
1908 dev->board_name, pci_name(pcidev), irqbuf,
1909 (devpriv->master ? "" : "no "), muxbuf);
1912 static int pci9118_attach(struct comedi_device *dev,
1913 struct comedi_devconfig *it)
1915 const struct boardtype *this_board = comedi_board(dev);
1916 struct pci9118_private *devpriv;
1917 struct pci_dev *pcidev;
1918 struct comedi_subdevice *s;
1920 unsigned short master;
1924 if (it->options[3] & 1)
1925 master = 0; /* user don't want use bus master */
1929 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1932 dev->private = devpriv;
1934 pcidev = pci9118_find_pci(dev, it);
1937 comedi_set_hw_dev(dev, &pcidev->dev);
1940 pci_set_master(pcidev);
1943 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1944 dev->iobase = pci_resource_start(pcidev, 2);
1946 dev->board_name = this_board->name;
1950 if (it->options[3] & 2)
1951 irq = 0; /* user don't want use IRQ */
1953 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
1954 "ADLink PCI-9118", dev))
1955 dev_warn(dev->class_dev,
1956 "unable to allocate IRQ %u, DISABLING IT\n",
1962 if (master) { /* alloc DMA buffers */
1963 devpriv->dma_doublebuf = 0;
1964 for (i = 0; i < 2; i++) {
1965 for (pages = 4; pages >= 0; pages--) {
1966 devpriv->dmabuf_virt[i] =
1967 (short *)__get_free_pages(GFP_KERNEL,
1969 if (devpriv->dmabuf_virt[i])
1972 if (devpriv->dmabuf_virt[i]) {
1973 devpriv->dmabuf_pages[i] = pages;
1974 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
1975 devpriv->dmabuf_samples[i] =
1976 devpriv->dmabuf_size[i] >> 1;
1977 devpriv->dmabuf_hw[i] =
1978 virt_to_bus((void *)
1979 devpriv->dmabuf_virt[i]);
1982 if (!devpriv->dmabuf_virt[0]) {
1983 dev_warn(dev->class_dev,
1984 "Can't allocate DMA buffer, DMA disabled!\n");
1988 if (devpriv->dmabuf_virt[1])
1989 devpriv->dma_doublebuf = 1;
1993 devpriv->master = master;
1994 devpriv->usemux = 0;
1995 if (it->options[2] > 0) {
1996 devpriv->usemux = it->options[2];
1997 if (devpriv->usemux > 256)
1998 devpriv->usemux = 256; /* max 256 channels! */
1999 if (it->options[4] > 0)
2000 if (devpriv->usemux > 128) {
2001 devpriv->usemux = 128;
2002 /* max 128 channels with softare S&H! */
2006 devpriv->softsshdelay = it->options[4];
2007 if (devpriv->softsshdelay < 0) {
2008 /* select sample&hold signal polarity */
2009 devpriv->softsshdelay = -devpriv->softsshdelay;
2010 devpriv->softsshsample = 0x80;
2011 devpriv->softsshhold = 0x00;
2013 devpriv->softsshsample = 0x00;
2014 devpriv->softsshhold = 0x80;
2017 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
2018 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
2019 /* Enable parity check for parity error */
2021 ret = comedi_alloc_subdevices(dev, 4);
2025 s = &dev->subdevices[0];
2026 dev->read_subdev = s;
2027 s->type = COMEDI_SUBD_AI;
2028 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2029 if (devpriv->usemux)
2030 s->n_chan = devpriv->usemux;
2032 s->n_chan = this_board->n_aichan;
2034 s->maxdata = this_board->ai_maxdata;
2035 s->len_chanlist = this_board->n_aichanlist;
2036 s->range_table = this_board->rangelist_ai;
2037 s->cancel = pci9118_ai_cancel;
2038 s->insn_read = pci9118_insn_read_ai;
2040 s->subdev_flags |= SDF_CMD_READ;
2041 s->do_cmdtest = pci9118_ai_cmdtest;
2042 s->do_cmd = pci9118_ai_cmd;
2043 s->munge = pci9118_ai_munge;
2046 s = &dev->subdevices[1];
2047 s->type = COMEDI_SUBD_AO;
2048 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2049 s->n_chan = this_board->n_aochan;
2050 s->maxdata = this_board->ao_maxdata;
2051 s->len_chanlist = this_board->n_aochan;
2052 s->range_table = this_board->rangelist_ao;
2053 s->insn_write = pci9118_insn_write_ao;
2054 s->insn_read = pci9118_insn_read_ao;
2056 s = &dev->subdevices[2];
2057 s->type = COMEDI_SUBD_DI;
2058 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2061 s->len_chanlist = 4;
2062 s->range_table = &range_digital;
2063 s->io_bits = 0; /* all bits input */
2064 s->insn_bits = pci9118_insn_bits_di;
2066 s = &dev->subdevices[3];
2067 s->type = COMEDI_SUBD_DO;
2068 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2071 s->len_chanlist = 4;
2072 s->range_table = &range_digital;
2073 s->io_bits = 0xf; /* all bits output */
2074 s->insn_bits = pci9118_insn_bits_do;
2077 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2078 devpriv->ai_maskharderr = 0x10a;
2079 /* default measure crash condition */
2080 if (it->options[5]) /* disable some requested */
2081 devpriv->ai_maskharderr &= ~it->options[5];
2083 switch (this_board->ai_maxdata) {
2085 devpriv->ai16bits = 1;
2088 devpriv->ai16bits = 0;
2091 pci9118_report_attach(dev, irq);
2095 static void pci9118_detach(struct comedi_device *dev)
2097 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2098 struct pci9118_private *devpriv = dev->private;
2104 free_irq(dev->irq, dev);
2105 if (devpriv->dmabuf_virt[0])
2106 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2107 devpriv->dmabuf_pages[0]);
2108 if (devpriv->dmabuf_virt[1])
2109 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2110 devpriv->dmabuf_pages[1]);
2114 comedi_pci_disable(pcidev);
2116 pci_dev_put(pcidev);
2120 static const struct boardtype boardtypes[] = {
2122 .name = "pci9118dg",
2123 .vendor_id = PCI_VENDOR_ID_AMCC,
2124 .device_id = 0x80d9,
2125 .iorange_amcc = AMCC_OP_REG_SIZE,
2126 .iorange_9118 = IORANGE_9118,
2130 .n_aichanlist = PCI9118_CHANLEN,
2132 .ai_maxdata = 0x0fff,
2133 .ao_maxdata = 0x0fff,
2134 .rangelist_ai = &range_pci9118dg_hr,
2135 .rangelist_ao = &range_bipolar10,
2138 .half_fifo_size = 512,
2140 .name = "pci9118hg",
2141 .vendor_id = PCI_VENDOR_ID_AMCC,
2142 .device_id = 0x80d9,
2143 .iorange_amcc = AMCC_OP_REG_SIZE,
2144 .iorange_9118 = IORANGE_9118,
2148 .n_aichanlist = PCI9118_CHANLEN,
2150 .ai_maxdata = 0x0fff,
2151 .ao_maxdata = 0x0fff,
2152 .rangelist_ai = &range_pci9118hg,
2153 .rangelist_ao = &range_bipolar10,
2156 .half_fifo_size = 512,
2158 .name = "pci9118hr",
2159 .vendor_id = PCI_VENDOR_ID_AMCC,
2160 .device_id = 0x80d9,
2161 .iorange_amcc = AMCC_OP_REG_SIZE,
2162 .iorange_9118 = IORANGE_9118,
2166 .n_aichanlist = PCI9118_CHANLEN,
2168 .ai_maxdata = 0xffff,
2169 .ao_maxdata = 0x0fff,
2170 .rangelist_ai = &range_pci9118dg_hr,
2171 .rangelist_ao = &range_bipolar10,
2174 .half_fifo_size = 512,
2178 static struct comedi_driver adl_pci9118_driver = {
2179 .driver_name = "adl_pci9118",
2180 .module = THIS_MODULE,
2181 .attach = pci9118_attach,
2182 .detach = pci9118_detach,
2183 .num_names = ARRAY_SIZE(boardtypes),
2184 .board_name = &boardtypes[0].name,
2185 .offset = sizeof(struct boardtype),
2188 static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
2189 const struct pci_device_id *ent)
2191 return comedi_pci_auto_config(dev, &adl_pci9118_driver);
2194 static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
2196 comedi_pci_auto_unconfig(dev);
2199 static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
2200 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2203 MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2205 static struct pci_driver adl_pci9118_pci_driver = {
2206 .name = "adl_pci9118",
2207 .id_table = adl_pci9118_pci_table,
2208 .probe = adl_pci9118_pci_probe,
2209 .remove = __devexit_p(adl_pci9118_pci_remove),
2211 module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
2213 MODULE_AUTHOR("Comedi http://www.comedi.org");
2214 MODULE_DESCRIPTION("Comedi low-level driver");
2215 MODULE_LICENSE("GPL");