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 ("comedi%d: range/channel list is too long for "
361 "actual configuration (%d>%d)!",
362 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
366 if (CR_AREF(chanlist[0]) == AREF_DIFF)
367 differencial = 1; /* all input must be diff */
368 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
369 bipolar = 1; /* all input must be bipolar */
371 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
372 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
375 "Differencial and single ended "
376 "inputs can't be mixtured!");
379 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
382 "Bipolar and unipolar ranges "
383 "can't be mixtured!");
386 if (!devpriv->usemux && differencial &&
387 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
389 "If AREF_DIFF is used then is "
390 "available only first 8 channels!");
398 static int setup_channel_list(struct comedi_device *dev,
399 struct comedi_subdevice *s, int n_chan,
400 unsigned int *chanlist, int rot, int frontadd,
401 int backadd, int usedma, char useeos)
403 struct pci9118_private *devpriv = dev->private;
404 unsigned int i, differencial = 0, bipolar = 0;
405 unsigned int scanquad, gain, ssh = 0x00;
412 if (CR_AREF(chanlist[0]) == AREF_DIFF)
413 differencial = 1; /* all input must be diff */
414 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
415 bipolar = 1; /* all input must be bipolar */
417 /* All is ok, so we can setup channel/range list */
420 devpriv->AdControlReg |= AdControl_UniP;
423 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
428 devpriv->AdControlReg |= AdControl_Diff;
429 /* enable diff inputs */
431 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
432 /* set single ended inputs */
435 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
438 outl(2, dev->iobase + PCI9118_SCANMOD);
439 /* gods know why this sequence! */
440 outl(0, dev->iobase + PCI9118_SCANMOD);
441 outl(1, dev->iobase + PCI9118_SCANMOD);
443 #ifdef PCI9118_PARANOIDCHECK
444 devpriv->chanlistlen = n_chan;
445 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
446 devpriv->chanlist[i] = 0x55aa;
449 if (frontadd) { /* insert channels for S&H */
450 ssh = devpriv->softsshsample;
451 for (i = 0; i < frontadd; i++) {
452 /* store range list to card */
453 scanquad = CR_CHAN(chanlist[0]);
454 /* get channel number; */
455 gain = CR_RANGE(chanlist[0]);
456 /* get gain number */
457 scanquad |= ((gain & 0x03) << 8);
458 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
459 ssh = devpriv->softsshhold;
463 for (i = 0; i < n_chan; i++) { /* store range list to card */
464 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
465 #ifdef PCI9118_PARANOIDCHECK
466 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
468 gain = CR_RANGE(chanlist[i]); /* get gain number */
469 scanquad |= ((gain & 0x03) << 8);
470 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
473 if (backadd) { /* insert channels for fit onto 32bit DMA */
474 for (i = 0; i < backadd; i++) { /* store range list to card */
475 scanquad = CR_CHAN(chanlist[0]);
476 /* get channel number */
477 gain = CR_RANGE(chanlist[0]); /* get gain number */
478 scanquad |= ((gain & 0x03) << 8);
479 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
482 #ifdef PCI9118_PARANOIDCHECK
483 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
484 /* for 32bit operations */
486 for (i = 1; i < n_chan; i++) { /* store range list to card */
487 devpriv->chanlist[(n_chan + i) ^ usedma] =
488 (CR_CHAN(chanlist[i]) & 0xf) << rot;
490 devpriv->chanlist[(2 * n_chan) ^ usedma] =
491 devpriv->chanlist[0 ^ usedma];
492 /* for 32bit operations */
498 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
499 /* udelay(100); important delay, or first sample will be crippled */
501 return 1; /* we can serve this with scan logic */
504 static int pci9118_insn_read_ai(struct comedi_device *dev,
505 struct comedi_subdevice *s,
506 struct comedi_insn *insn, unsigned int *data)
508 struct pci9118_private *devpriv = dev->private;
511 devpriv->AdControlReg = AdControl_Int & 0xff;
512 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
513 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
515 * positive triggers, no S&H,
516 * no burst, burst stop,
522 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
525 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
527 for (n = 0; n < insn->n; n++) {
528 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
532 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
537 comedi_error(dev, "A/D insn timeout");
539 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
543 if (devpriv->ai16bits) {
546 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
549 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
553 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
558 static int pci9118_insn_write_ao(struct comedi_device *dev,
559 struct comedi_subdevice *s,
560 struct comedi_insn *insn, unsigned int *data)
562 struct pci9118_private *devpriv = dev->private;
565 ch = CR_CHAN(insn->chanspec);
567 chanreg = PCI9118_DA2;
569 chanreg = PCI9118_DA1;
572 for (n = 0; n < insn->n; n++) {
573 outl(data[n], dev->iobase + chanreg);
574 devpriv->ao_data[ch] = data[n];
580 static int pci9118_insn_read_ao(struct comedi_device *dev,
581 struct comedi_subdevice *s,
582 struct comedi_insn *insn, unsigned int *data)
584 struct pci9118_private *devpriv = dev->private;
587 chan = CR_CHAN(insn->chanspec);
588 for (n = 0; n < insn->n; n++)
589 data[n] = devpriv->ao_data[chan];
594 static int pci9118_insn_bits_di(struct comedi_device *dev,
595 struct comedi_subdevice *s,
596 struct comedi_insn *insn, unsigned int *data)
598 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
603 static int pci9118_insn_bits_do(struct comedi_device *dev,
604 struct comedi_subdevice *s,
605 struct comedi_insn *insn, unsigned int *data)
608 s->state &= ~data[0];
609 s->state |= (data[0] & data[1]);
610 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
617 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
619 struct pci9118_private *devpriv = dev->private;
621 devpriv->AdFunctionReg =
622 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
623 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
624 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
625 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
626 dev->iobase + PCI9118_CNT0);
627 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
628 dev->iobase + PCI9118_CNT0);
629 devpriv->AdFunctionReg |= AdFunction_Start;
630 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
633 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
634 struct comedi_subdevice *s,
636 unsigned int num_samples)
638 struct pci9118_private *devpriv = dev->private;
639 unsigned int i = 0, j = 0;
640 unsigned int start_pos = devpriv->ai_add_front,
641 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
642 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
643 devpriv->ai_add_back;
645 for (i = 0; i < num_samples; i++) {
646 if (devpriv->ai_act_dmapos >= start_pos &&
647 devpriv->ai_act_dmapos < stop_pos) {
648 dma_buffer[j++] = dma_buffer[i];
650 devpriv->ai_act_dmapos++;
651 devpriv->ai_act_dmapos %= raw_scanlen;
657 static int move_block_from_dma(struct comedi_device *dev,
658 struct comedi_subdevice *s,
660 unsigned int num_samples)
662 struct pci9118_private *devpriv = dev->private;
663 unsigned int num_bytes;
665 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
666 devpriv->ai_act_scan +=
667 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
668 s->async->cur_chan += num_samples;
669 s->async->cur_chan %= devpriv->ai_n_scanlen;
671 cfc_write_array_to_buffer(s, dma_buffer,
672 num_samples * sizeof(short));
673 if (num_bytes < num_samples * sizeof(short))
678 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
680 struct pci9118_private *devpriv = dev->private;
683 return -1; /* incorrect source */
684 devpriv->exttrg_users |= (1 << source);
685 devpriv->IntControlReg |= Int_DTrg;
686 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
687 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
688 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
689 /* allow INT in AMCC */
693 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
695 struct pci9118_private *devpriv = dev->private;
698 return -1; /* incorrect source */
699 devpriv->exttrg_users &= ~(1 << source);
700 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
701 devpriv->IntControlReg &= ~Int_DTrg;
702 if (!devpriv->IntControlReg) /* all IRQ disabled */
703 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
705 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
706 /* disable int in AMCC */
707 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
712 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
713 struct comedi_subdevice *s,
714 unsigned int *tim1, unsigned int *tim2,
715 unsigned int flags, int chans,
716 unsigned int *div1, unsigned int *div2,
717 char usessh, unsigned int chnsshfront)
719 const struct boardtype *this_board = comedi_board(dev);
720 struct pci9118_private *devpriv = dev->private;
725 if (*tim2 < this_board->ai_ns_min)
726 *tim2 = this_board->ai_ns_min;
727 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
728 tim2, flags & TRIG_ROUND_NEAREST);
731 if (*tim2 < this_board->ai_ns_min)
732 *tim2 = this_board->ai_ns_min;
733 *div1 = *tim2 / devpriv->i8254_osc_base;
734 /* convert timer (burst) */
735 if (*div1 < this_board->ai_pacer_min)
736 *div1 = this_board->ai_pacer_min;
737 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
738 *div2 = *div2 / *div1; /* major timer is c1*c2 */
742 *tim2 = *div1 * devpriv->i8254_osc_base;
743 /* real convert timer */
745 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
746 if (*div2 < (chans + 2))
749 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
754 static void start_pacer(struct comedi_device *dev, int mode,
755 unsigned int divisor1, unsigned int divisor2)
757 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
758 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
759 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
762 if ((mode == 1) || (mode == 2) || (mode == 4)) {
763 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
764 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
765 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
766 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
770 static int pci9118_ai_cancel(struct comedi_device *dev,
771 struct comedi_subdevice *s)
773 struct pci9118_private *devpriv = dev->private;
776 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
778 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
779 pci9118_exttrg_del(dev, EXTTRG_AI);
780 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
781 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
782 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
784 * positive triggers, no S&H, no burst,
785 * burst stop, no post trigger,
786 * no about trigger, trigger stop
788 devpriv->AdControlReg = 0x00;
789 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
791 * bipolar, S.E., use 8254, stop 8354,
792 * internal trigger, soft trigger,
793 * disable INT and DMA
795 outl(0, dev->iobase + PCI9118_BURST);
796 outl(1, dev->iobase + PCI9118_SCANMOD);
797 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
798 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
803 devpriv->ai_act_scan = 0;
804 devpriv->ai_act_dmapos = 0;
805 s->async->cur_chan = 0;
806 s->async->inttrig = NULL;
807 devpriv->ai_buf_ptr = 0;
808 devpriv->ai_neverending = 0;
809 devpriv->dma_actbuf = 0;
811 if (!devpriv->IntControlReg)
812 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
813 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
814 /* allow INT in AMCC */
819 static char pci9118_decode_error_status(struct comedi_device *dev,
820 struct comedi_subdevice *s,
823 struct pci9118_private *devpriv = dev->private;
826 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
827 devpriv->ai_maskerr &= ~0x100L;
831 "A/D Burst Mode Overrun Status (Fatal Error!)");
832 devpriv->ai_maskerr &= ~0x008L;
835 comedi_error(dev, "A/D Over Speed Status (Warning!)");
836 devpriv->ai_maskerr &= ~0x004L;
839 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
840 devpriv->ai_maskerr &= ~0x002L;
842 if (m & devpriv->ai_maskharderr) {
843 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
844 pci9118_ai_cancel(dev, s);
845 comedi_event(dev, s);
852 static void pci9118_ai_munge(struct comedi_device *dev,
853 struct comedi_subdevice *s, void *data,
854 unsigned int num_bytes,
855 unsigned int start_chan_index)
857 struct pci9118_private *devpriv = dev->private;
858 unsigned int i, num_samples = num_bytes / sizeof(short);
861 for (i = 0; i < num_samples; i++) {
863 array[i] = be16_to_cpu(array[i]);
864 if (devpriv->ai16bits)
867 array[i] = (array[i] >> 4) & 0x0fff;
872 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
873 struct comedi_subdevice *s,
874 unsigned short int_adstat,
875 unsigned int int_amcc,
876 unsigned short int_daq)
878 struct pci9118_private *devpriv = dev->private;
879 register short sampl;
881 s->async->events = 0;
883 if (int_adstat & devpriv->ai_maskerr)
884 if (pci9118_decode_error_status(dev, s, int_adstat))
887 sampl = inw(dev->iobase + PCI9118_AD_DATA);
889 #ifdef PCI9118_PARANOIDCHECK
890 if (devpriv->ai16bits == 0) {
891 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
894 ("comedi: A/D SAMPL - data dropout: "
895 "received channel %d, expected %d!\n",
897 devpriv->chanlist[s->async->cur_chan]);
898 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
899 pci9118_ai_cancel(dev, s);
900 comedi_event(dev, s);
905 cfc_write_to_buffer(s, sampl);
906 s->async->cur_chan++;
907 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
909 s->async->cur_chan %= devpriv->ai_n_scanlen;
910 devpriv->ai_act_scan++;
911 if (!(devpriv->ai_neverending))
912 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
913 /* all data sampled */
914 pci9118_ai_cancel(dev, s);
915 s->async->events |= COMEDI_CB_EOA;
919 if (s->async->events)
920 comedi_event(dev, s);
923 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
924 struct comedi_subdevice *s,
925 unsigned short int_adstat,
926 unsigned int int_amcc,
927 unsigned short int_daq)
929 struct pci9118_private *devpriv = dev->private;
930 unsigned int next_dma_buf, samplesinbuf, sampls, m;
932 if (int_amcc & MASTER_ABORT_INT) {
933 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
934 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
935 pci9118_ai_cancel(dev, s);
936 comedi_event(dev, s);
940 if (int_amcc & TARGET_ABORT_INT) {
941 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
942 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
943 pci9118_ai_cancel(dev, s);
944 comedi_event(dev, s);
947 if (int_adstat & devpriv->ai_maskerr)
948 /* if (int_adstat & 0x106) */
949 if (pci9118_decode_error_status(dev, s, int_adstat))
952 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
953 /* number of received real samples */
955 if (devpriv->dma_doublebuf) { /*
956 * switch DMA buffers if is used
959 next_dma_buf = 1 - devpriv->dma_actbuf;
960 outl(devpriv->dmabuf_hw[next_dma_buf],
961 devpriv->iobase_a + AMCC_OP_REG_MWAR);
962 outl(devpriv->dmabuf_use_size[next_dma_buf],
963 devpriv->iobase_a + AMCC_OP_REG_MWTC);
964 devpriv->dmabuf_used_size[next_dma_buf] =
965 devpriv->dmabuf_use_size[next_dma_buf];
966 if (devpriv->ai_do == 4)
967 interrupt_pci9118_ai_mode4_switch(dev);
971 m = devpriv->ai_data_len >> 1; /*
972 * how many samples is to
976 move_block_from_dma(dev, s,
977 devpriv->dmabuf_virt[devpriv->dma_actbuf],
979 m = m - sampls; /* m= how many samples was transferred */
982 if (!devpriv->ai_neverending)
983 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
984 /* all data sampled */
985 pci9118_ai_cancel(dev, s);
986 s->async->events |= COMEDI_CB_EOA;
989 if (devpriv->dma_doublebuf) { /* switch dma buffers */
990 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
991 } else { /* restart DMA if is not used double buffering */
992 outl(devpriv->dmabuf_hw[0],
993 devpriv->iobase_a + AMCC_OP_REG_MWAR);
994 outl(devpriv->dmabuf_use_size[0],
995 devpriv->iobase_a + AMCC_OP_REG_MWTC);
996 if (devpriv->ai_do == 4)
997 interrupt_pci9118_ai_mode4_switch(dev);
1000 comedi_event(dev, s);
1003 static irqreturn_t interrupt_pci9118(int irq, void *d)
1005 struct comedi_device *dev = d;
1006 struct pci9118_private *devpriv = dev->private;
1007 unsigned int int_daq = 0, int_amcc, int_adstat;
1010 return IRQ_NONE; /* not fully initialized */
1012 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
1013 /* get IRQ reasons from card */
1014 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1015 /* get INT register from AMCC chip */
1017 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
1018 return IRQ_NONE; /* interrupt from other source */
1020 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1021 /* shutdown IRQ reasons in AMCC */
1023 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
1024 /* get STATUS register */
1026 if (devpriv->ai_do) {
1027 if (devpriv->ai12_startstop)
1028 if ((int_adstat & AdStatus_DTH) &&
1029 (int_daq & Int_DTrg)) {
1030 /* start stop of measure */
1031 if (devpriv->ai12_startstop & START_AI_EXT) {
1032 devpriv->ai12_startstop &=
1034 if (!(devpriv->ai12_startstop &
1038 /* deactivate EXT trigger */
1039 start_pacer(dev, devpriv->ai_do,
1040 devpriv->ai_divisor1,
1041 devpriv->ai_divisor2);
1043 outl(devpriv->AdControlReg,
1044 dev->iobase + PCI9118_ADCNTRL);
1046 if (devpriv->ai12_startstop &
1048 devpriv->ai12_startstop &=
1052 /* deactivate EXT trigger */
1053 devpriv->ai_neverending = 0;
1055 * well, on next interrupt from
1056 * DMA/EOC measure will stop
1062 (devpriv->int_ai_func) (dev, &dev->subdevices[0], int_adstat,
1069 static int pci9118_ai_inttrig(struct comedi_device *dev,
1070 struct comedi_subdevice *s, unsigned int trignum)
1072 struct pci9118_private *devpriv = dev->private;
1074 if (trignum != devpriv->ai_inttrig_start)
1077 devpriv->ai12_startstop &= ~START_AI_INT;
1078 s->async->inttrig = NULL;
1080 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1081 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1082 if (devpriv->ai_do != 3) {
1083 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1084 devpriv->ai_divisor2);
1085 devpriv->AdControlReg |= AdControl_SoftG;
1087 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1092 static int pci9118_ai_cmdtest(struct comedi_device *dev,
1093 struct comedi_subdevice *s,
1094 struct comedi_cmd *cmd)
1096 const struct boardtype *this_board = comedi_board(dev);
1097 struct pci9118_private *devpriv = dev->private;
1101 unsigned int divisor1 = 0, divisor2 = 0;
1103 /* Step 1 : check if triggers are trivially valid */
1105 err |= cfc_check_trigger_src(&cmd->start_src,
1106 TRIG_NOW | TRIG_EXT | TRIG_INT);
1108 flags = TRIG_FOLLOW;
1109 if (devpriv->master)
1110 flags |= TRIG_TIMER | TRIG_EXT;
1111 err |= cfc_check_trigger_src(&cmd->scan_begin_src, flags);
1113 flags = TRIG_TIMER | TRIG_EXT;
1114 if (devpriv->master)
1116 err |= cfc_check_trigger_src(&cmd->convert_src, flags);
1118 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1119 err |= cfc_check_trigger_src(&cmd->stop_src,
1120 TRIG_COUNT | TRIG_NONE | TRIG_EXT);
1125 /* Step 2a : make sure trigger sources are unique */
1127 err |= cfc_check_trigger_is_unique(cmd->start_src);
1128 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
1129 err |= cfc_check_trigger_is_unique(cmd->convert_src);
1130 err |= cfc_check_trigger_is_unique(cmd->stop_src);
1132 /* Step 2b : and mutually compatible */
1134 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1137 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT)
1140 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1141 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW))))
1144 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1145 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT))))
1148 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT)
1154 /* step 3: make sure arguments are trivially compatible */
1156 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1157 if (cmd->start_arg != 0) {
1162 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1163 if (cmd->scan_begin_arg != 0) {
1164 cmd->scan_begin_arg = 0;
1168 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1169 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1170 cmd->scan_begin_src = TRIG_FOLLOW;
1171 cmd->convert_arg = cmd->scan_begin_arg;
1172 cmd->scan_begin_arg = 0;
1175 if (cmd->scan_begin_src == TRIG_TIMER)
1176 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1177 cmd->scan_begin_arg = this_board->ai_ns_min;
1181 if (cmd->scan_begin_src == TRIG_EXT)
1182 if (cmd->scan_begin_arg) {
1183 cmd->scan_begin_arg = 0;
1185 if (cmd->scan_end_arg > 65535) {
1186 cmd->scan_end_arg = 65535;
1191 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1192 if (cmd->convert_arg < this_board->ai_ns_min) {
1193 cmd->convert_arg = this_board->ai_ns_min;
1197 if (cmd->convert_src == TRIG_EXT)
1198 if (cmd->convert_arg) {
1199 cmd->convert_arg = 0;
1203 if (cmd->stop_src == TRIG_COUNT) {
1204 if (!cmd->stop_arg) {
1208 } else { /* TRIG_NONE */
1209 if (cmd->stop_arg != 0) {
1215 if (!cmd->chanlist_len) {
1216 cmd->chanlist_len = 1;
1220 if (cmd->chanlist_len > this_board->n_aichanlist) {
1221 cmd->chanlist_len = this_board->n_aichanlist;
1225 if (cmd->scan_end_arg < cmd->chanlist_len) {
1226 cmd->scan_end_arg = cmd->chanlist_len;
1230 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1232 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1239 /* step 4: fix up any arguments */
1241 if (cmd->scan_begin_src == TRIG_TIMER) {
1242 tmp = cmd->scan_begin_arg;
1243 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1244 &divisor2, &cmd->scan_begin_arg,
1245 cmd->flags & TRIG_ROUND_MASK);
1246 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1247 cmd->scan_begin_arg = this_board->ai_ns_min;
1248 if (tmp != cmd->scan_begin_arg)
1252 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1253 tmp = cmd->convert_arg;
1254 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1255 &divisor2, &cmd->convert_arg,
1256 cmd->flags & TRIG_ROUND_MASK);
1257 if (cmd->convert_arg < this_board->ai_ns_min)
1258 cmd->convert_arg = this_board->ai_ns_min;
1259 if (tmp != cmd->convert_arg)
1261 if (cmd->scan_begin_src == TRIG_TIMER
1262 && cmd->convert_src == TRIG_NOW) {
1263 if (cmd->convert_arg == 0) {
1264 if (cmd->scan_begin_arg <
1265 this_board->ai_ns_min *
1266 (cmd->scan_end_arg + 2)) {
1267 cmd->scan_begin_arg =
1268 this_board->ai_ns_min *
1269 (cmd->scan_end_arg + 2);
1273 if (cmd->scan_begin_arg <
1274 cmd->convert_arg * cmd->chanlist_len) {
1275 cmd->scan_begin_arg =
1288 if (!check_channel_list(dev, s, cmd->chanlist_len,
1289 cmd->chanlist, 0, 0))
1290 return 5; /* incorrect channels list */
1295 static int Compute_and_setup_dma(struct comedi_device *dev)
1297 struct pci9118_private *devpriv = dev->private;
1298 unsigned int dmalen0, dmalen1, i;
1300 dmalen0 = devpriv->dmabuf_size[0];
1301 dmalen1 = devpriv->dmabuf_size[1];
1302 /* isn't output buff smaller that our DMA buff? */
1303 if (dmalen0 > (devpriv->ai_data_len)) {
1304 dmalen0 = devpriv->ai_data_len & ~3L; /*
1305 * align to 32bit down
1308 if (dmalen1 > (devpriv->ai_data_len)) {
1309 dmalen1 = devpriv->ai_data_len & ~3L; /*
1310 * align to 32bit down
1314 /* we want wake up every scan? */
1315 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1316 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1317 /* uff, too short DMA buffer, disable EOS support! */
1318 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1320 ("comedi%d: WAR: DMA0 buf too short, can't "
1321 "support TRIG_WAKE_EOS (%d<%d)\n",
1322 dev->minor, dmalen0,
1323 devpriv->ai_n_realscanlen << 1);
1325 /* short first DMA buffer to one scan */
1326 dmalen0 = devpriv->ai_n_realscanlen << 1;
1327 if (devpriv->useeoshandle)
1331 ("comedi%d: ERR: DMA0 buf len bug? "
1333 dev->minor, dmalen0);
1338 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1339 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1340 /* uff, too short DMA buffer, disable EOS support! */
1341 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1343 ("comedi%d: WAR: DMA1 buf too short, "
1344 "can't support TRIG_WAKE_EOS (%d<%d)\n",
1345 dev->minor, dmalen1,
1346 devpriv->ai_n_realscanlen << 1);
1348 /* short second DMA buffer to one scan */
1349 dmalen1 = devpriv->ai_n_realscanlen << 1;
1350 if (devpriv->useeoshandle)
1354 ("comedi%d: ERR: DMA1 buf len bug? "
1356 dev->minor, dmalen1);
1362 /* transfer without TRIG_WAKE_EOS */
1363 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1364 /* if it's possible then align DMA buffers to length of scan */
1367 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1368 (devpriv->ai_n_realscanlen << 1);
1371 dmalen0 = i; /* uff. very long scan? */
1374 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1375 (devpriv->ai_n_realscanlen << 1);
1378 dmalen1 = i; /* uff. very long scan? */
1380 * if measure isn't neverending then test, if it fits whole
1381 * into one or two DMA buffers
1383 if (!devpriv->ai_neverending) {
1384 /* fits whole measure into one DMA buffer? */
1386 ((devpriv->ai_n_realscanlen << 1) *
1387 devpriv->ai_scans)) {
1389 (devpriv->ai_n_realscanlen << 1) *
1393 * fits whole measure into
1397 ((devpriv->ai_n_realscanlen << 1) *
1398 devpriv->ai_scans - dmalen0))
1400 (devpriv->ai_n_realscanlen << 1) *
1401 devpriv->ai_scans - dmalen0;
1407 /* these DMA buffer size will be used */
1408 devpriv->dma_actbuf = 0;
1409 devpriv->dmabuf_use_size[0] = dmalen0;
1410 devpriv->dmabuf_use_size[1] = dmalen1;
1413 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1414 devpriv->dmabuf_panic_size[0] =
1415 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1416 1) * devpriv->ai_n_scanlen * sizeof(short);
1417 devpriv->dmabuf_panic_size[1] =
1418 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1419 1) * devpriv->ai_n_scanlen * sizeof(short);
1421 devpriv->dmabuf_panic_size[0] =
1422 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1423 devpriv->dmabuf_panic_size[1] =
1424 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1428 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1429 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1430 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1431 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1432 /* init DMA transfer */
1433 outl(0x00000000 | AINT_WRITE_COMPL,
1434 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1435 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1437 outl(inl(devpriv->iobase_a +
1438 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1439 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1440 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1441 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1442 /* allow bus mastering */
1447 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1448 struct comedi_subdevice *s)
1450 struct pci9118_private *devpriv = dev->private;
1452 switch (devpriv->ai_do) {
1454 devpriv->AdControlReg |= AdControl_TmrTr;
1457 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1460 devpriv->AdControlReg |= AdControl_ExtM;
1463 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1467 "pci9118_ai_docmd_sampl() mode number bug!\n");
1471 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1472 /* transfer function */
1474 if (devpriv->ai12_startstop)
1475 pci9118_exttrg_add(dev, EXTTRG_AI);
1476 /* activate EXT trigger */
1478 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1479 devpriv->IntControlReg |= Int_Timer;
1481 devpriv->AdControlReg |= AdControl_Int;
1483 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1484 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1485 /* allow INT in AMCC */
1487 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1488 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1489 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1490 if (devpriv->ai_do != 3) {
1491 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1492 devpriv->ai_divisor2);
1493 devpriv->AdControlReg |= AdControl_SoftG;
1495 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1501 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1502 struct comedi_subdevice *s)
1504 struct pci9118_private *devpriv = dev->private;
1506 Compute_and_setup_dma(dev);
1508 switch (devpriv->ai_do) {
1510 devpriv->AdControlReg |=
1511 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1514 devpriv->AdControlReg |=
1515 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1516 devpriv->AdFunctionReg =
1517 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1519 if (devpriv->usessh && (!devpriv->softsshdelay))
1520 devpriv->AdFunctionReg |= AdFunction_BSSH;
1521 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1524 devpriv->AdControlReg |=
1525 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1526 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1529 devpriv->AdControlReg |=
1530 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1531 devpriv->AdFunctionReg =
1532 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1533 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1534 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1535 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1536 dev->iobase + PCI9118_CNT0);
1537 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1538 dev->iobase + PCI9118_CNT0);
1539 devpriv->AdFunctionReg |= AdFunction_Start;
1542 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1546 if (devpriv->ai12_startstop) {
1547 pci9118_exttrg_add(dev, EXTTRG_AI);
1548 /* activate EXT trigger */
1551 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1552 /* transfer function */
1554 outl(0x02000000 | AINT_WRITE_COMPL,
1555 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1557 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1558 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1559 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1560 if (devpriv->ai_do != 3) {
1561 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1562 devpriv->ai_divisor2);
1563 devpriv->AdControlReg |= AdControl_SoftG;
1565 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1571 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1573 const struct boardtype *this_board = comedi_board(dev);
1574 struct pci9118_private *devpriv = dev->private;
1575 struct comedi_cmd *cmd = &s->async->cmd;
1576 unsigned int addchans = 0;
1579 devpriv->ai12_startstop = 0;
1580 devpriv->ai_flags = cmd->flags;
1581 devpriv->ai_n_chan = cmd->chanlist_len;
1582 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1583 devpriv->ai_chanlist = cmd->chanlist;
1584 devpriv->ai_data = s->async->prealloc_buf;
1585 devpriv->ai_data_len = s->async->prealloc_bufsz;
1586 devpriv->ai_timer1 = 0;
1587 devpriv->ai_timer2 = 0;
1588 devpriv->ai_add_front = 0;
1589 devpriv->ai_add_back = 0;
1590 devpriv->ai_maskerr = 0x10e;
1592 /* prepare for start/stop conditions */
1593 if (cmd->start_src == TRIG_EXT)
1594 devpriv->ai12_startstop |= START_AI_EXT;
1595 if (cmd->stop_src == TRIG_EXT) {
1596 devpriv->ai_neverending = 1;
1597 devpriv->ai12_startstop |= STOP_AI_EXT;
1599 if (cmd->start_src == TRIG_INT) {
1600 devpriv->ai12_startstop |= START_AI_INT;
1601 devpriv->ai_inttrig_start = cmd->start_arg;
1602 s->async->inttrig = pci9118_ai_inttrig;
1605 if (cmd->stop_src == TRIG_INT) {
1606 devpriv->ai_neverending = 1;
1607 devpriv->ai12_startstop |= STOP_AI_INT;
1610 if (cmd->stop_src == TRIG_NONE)
1611 devpriv->ai_neverending = 1;
1612 if (cmd->stop_src == TRIG_COUNT) {
1613 devpriv->ai_scans = cmd->stop_arg;
1614 devpriv->ai_neverending = 0;
1616 devpriv->ai_scans = 0;
1619 /* use sample&hold signal? */
1620 if (cmd->convert_src == TRIG_NOW)
1621 devpriv->usessh = 1;
1624 devpriv->usessh = 0;
1628 * use additional sample at end of every scan
1629 * to satisty DMA 32 bit transfer?
1631 devpriv->ai_add_front = 0;
1632 devpriv->ai_add_back = 0;
1633 devpriv->useeoshandle = 0;
1634 if (devpriv->master) {
1635 devpriv->usedma = 1;
1636 if ((cmd->flags & TRIG_WAKE_EOS) &&
1637 (devpriv->ai_n_scanlen == 1)) {
1638 if (cmd->convert_src == TRIG_NOW)
1639 devpriv->ai_add_back = 1;
1640 if (cmd->convert_src == TRIG_TIMER) {
1641 devpriv->usedma = 0;
1643 * use INT transfer if scanlist
1644 * have only one channel
1648 if ((cmd->flags & TRIG_WAKE_EOS) &&
1649 (devpriv->ai_n_scanlen & 1) &&
1650 (devpriv->ai_n_scanlen > 1)) {
1651 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1653 * vpriv->useeoshandle=1; // change DMA transfer
1654 * block to fit EOS on every second call
1656 devpriv->usedma = 0;
1658 * XXX maybe can be corrected to use 16 bit DMA
1661 * well, we must insert one sample
1662 * to end of EOS to meet 32 bit transfer
1664 devpriv->ai_add_back = 1;
1667 } else { /* interrupt transfer don't need any correction */
1668 devpriv->usedma = 0;
1672 * we need software S&H signal?
1673 * It adds two samples before every scan as minimum
1675 if (devpriv->usessh && devpriv->softsshdelay) {
1676 devpriv->ai_add_front = 2;
1677 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1678 /* move it to front */
1679 devpriv->ai_add_front++;
1680 devpriv->ai_add_back = 0;
1682 if (cmd->convert_arg < this_board->ai_ns_min)
1683 cmd->convert_arg = this_board->ai_ns_min;
1684 addchans = devpriv->softsshdelay / cmd->convert_arg;
1685 if (devpriv->softsshdelay % cmd->convert_arg)
1687 if (addchans > (devpriv->ai_add_front - 1)) {
1688 /* uff, still short */
1689 devpriv->ai_add_front = addchans + 1;
1690 if (devpriv->usedma == 1)
1691 if ((devpriv->ai_add_front +
1692 devpriv->ai_n_chan +
1693 devpriv->ai_add_back) & 1)
1694 devpriv->ai_add_front++;
1695 /* round up to 32 bit */
1698 /* well, we now know what must be all added */
1699 devpriv->ai_n_realscanlen = /*
1700 * what we must take from card in real
1701 * to have ai_n_scanlen on output?
1703 (devpriv->ai_add_front + devpriv->ai_n_chan +
1704 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1705 devpriv->ai_n_chan);
1707 /* check and setup channel list */
1708 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1709 devpriv->ai_chanlist, devpriv->ai_add_front,
1710 devpriv->ai_add_back))
1712 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1713 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1714 devpriv->ai_add_back, devpriv->usedma,
1715 devpriv->useeoshandle))
1718 /* compute timers settings */
1720 * simplest way, fr=4Mhz/(tim1*tim2),
1721 * channel manipulation without timers effect
1723 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1724 (cmd->scan_begin_src == TRIG_EXT) ||
1725 (cmd->scan_begin_src == TRIG_INT)) &&
1726 (cmd->convert_src == TRIG_TIMER)) {
1727 /* both timer is used for one time */
1728 if (cmd->scan_begin_src == TRIG_EXT)
1732 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1733 &cmd->scan_begin_arg, &cmd->convert_arg,
1735 devpriv->ai_n_realscanlen,
1736 &devpriv->ai_divisor1,
1737 &devpriv->ai_divisor2, devpriv->usessh,
1738 devpriv->ai_add_front);
1739 devpriv->ai_timer2 = cmd->convert_arg;
1742 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1743 ((cmd->convert_src == TRIG_TIMER) ||
1744 (cmd->convert_src == TRIG_NOW))) {
1745 /* double timed action */
1746 if (!devpriv->usedma) {
1748 "cmd->scan_begin_src=TRIG_TIMER works "
1749 "only with bus mastering!");
1754 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1755 &cmd->scan_begin_arg, &cmd->convert_arg,
1757 devpriv->ai_n_realscanlen,
1758 &devpriv->ai_divisor1,
1759 &devpriv->ai_divisor2, devpriv->usessh,
1760 devpriv->ai_add_front);
1761 devpriv->ai_timer1 = cmd->scan_begin_arg;
1762 devpriv->ai_timer2 = cmd->convert_arg;
1765 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1766 && (cmd->convert_src == TRIG_EXT)) {
1770 start_pacer(dev, -1, 0, 0); /* stop pacer */
1772 devpriv->AdControlReg = 0; /*
1773 * bipolar, S.E., use 8254, stop 8354,
1774 * internal trigger, soft trigger,
1777 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1778 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1780 * positive triggers, no S&H, no burst,
1781 * burst stop, no post trigger,
1782 * no about trigger, trigger stop
1784 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1786 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1787 inl(dev->iobase + PCI9118_ADSTAT); /*
1791 inl(dev->iobase + PCI9118_INTSRC);
1793 devpriv->ai_act_scan = 0;
1794 devpriv->ai_act_dmapos = 0;
1795 s->async->cur_chan = 0;
1796 devpriv->ai_buf_ptr = 0;
1798 if (devpriv->usedma)
1799 ret = pci9118_ai_docmd_dma(dev, s);
1801 ret = pci9118_ai_docmd_sampl(dev, s);
1806 static int pci9118_reset(struct comedi_device *dev)
1808 struct pci9118_private *devpriv = dev->private;
1810 devpriv->IntControlReg = 0;
1811 devpriv->exttrg_users = 0;
1812 inl(dev->iobase + PCI9118_INTCTRL);
1813 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1814 /* disable interrupts source */
1815 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1816 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1817 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
1818 devpriv->AdControlReg = 0;
1819 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1821 * bipolar, S.E., use 8254,
1822 * stop 8354, internal trigger,
1824 * disable INT and DMA
1826 outl(0, dev->iobase + PCI9118_BURST);
1827 outl(1, dev->iobase + PCI9118_SCANMOD);
1828 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1829 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1830 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1832 * positive triggers, no S&H,
1833 * no burst, burst stop,
1839 devpriv->ao_data[0] = 2047;
1840 devpriv->ao_data[1] = 2047;
1841 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
1842 /* reset A/D outs to 0V */
1843 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1844 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
1846 inl(dev->iobase + PCI9118_AD_DATA);
1847 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1848 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1849 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1850 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
1851 devpriv->AdControlReg = 0;
1852 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1854 * bipolar, S.E., use 8254,
1855 * stop 8354, internal trigger,
1857 * disable INT and DMA
1860 devpriv->cnt0_users = 0;
1861 devpriv->exttrg_users = 0;
1866 static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
1867 struct comedi_devconfig *it)
1869 const struct boardtype *this_board = comedi_board(dev);
1870 struct pci_dev *pcidev = NULL;
1871 int bus = it->options[0];
1872 int slot = it->options[1];
1874 for_each_pci_dev(pcidev) {
1875 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
1877 if (pcidev->device != this_board->device_id)
1880 /* requested particular bus/slot */
1881 if (pcidev->bus->number != bus ||
1882 PCI_SLOT(pcidev->devfn) != slot)
1886 * Look for device that isn't in use.
1887 * Enable PCI device and request regions.
1889 if (comedi_pci_enable(pcidev, "adl_pci9118"))
1891 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx",
1892 pcidev->bus->number,
1893 PCI_SLOT(pcidev->devfn),
1894 PCI_FUNC(pcidev->devfn),
1895 (unsigned long)pci_resource_start(pcidev, 2),
1896 (unsigned long)pci_resource_start(pcidev, 0));
1900 "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
1901 dev->minor, bus, slot);
1905 static int pci9118_attach(struct comedi_device *dev,
1906 struct comedi_devconfig *it)
1908 const struct boardtype *this_board = comedi_board(dev);
1909 struct pci9118_private *devpriv;
1910 struct pci_dev *pcidev;
1911 struct comedi_subdevice *s;
1913 unsigned short master;
1917 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
1919 if (it->options[3] & 1)
1920 master = 0; /* user don't want use bus master */
1924 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1927 dev->private = devpriv;
1929 pcidev = pci9118_find_pci(dev, it);
1932 comedi_set_hw_dev(dev, &pcidev->dev);
1935 pci_set_master(pcidev);
1938 devpriv->iobase_a = pci_resource_start(pcidev, 0);
1939 dev->iobase = pci_resource_start(pcidev, 2);
1941 dev->board_name = this_board->name;
1945 if (it->options[3] & 2)
1946 irq = 0; /* user don't want use IRQ */
1948 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
1949 "ADLink PCI-9118", dev)) {
1950 printk(", unable to allocate IRQ %d, DISABLING IT",
1952 irq = 0; /* Can't use IRQ */
1954 printk(", irq=%u", irq);
1957 printk(", IRQ disabled");
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 printk(", Can't allocate DMA buffer, DMA disabled!");
1987 if (devpriv->dmabuf_virt[1])
1988 devpriv->dma_doublebuf = 1;
1992 devpriv->master = master;
1993 if (devpriv->master)
1994 printk(", bus master");
1996 printk(", no bus master");
1998 devpriv->usemux = 0;
1999 if (it->options[2] > 0) {
2000 devpriv->usemux = it->options[2];
2001 if (devpriv->usemux > 256)
2002 devpriv->usemux = 256; /* max 256 channels! */
2003 if (it->options[4] > 0)
2004 if (devpriv->usemux > 128) {
2005 devpriv->usemux = 128;
2006 /* max 128 channels with softare S&H! */
2008 printk(", ext. mux %d channels", devpriv->usemux);
2011 devpriv->softsshdelay = it->options[4];
2012 if (devpriv->softsshdelay < 0) {
2013 /* select sample&hold signal polarity */
2014 devpriv->softsshdelay = -devpriv->softsshdelay;
2015 devpriv->softsshsample = 0x80;
2016 devpriv->softsshhold = 0x00;
2018 devpriv->softsshsample = 0x00;
2019 devpriv->softsshhold = 0x80;
2024 pci_read_config_word(pcidev, PCI_COMMAND, &u16w);
2025 pci_write_config_word(pcidev, PCI_COMMAND, u16w | 64);
2026 /* Enable parity check for parity error */
2028 ret = comedi_alloc_subdevices(dev, 4);
2032 s = &dev->subdevices[0];
2033 dev->read_subdev = s;
2034 s->type = COMEDI_SUBD_AI;
2035 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2036 if (devpriv->usemux)
2037 s->n_chan = devpriv->usemux;
2039 s->n_chan = this_board->n_aichan;
2041 s->maxdata = this_board->ai_maxdata;
2042 s->len_chanlist = this_board->n_aichanlist;
2043 s->range_table = this_board->rangelist_ai;
2044 s->cancel = pci9118_ai_cancel;
2045 s->insn_read = pci9118_insn_read_ai;
2047 s->subdev_flags |= SDF_CMD_READ;
2048 s->do_cmdtest = pci9118_ai_cmdtest;
2049 s->do_cmd = pci9118_ai_cmd;
2050 s->munge = pci9118_ai_munge;
2053 s = &dev->subdevices[1];
2054 s->type = COMEDI_SUBD_AO;
2055 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2056 s->n_chan = this_board->n_aochan;
2057 s->maxdata = this_board->ao_maxdata;
2058 s->len_chanlist = this_board->n_aochan;
2059 s->range_table = this_board->rangelist_ao;
2060 s->insn_write = pci9118_insn_write_ao;
2061 s->insn_read = pci9118_insn_read_ao;
2063 s = &dev->subdevices[2];
2064 s->type = COMEDI_SUBD_DI;
2065 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2068 s->len_chanlist = 4;
2069 s->range_table = &range_digital;
2070 s->io_bits = 0; /* all bits input */
2071 s->insn_bits = pci9118_insn_bits_di;
2073 s = &dev->subdevices[3];
2074 s->type = COMEDI_SUBD_DO;
2075 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2078 s->len_chanlist = 4;
2079 s->range_table = &range_digital;
2080 s->io_bits = 0xf; /* all bits output */
2081 s->insn_bits = pci9118_insn_bits_do;
2084 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2085 devpriv->ai_maskharderr = 0x10a;
2086 /* default measure crash condition */
2087 if (it->options[5]) /* disable some requested */
2088 devpriv->ai_maskharderr &= ~it->options[5];
2090 switch (this_board->ai_maxdata) {
2092 devpriv->ai16bits = 1;
2095 devpriv->ai16bits = 0;
2101 static void pci9118_detach(struct comedi_device *dev)
2103 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
2104 struct pci9118_private *devpriv = dev->private;
2110 free_irq(dev->irq, dev);
2111 if (devpriv->dmabuf_virt[0])
2112 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2113 devpriv->dmabuf_pages[0]);
2114 if (devpriv->dmabuf_virt[1])
2115 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2116 devpriv->dmabuf_pages[1]);
2120 comedi_pci_disable(pcidev);
2122 pci_dev_put(pcidev);
2126 static const struct boardtype boardtypes[] = {
2128 .name = "pci9118dg",
2129 .vendor_id = PCI_VENDOR_ID_AMCC,
2130 .device_id = 0x80d9,
2131 .iorange_amcc = AMCC_OP_REG_SIZE,
2132 .iorange_9118 = IORANGE_9118,
2136 .n_aichanlist = PCI9118_CHANLEN,
2138 .ai_maxdata = 0x0fff,
2139 .ao_maxdata = 0x0fff,
2140 .rangelist_ai = &range_pci9118dg_hr,
2141 .rangelist_ao = &range_bipolar10,
2144 .half_fifo_size = 512,
2146 .name = "pci9118hg",
2147 .vendor_id = PCI_VENDOR_ID_AMCC,
2148 .device_id = 0x80d9,
2149 .iorange_amcc = AMCC_OP_REG_SIZE,
2150 .iorange_9118 = IORANGE_9118,
2154 .n_aichanlist = PCI9118_CHANLEN,
2156 .ai_maxdata = 0x0fff,
2157 .ao_maxdata = 0x0fff,
2158 .rangelist_ai = &range_pci9118hg,
2159 .rangelist_ao = &range_bipolar10,
2162 .half_fifo_size = 512,
2164 .name = "pci9118hr",
2165 .vendor_id = PCI_VENDOR_ID_AMCC,
2166 .device_id = 0x80d9,
2167 .iorange_amcc = AMCC_OP_REG_SIZE,
2168 .iorange_9118 = IORANGE_9118,
2172 .n_aichanlist = PCI9118_CHANLEN,
2174 .ai_maxdata = 0xffff,
2175 .ao_maxdata = 0x0fff,
2176 .rangelist_ai = &range_pci9118dg_hr,
2177 .rangelist_ao = &range_bipolar10,
2180 .half_fifo_size = 512,
2184 static struct comedi_driver adl_pci9118_driver = {
2185 .driver_name = "adl_pci9118",
2186 .module = THIS_MODULE,
2187 .attach = pci9118_attach,
2188 .detach = pci9118_detach,
2189 .num_names = ARRAY_SIZE(boardtypes),
2190 .board_name = &boardtypes[0].name,
2191 .offset = sizeof(struct boardtype),
2194 static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
2195 const struct pci_device_id *ent)
2197 return comedi_pci_auto_config(dev, &adl_pci9118_driver);
2200 static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
2202 comedi_pci_auto_unconfig(dev);
2205 static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
2206 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2209 MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2211 static struct pci_driver adl_pci9118_pci_driver = {
2212 .name = "adl_pci9118",
2213 .id_table = adl_pci9118_pci_table,
2214 .probe = adl_pci9118_pci_probe,
2215 .remove = __devexit_p(adl_pci9118_pci_remove),
2217 module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
2219 MODULE_AUTHOR("Comedi http://www.comedi.org");
2220 MODULE_DESCRIPTION("Comedi low-level driver");
2221 MODULE_LICENSE("GPL");