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_pci.h"
75 #include "comedi_fc.h"
77 #define PCI_VENDOR_ID_AMCC 0x10e8
79 /* paranoid checks are broken */
80 #undef PCI9118_PARANOIDCHECK /*
81 * if defined, then is used code which control
82 * correct channel number on every 12 bit sample
85 #undef PCI9118_EXTDEBUG /*
86 * if defined then driver prints
91 #ifdef PCI9118_EXTDEBUG
92 #define DPRINTK(fmt, args...) printk(fmt, ## args)
94 #define DPRINTK(fmt, args...)
97 #define IORANGE_9118 64 /* I hope */
98 #define PCI9118_CHANLEN 255 /*
99 * len of chanlist, some source say 256,
100 * but reality looks like 255 :-(
103 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
104 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
105 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
106 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
107 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
108 #define PCI9118_DA1 0x10 /* W: D/A registers */
109 #define PCI9118_DA2 0x14
110 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
111 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
112 #define PCI9118_DI 0x1c /* R: digi input register */
113 #define PCI9118_DO 0x1c /* W: digi output register */
114 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
115 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
116 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
117 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
118 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
119 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
120 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
121 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
123 /* bits from A/D control register (PCI9118_ADCNTRL) */
124 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
125 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
126 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
127 #define AdControl_ExtG 0x10 /*
128 * 1=8254 countrol controlled by TGIN(pin 46),
129 * 0=controlled by SoftG
131 #define AdControl_ExtM 0x08 /*
132 * 1=external hardware trigger (pin 44),
135 #define AdControl_TmrTr 0x04 /*
136 * 1=8254 is iternal trigger source,
137 * 0=software trigger is source
138 * (register PCI9118_SOFTTRG)
140 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
141 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
143 /* bits from A/D function register (PCI9118_ADFUNC) */
144 #define AdFunction_PDTrg 0x80 /*
146 * 0=negative digital trigger
147 * (only positive is correct)
149 #define AdFunction_PETrg 0x40 /*
151 * 0=negative external trigger
152 * (only positive is correct)
154 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
155 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
156 #define AdFunction_BS 0x08 /*
157 * 1=burst mode start,
160 #define AdFunction_PM 0x04 /*
161 * 1=post trigger mode,
164 #define AdFunction_AM 0x02 /*
165 * 1=about trigger mode,
166 * 0=not about trigger
168 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
170 /* bits from A/D status register (PCI9118_ADSTAT) */
171 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
172 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
173 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
174 #define AdStatus_Acmp 0x020 /* */
175 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
176 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
177 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
178 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
179 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
181 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
182 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
183 #define Int_Timer 0x08 /* timer interrupt */
184 #define Int_About 0x04 /* about trigger complete */
185 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
186 #define Int_DTrg 0x01 /* external digital trigger */
188 #define START_AI_EXT 0x01 /* start measure on external trigger */
189 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
190 #define START_AI_INT 0x04 /* start measure on internal trigger */
191 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
193 #define EXTTRG_AI 0 /* ext trg is used by AI */
195 static const struct comedi_lrange range_pci9118dg_hr = { 8, {
207 static const struct comedi_lrange range_pci9118hg = { 8, {
219 #define PCI9118_BIPOLAR_RANGES 4 /*
220 * used for test on mixture
224 static int pci9118_attach(struct comedi_device *dev,
225 struct comedi_devconfig *it);
226 static int pci9118_detach(struct comedi_device *dev);
229 const char *name; /* board name */
230 int vendor_id; /* PCI vendor a device ID of card */
232 int iorange_amcc; /* iorange for own S5933 region */
233 int iorange_9118; /* pass thru card region size */
234 int n_aichan; /* num of A/D chans */
235 int n_aichand; /* num of A/D chans in diff mode */
237 * num of A/D chans with
238 * external multiplexor
240 int n_aichanlist; /* len of chanlist */
241 int n_aochan; /* num of D/A chans */
242 int ai_maxdata; /* resolution of A/D */
243 int ao_maxdata; /* resolution of D/A */
244 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
245 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
246 unsigned int ai_ns_min; /* max sample speed of card v ns */
247 unsigned int ai_pacer_min; /*
248 * minimal pacer value
249 * (c1*c2 or c1 in burst)
251 int half_fifo_size; /* size of FIFO/2 */
255 static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
256 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
260 MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
262 static const struct boardtype boardtypes[] = {
263 {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
264 AMCC_OP_REG_SIZE, IORANGE_9118,
265 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
266 &range_pci9118dg_hr, &range_bipolar10,
268 {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
269 AMCC_OP_REG_SIZE, IORANGE_9118,
270 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
271 &range_pci9118hg, &range_bipolar10,
273 {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
274 AMCC_OP_REG_SIZE, IORANGE_9118,
275 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
276 &range_pci9118dg_hr, &range_bipolar10,
280 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
282 static struct comedi_driver driver_pci9118 = {
283 .driver_name = "adl_pci9118",
284 .module = THIS_MODULE,
285 .attach = pci9118_attach,
286 .detach = pci9118_detach,
287 .num_names = n_boardtypes,
288 .board_name = &boardtypes[0].name,
289 .offset = sizeof(struct boardtype),
292 static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
293 const struct pci_device_id *ent)
295 return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
298 static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
300 comedi_pci_auto_unconfig(dev);
303 static struct pci_driver driver_pci9118_pci_driver = {
304 .id_table = pci9118_pci_table,
305 .probe = &driver_pci9118_pci_probe,
306 .remove = __devexit_p(&driver_pci9118_pci_remove)
309 static int __init driver_pci9118_init_module(void)
313 retval = comedi_driver_register(&driver_pci9118);
317 driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
318 return pci_register_driver(&driver_pci9118_pci_driver);
321 static void __exit driver_pci9118_cleanup_module(void)
323 pci_unregister_driver(&driver_pci9118_pci_driver);
324 comedi_driver_unregister(&driver_pci9118);
327 module_init(driver_pci9118_init_module);
328 module_exit(driver_pci9118_cleanup_module);
330 struct pci9118_private {
331 unsigned long iobase_a; /* base+size for AMCC chip */
332 unsigned int master; /* master capable */
333 struct pci_dev *pcidev; /* ptr to actual pcidev */
334 unsigned int usemux; /* we want to use external multiplexor! */
335 #ifdef PCI9118_PARANOIDCHECK
336 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
340 unsigned char chanlistlen; /* number of scanlist */
342 unsigned char AdControlReg; /* A/D control register */
343 unsigned char IntControlReg; /* Interrupt control register */
344 unsigned char AdFunctionReg; /* A/D function register */
345 char valid; /* driver is ok */
346 char ai_neverending; /* we do unlimited AI */
347 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
348 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
349 unsigned int ai_act_scan; /* how many scans we finished */
350 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
351 unsigned int ai_n_chan; /* how many channels is measured */
352 unsigned int ai_n_scanlen; /* len of actual scanlist */
353 unsigned int ai_n_realscanlen; /*
354 * what we must transfer for one
355 * outgoing scan include front/back adds
357 unsigned int ai_act_dmapos; /* position in actual real stream */
358 unsigned int ai_add_front; /*
359 * how many channels we must add
360 * before scan to satisfy S&H?
362 unsigned int ai_add_back; /*
363 * how many channels we must add
364 * before scan to satisfy DMA?
366 unsigned int *ai_chanlist; /* actual chanlist */
367 unsigned int ai_timer1;
368 unsigned int ai_timer2;
369 unsigned int ai_flags;
370 char ai12_startstop; /*
371 * measure can start/stop
372 * on external trigger
374 unsigned int ai_divisor1, ai_divisor2; /*
375 * divisors for start of measure
378 unsigned int ai_data_len;
380 short ao_data[2]; /* data output buffer */
381 unsigned int ai_scans; /* number of scans to do */
382 char dma_doublebuf; /* we can use double buffring */
383 unsigned int dma_actbuf; /* which buffer is used now */
384 short *dmabuf_virt[2]; /*
385 * pointers to begin of
388 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
389 unsigned int dmabuf_size[2]; /*
390 * size of dma buffer in bytes
392 unsigned int dmabuf_use_size[2]; /*
393 * which size we may now use
396 unsigned int dmabuf_used_size[2]; /* which size was truly used */
397 unsigned int dmabuf_panic_size[2];
398 unsigned int dmabuf_samples[2]; /* size in samples */
399 int dmabuf_pages[2]; /* number of pages in buffer */
400 unsigned char cnt0_users; /*
401 * bit field of 8254 CNT0 users
402 * (0-unused, 1-AO, 2-DI, 3-DO)
404 unsigned char exttrg_users; /*
405 * bit field of external trigger
406 * users(0-AI, 1-AO, 2-DI, 3-DO)
408 unsigned int cnt0_divisor; /* actual CNT0 divisor */
409 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
413 * ptr to actual interrupt
416 unsigned char ai16bits; /* =1 16 bit card */
417 unsigned char usedma; /* =1 use DMA transfer and not INT */
418 unsigned char useeoshandle; /*
419 * =1 change WAKE_EOS DMA transfer
420 * to fit on every second
422 unsigned char usessh; /* =1 turn on S&H support */
424 * >0 use software S&H,
425 * numer is requested delay in ns
427 unsigned char softsshsample; /*
428 * polarity of S&H signal
431 unsigned char softsshhold; /*
432 * polarity of S&H signal
435 unsigned int ai_maskerr; /* which warning was printed */
436 unsigned int ai_maskharderr; /* on which error bits stops */
437 unsigned int ai_inttrig_start; /* TRIG_INT for start */
440 #define devpriv ((struct pci9118_private *)dev->private)
441 #define this_board ((struct boardtype *)dev->board_ptr)
444 ==============================================================================
447 static int check_channel_list(struct comedi_device *dev,
448 struct comedi_subdevice *s, int n_chan,
449 unsigned int *chanlist, int frontadd,
451 static int setup_channel_list(struct comedi_device *dev,
452 struct comedi_subdevice *s, int n_chan,
453 unsigned int *chanlist, int rot, int frontadd,
454 int backadd, int usedma, char eoshandle);
455 static void start_pacer(struct comedi_device *dev, int mode,
456 unsigned int divisor1, unsigned int divisor2);
457 static int pci9118_reset(struct comedi_device *dev);
458 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
459 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
460 static int pci9118_ai_cancel(struct comedi_device *dev,
461 struct comedi_subdevice *s);
462 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
463 struct comedi_subdevice *s,
464 unsigned int *tim1, unsigned int *tim2,
465 unsigned int flags, int chans,
466 unsigned int *div1, unsigned int *div2,
467 char usessh, unsigned int chnsshfront);
470 ==============================================================================
472 static int pci9118_insn_read_ai(struct comedi_device *dev,
473 struct comedi_subdevice *s,
474 struct comedi_insn *insn, unsigned int *data)
479 devpriv->AdControlReg = AdControl_Int & 0xff;
480 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
481 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
483 * positive triggers, no S&H,
484 * no burst, burst stop,
490 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
493 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
495 for (n = 0; n < insn->n; n++) {
496 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
500 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
505 comedi_error(dev, "A/D insn timeout");
507 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
511 if (devpriv->ai16bits) {
514 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
517 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
521 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
527 ==============================================================================
529 static int pci9118_insn_write_ao(struct comedi_device *dev,
530 struct comedi_subdevice *s,
531 struct comedi_insn *insn, unsigned int *data)
535 ch = CR_CHAN(insn->chanspec);
537 chanreg = PCI9118_DA2;
539 chanreg = PCI9118_DA1;
542 for (n = 0; n < insn->n; n++) {
543 outl(data[n], dev->iobase + chanreg);
544 devpriv->ao_data[ch] = data[n];
551 ==============================================================================
553 static int pci9118_insn_read_ao(struct comedi_device *dev,
554 struct comedi_subdevice *s,
555 struct comedi_insn *insn, unsigned int *data)
559 chan = CR_CHAN(insn->chanspec);
560 for (n = 0; n < insn->n; n++)
561 data[n] = devpriv->ao_data[chan];
567 ==============================================================================
569 static int pci9118_insn_bits_di(struct comedi_device *dev,
570 struct comedi_subdevice *s,
571 struct comedi_insn *insn, unsigned int *data)
573 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
579 ==============================================================================
581 static int pci9118_insn_bits_do(struct comedi_device *dev,
582 struct comedi_subdevice *s,
583 struct comedi_insn *insn, unsigned int *data)
586 s->state &= ~data[0];
587 s->state |= (data[0] & data[1]);
588 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
596 ==============================================================================
598 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
600 devpriv->AdFunctionReg =
601 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
602 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
603 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
604 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
605 dev->iobase + PCI9118_CNT0);
606 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
607 dev->iobase + PCI9118_CNT0);
608 devpriv->AdFunctionReg |= AdFunction_Start;
609 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
612 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
613 struct comedi_subdevice *s,
615 unsigned int num_samples)
617 unsigned int i = 0, j = 0;
618 unsigned int start_pos = devpriv->ai_add_front,
619 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
620 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
621 devpriv->ai_add_back;
623 for (i = 0; i < num_samples; i++) {
624 if (devpriv->ai_act_dmapos >= start_pos &&
625 devpriv->ai_act_dmapos < stop_pos) {
626 dma_buffer[j++] = dma_buffer[i];
628 devpriv->ai_act_dmapos++;
629 devpriv->ai_act_dmapos %= raw_scanlen;
636 ==============================================================================
638 static int move_block_from_dma(struct comedi_device *dev,
639 struct comedi_subdevice *s,
641 unsigned int num_samples)
643 unsigned int num_bytes;
645 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
646 devpriv->ai_act_scan +=
647 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
648 s->async->cur_chan += num_samples;
649 s->async->cur_chan %= devpriv->ai_n_scanlen;
651 cfc_write_array_to_buffer(s, dma_buffer,
652 num_samples * sizeof(short));
653 if (num_bytes < num_samples * sizeof(short))
659 ==============================================================================
661 static char pci9118_decode_error_status(struct comedi_device *dev,
662 struct comedi_subdevice *s,
666 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
667 devpriv->ai_maskerr &= ~0x100L;
671 "A/D Burst Mode Overrun Status (Fatal Error!)");
672 devpriv->ai_maskerr &= ~0x008L;
675 comedi_error(dev, "A/D Over Speed Status (Warning!)");
676 devpriv->ai_maskerr &= ~0x004L;
679 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
680 devpriv->ai_maskerr &= ~0x002L;
682 if (m & devpriv->ai_maskharderr) {
683 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
684 pci9118_ai_cancel(dev, s);
685 comedi_event(dev, s);
692 static void pci9118_ai_munge(struct comedi_device *dev,
693 struct comedi_subdevice *s, void *data,
694 unsigned int num_bytes,
695 unsigned int start_chan_index)
697 unsigned int i, num_samples = num_bytes / sizeof(short);
700 for (i = 0; i < num_samples; i++) {
702 array[i] = be16_to_cpu(array[i]);
703 if (devpriv->ai16bits)
706 array[i] = (array[i] >> 4) & 0x0fff;
712 ==============================================================================
714 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
715 struct comedi_subdevice *s,
716 unsigned short int_adstat,
717 unsigned int int_amcc,
718 unsigned short int_daq)
720 register short sampl;
722 s->async->events = 0;
724 if (int_adstat & devpriv->ai_maskerr)
725 if (pci9118_decode_error_status(dev, s, int_adstat))
728 sampl = inw(dev->iobase + PCI9118_AD_DATA);
730 #ifdef PCI9118_PARANOIDCHECK
731 if (devpriv->ai16bits == 0) {
732 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
735 ("comedi: A/D SAMPL - data dropout: "
736 "received channel %d, expected %d!\n",
738 devpriv->chanlist[s->async->cur_chan]);
739 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
740 pci9118_ai_cancel(dev, s);
741 comedi_event(dev, s);
746 cfc_write_to_buffer(s, sampl);
747 s->async->cur_chan++;
748 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
750 s->async->cur_chan %= devpriv->ai_n_scanlen;
751 devpriv->ai_act_scan++;
752 if (!(devpriv->ai_neverending))
753 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
754 /* all data sampled */
755 pci9118_ai_cancel(dev, s);
756 s->async->events |= COMEDI_CB_EOA;
760 if (s->async->events)
761 comedi_event(dev, s);
765 ==============================================================================
767 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
768 struct comedi_subdevice *s,
769 unsigned short int_adstat,
770 unsigned int int_amcc,
771 unsigned short int_daq)
773 unsigned int next_dma_buf, samplesinbuf, sampls, m;
775 if (int_amcc & MASTER_ABORT_INT) {
776 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
777 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
778 pci9118_ai_cancel(dev, s);
779 comedi_event(dev, s);
783 if (int_amcc & TARGET_ABORT_INT) {
784 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
785 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
786 pci9118_ai_cancel(dev, s);
787 comedi_event(dev, s);
790 if (int_adstat & devpriv->ai_maskerr)
791 /* if (int_adstat & 0x106) */
792 if (pci9118_decode_error_status(dev, s, int_adstat))
795 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
796 /* number of received real samples */
797 /* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
799 if (devpriv->dma_doublebuf) { /*
800 * switch DMA buffers if is used
803 next_dma_buf = 1 - devpriv->dma_actbuf;
804 outl(devpriv->dmabuf_hw[next_dma_buf],
805 devpriv->iobase_a + AMCC_OP_REG_MWAR);
806 outl(devpriv->dmabuf_use_size[next_dma_buf],
807 devpriv->iobase_a + AMCC_OP_REG_MWTC);
808 devpriv->dmabuf_used_size[next_dma_buf] =
809 devpriv->dmabuf_use_size[next_dma_buf];
810 if (devpriv->ai_do == 4)
811 interrupt_pci9118_ai_mode4_switch(dev);
815 m = devpriv->ai_data_len >> 1; /*
816 * how many samples is to
820 * DPRINTK("samps=%d m=%d %d %d\n",
821 * samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
824 move_block_from_dma(dev, s,
825 devpriv->dmabuf_virt[devpriv->dma_actbuf],
827 m = m - sampls; /* m= how many samples was transferred */
829 /* DPRINTK("YYY\n"); */
831 if (!devpriv->ai_neverending)
832 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
833 /* all data sampled */
834 pci9118_ai_cancel(dev, s);
835 s->async->events |= COMEDI_CB_EOA;
838 if (devpriv->dma_doublebuf) { /* switch dma buffers */
839 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
840 } else { /* restart DMA if is not used double buffering */
841 outl(devpriv->dmabuf_hw[0],
842 devpriv->iobase_a + AMCC_OP_REG_MWAR);
843 outl(devpriv->dmabuf_use_size[0],
844 devpriv->iobase_a + AMCC_OP_REG_MWTC);
845 if (devpriv->ai_do == 4)
846 interrupt_pci9118_ai_mode4_switch(dev);
849 comedi_event(dev, s);
853 ==============================================================================
855 static irqreturn_t interrupt_pci9118(int irq, void *d)
857 struct comedi_device *dev = d;
858 unsigned int int_daq = 0, int_amcc, int_adstat;
861 return IRQ_NONE; /* not fully initialized */
863 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
864 /* get IRQ reasons from card */
865 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
866 /* get INT register from AMCC chip */
869 * DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x
870 * MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n",
871 * int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR),
872 * inl(devpriv->iobase_a+AMCC_OP_REG_MWTC),
873 * inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
876 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
877 return IRQ_NONE; /* interrupt from other source */
879 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
880 /* shutdown IRQ reasons in AMCC */
882 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
883 /* get STATUS register */
885 if (devpriv->ai_do) {
886 if (devpriv->ai12_startstop)
887 if ((int_adstat & AdStatus_DTH) &&
888 (int_daq & Int_DTrg)) {
889 /* start stop of measure */
890 if (devpriv->ai12_startstop & START_AI_EXT) {
891 devpriv->ai12_startstop &=
893 if (!(devpriv->ai12_startstop &
897 /* deactivate EXT trigger */
898 start_pacer(dev, devpriv->ai_do,
899 devpriv->ai_divisor1,
900 devpriv->ai_divisor2);
902 outl(devpriv->AdControlReg,
903 dev->iobase + PCI9118_ADCNTRL);
905 if (devpriv->ai12_startstop &
907 devpriv->ai12_startstop &=
911 /* deactivate EXT trigger */
912 devpriv->ai_neverending = 0;
914 * well, on next interrupt from
915 * DMA/EOC measure will stop
921 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
929 ==============================================================================
931 static int pci9118_ai_inttrig(struct comedi_device *dev,
932 struct comedi_subdevice *s, unsigned int trignum)
934 if (trignum != devpriv->ai_inttrig_start)
937 devpriv->ai12_startstop &= ~START_AI_INT;
938 s->async->inttrig = NULL;
940 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
941 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
942 if (devpriv->ai_do != 3) {
943 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
944 devpriv->ai_divisor2);
945 devpriv->AdControlReg |= AdControl_SoftG;
947 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
953 ==============================================================================
955 static int pci9118_ai_cmdtest(struct comedi_device *dev,
956 struct comedi_subdevice *s,
957 struct comedi_cmd *cmd)
961 unsigned int divisor1 = 0, divisor2 = 0;
963 /* step 1: make sure trigger sources are trivially valid */
965 tmp = cmd->start_src;
966 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
967 if (!cmd->start_src || tmp != cmd->start_src)
970 tmp = cmd->scan_begin_src;
972 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
974 cmd->scan_begin_src &= TRIG_FOLLOW;
976 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
979 tmp = cmd->convert_src;
981 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
983 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
985 if (!cmd->convert_src || tmp != cmd->convert_src)
988 tmp = cmd->scan_end_src;
989 cmd->scan_end_src &= TRIG_COUNT;
990 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
994 cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
995 if (!cmd->stop_src || tmp != cmd->stop_src)
1003 * make sure trigger sources are
1004 * unique and mutually compatible
1007 if (cmd->start_src != TRIG_NOW &&
1008 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
1009 cmd->start_src = TRIG_NOW;
1013 if (cmd->scan_begin_src != TRIG_TIMER &&
1014 cmd->scan_begin_src != TRIG_EXT &&
1015 cmd->scan_begin_src != TRIG_INT &&
1016 cmd->scan_begin_src != TRIG_FOLLOW) {
1017 cmd->scan_begin_src = TRIG_FOLLOW;
1021 if (cmd->convert_src != TRIG_TIMER &&
1022 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
1023 cmd->convert_src = TRIG_TIMER;
1027 if (cmd->scan_end_src != TRIG_COUNT) {
1028 cmd->scan_end_src = TRIG_COUNT;
1032 if (cmd->stop_src != TRIG_NONE &&
1033 cmd->stop_src != TRIG_COUNT &&
1034 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
1035 cmd->stop_src = TRIG_COUNT;
1039 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1040 cmd->start_src = TRIG_NOW;
1044 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
1045 cmd->start_src = TRIG_NOW;
1049 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1050 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
1051 cmd->convert_src = TRIG_TIMER;
1055 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1056 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
1057 cmd->convert_src = TRIG_TIMER;
1061 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1062 cmd->stop_src = TRIG_COUNT;
1069 /* step 3: make sure arguments are trivially compatible */
1071 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1072 if (cmd->start_arg != 0) {
1077 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1078 if (cmd->scan_begin_arg != 0) {
1079 cmd->scan_begin_arg = 0;
1083 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1084 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1085 cmd->scan_begin_src = TRIG_FOLLOW;
1086 cmd->convert_arg = cmd->scan_begin_arg;
1087 cmd->scan_begin_arg = 0;
1090 if (cmd->scan_begin_src == TRIG_TIMER)
1091 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1092 cmd->scan_begin_arg = this_board->ai_ns_min;
1096 if (cmd->scan_begin_src == TRIG_EXT)
1097 if (cmd->scan_begin_arg) {
1098 cmd->scan_begin_arg = 0;
1100 if (cmd->scan_end_arg > 65535) {
1101 cmd->scan_end_arg = 65535;
1106 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1107 if (cmd->convert_arg < this_board->ai_ns_min) {
1108 cmd->convert_arg = this_board->ai_ns_min;
1112 if (cmd->convert_src == TRIG_EXT)
1113 if (cmd->convert_arg) {
1114 cmd->convert_arg = 0;
1118 if (cmd->stop_src == TRIG_COUNT) {
1119 if (!cmd->stop_arg) {
1123 } else { /* TRIG_NONE */
1124 if (cmd->stop_arg != 0) {
1130 if (!cmd->chanlist_len) {
1131 cmd->chanlist_len = 1;
1135 if (cmd->chanlist_len > this_board->n_aichanlist) {
1136 cmd->chanlist_len = this_board->n_aichanlist;
1140 if (cmd->scan_end_arg < cmd->chanlist_len) {
1141 cmd->scan_end_arg = cmd->chanlist_len;
1145 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1147 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1154 /* step 4: fix up any arguments */
1156 if (cmd->scan_begin_src == TRIG_TIMER) {
1157 tmp = cmd->scan_begin_arg;
1158 /* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1159 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1160 &divisor2, &cmd->scan_begin_arg,
1161 cmd->flags & TRIG_ROUND_MASK);
1162 /* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1163 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1164 cmd->scan_begin_arg = this_board->ai_ns_min;
1165 if (tmp != cmd->scan_begin_arg)
1169 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1170 tmp = cmd->convert_arg;
1171 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1172 &divisor2, &cmd->convert_arg,
1173 cmd->flags & TRIG_ROUND_MASK);
1174 /* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1175 if (cmd->convert_arg < this_board->ai_ns_min)
1176 cmd->convert_arg = this_board->ai_ns_min;
1177 if (tmp != cmd->convert_arg)
1179 if (cmd->scan_begin_src == TRIG_TIMER
1180 && cmd->convert_src == TRIG_NOW) {
1181 if (cmd->convert_arg == 0) {
1182 if (cmd->scan_begin_arg <
1183 this_board->ai_ns_min *
1184 (cmd->scan_end_arg + 2)) {
1185 cmd->scan_begin_arg =
1186 this_board->ai_ns_min *
1187 (cmd->scan_end_arg + 2);
1188 /* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1192 if (cmd->scan_begin_arg <
1193 cmd->convert_arg * cmd->chanlist_len) {
1194 cmd->scan_begin_arg =
1197 /* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1208 if (!check_channel_list(dev, s, cmd->chanlist_len,
1209 cmd->chanlist, 0, 0))
1210 return 5; /* incorrect channels list */
1216 ==============================================================================
1218 static int Compute_and_setup_dma(struct comedi_device *dev)
1220 unsigned int dmalen0, dmalen1, i;
1222 DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
1223 dmalen0 = devpriv->dmabuf_size[0];
1224 dmalen1 = devpriv->dmabuf_size[1];
1225 DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
1226 devpriv->ai_data_len);
1227 /* isn't output buff smaller that our DMA buff? */
1228 if (dmalen0 > (devpriv->ai_data_len)) {
1229 dmalen0 = devpriv->ai_data_len & ~3L; /*
1230 * align to 32bit down
1233 if (dmalen1 > (devpriv->ai_data_len)) {
1234 dmalen1 = devpriv->ai_data_len & ~3L; /*
1235 * align to 32bit down
1238 DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1240 /* we want wake up every scan? */
1241 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1242 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1243 /* uff, too short DMA buffer, disable EOS support! */
1244 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1246 ("comedi%d: WAR: DMA0 buf too short, can't "
1247 "support TRIG_WAKE_EOS (%d<%d)\n",
1248 dev->minor, dmalen0,
1249 devpriv->ai_n_realscanlen << 1);
1251 /* short first DMA buffer to one scan */
1252 dmalen0 = devpriv->ai_n_realscanlen << 1;
1254 ("21 dmalen0=%d ai_n_realscanlen=%d "
1255 "useeoshandle=%d\n",
1256 dmalen0, devpriv->ai_n_realscanlen,
1257 devpriv->useeoshandle);
1258 if (devpriv->useeoshandle)
1262 ("comedi%d: ERR: DMA0 buf len bug? "
1264 dev->minor, dmalen0);
1269 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1270 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1271 /* uff, too short DMA buffer, disable EOS support! */
1272 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1274 ("comedi%d: WAR: DMA1 buf too short, "
1275 "can't support TRIG_WAKE_EOS (%d<%d)\n",
1276 dev->minor, dmalen1,
1277 devpriv->ai_n_realscanlen << 1);
1279 /* short second DMA buffer to one scan */
1280 dmalen1 = devpriv->ai_n_realscanlen << 1;
1282 ("22 dmalen1=%d ai_n_realscanlen=%d "
1283 "useeoshandle=%d\n",
1284 dmalen1, devpriv->ai_n_realscanlen,
1285 devpriv->useeoshandle);
1286 if (devpriv->useeoshandle)
1290 ("comedi%d: ERR: DMA1 buf len bug? "
1292 dev->minor, dmalen1);
1298 DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1299 /* transfer without TRIG_WAKE_EOS */
1300 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1301 /* if it's possible then align DMA buffers to length of scan */
1304 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1305 (devpriv->ai_n_realscanlen << 1);
1308 dmalen0 = i; /* uff. very long scan? */
1311 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1312 (devpriv->ai_n_realscanlen << 1);
1315 dmalen1 = i; /* uff. very long scan? */
1317 * if measure isn't neverending then test, if it fits whole
1318 * into one or two DMA buffers
1320 if (!devpriv->ai_neverending) {
1321 /* fits whole measure into one DMA buffer? */
1323 ((devpriv->ai_n_realscanlen << 1) *
1324 devpriv->ai_scans)) {
1326 ("3.0 ai_n_realscanlen=%d ai_scans=%d\n",
1327 devpriv->ai_n_realscanlen,
1330 (devpriv->ai_n_realscanlen << 1) *
1332 DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0,
1336 * fits whole measure into
1340 ((devpriv->ai_n_realscanlen << 1) *
1341 devpriv->ai_scans - dmalen0))
1343 (devpriv->ai_n_realscanlen << 1) *
1344 devpriv->ai_scans - dmalen0;
1345 DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0,
1352 DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1354 /* these DMA buffer size will be used */
1355 devpriv->dma_actbuf = 0;
1356 devpriv->dmabuf_use_size[0] = dmalen0;
1357 devpriv->dmabuf_use_size[1] = dmalen1;
1359 DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1361 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1362 devpriv->dmabuf_panic_size[0] =
1363 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1364 1) * devpriv->ai_n_scanlen * sizeof(short);
1365 devpriv->dmabuf_panic_size[1] =
1366 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1367 1) * devpriv->ai_n_scanlen * sizeof(short);
1369 devpriv->dmabuf_panic_size[0] =
1370 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1371 devpriv->dmabuf_panic_size[1] =
1372 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1376 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1377 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1378 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1379 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1380 /* init DMA transfer */
1381 outl(0x00000000 | AINT_WRITE_COMPL,
1382 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1383 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1385 outl(inl(devpriv->iobase_a +
1386 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1387 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1388 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1389 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1390 /* allow bus mastering */
1392 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1397 ==============================================================================
1399 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1400 struct comedi_subdevice *s)
1402 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
1403 dev->minor, devpriv->ai_do);
1404 switch (devpriv->ai_do) {
1406 devpriv->AdControlReg |= AdControl_TmrTr;
1409 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1412 devpriv->AdControlReg |= AdControl_ExtM;
1415 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1419 "pci9118_ai_docmd_sampl() mode number bug!\n");
1423 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1424 /* transfer function */
1426 if (devpriv->ai12_startstop)
1427 pci9118_exttrg_add(dev, EXTTRG_AI);
1428 /* activate EXT trigger */
1430 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1431 devpriv->IntControlReg |= Int_Timer;
1433 devpriv->AdControlReg |= AdControl_Int;
1435 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1436 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1437 /* allow INT in AMCC */
1439 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1440 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1441 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1442 if (devpriv->ai_do != 3) {
1443 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1444 devpriv->ai_divisor2);
1445 devpriv->AdControlReg |= AdControl_SoftG;
1447 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1450 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
1455 ==============================================================================
1457 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1458 struct comedi_subdevice *s)
1460 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
1461 dev->minor, devpriv->ai_do, devpriv->usedma);
1462 Compute_and_setup_dma(dev);
1464 switch (devpriv->ai_do) {
1466 devpriv->AdControlReg |=
1467 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1470 devpriv->AdControlReg |=
1471 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1472 devpriv->AdFunctionReg =
1473 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1475 if (devpriv->usessh && (!devpriv->softsshdelay))
1476 devpriv->AdFunctionReg |= AdFunction_BSSH;
1477 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1480 devpriv->AdControlReg |=
1481 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1482 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1485 devpriv->AdControlReg |=
1486 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1487 devpriv->AdFunctionReg =
1488 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1489 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1490 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1491 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1492 dev->iobase + PCI9118_CNT0);
1493 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1494 dev->iobase + PCI9118_CNT0);
1495 devpriv->AdFunctionReg |= AdFunction_Start;
1498 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1502 if (devpriv->ai12_startstop) {
1503 pci9118_exttrg_add(dev, EXTTRG_AI);
1504 /* activate EXT trigger */
1507 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1508 /* transfer function */
1510 outl(0x02000000 | AINT_WRITE_COMPL,
1511 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1513 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1514 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1515 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1516 if (devpriv->ai_do != 3) {
1517 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1518 devpriv->ai_divisor2);
1519 devpriv->AdControlReg |= AdControl_SoftG;
1521 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1524 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
1529 ==============================================================================
1531 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1533 struct comedi_cmd *cmd = &s->async->cmd;
1534 unsigned int addchans = 0;
1537 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
1538 devpriv->ai12_startstop = 0;
1539 devpriv->ai_flags = cmd->flags;
1540 devpriv->ai_n_chan = cmd->chanlist_len;
1541 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1542 devpriv->ai_chanlist = cmd->chanlist;
1543 devpriv->ai_data = s->async->prealloc_buf;
1544 devpriv->ai_data_len = s->async->prealloc_bufsz;
1545 devpriv->ai_timer1 = 0;
1546 devpriv->ai_timer2 = 0;
1547 devpriv->ai_add_front = 0;
1548 devpriv->ai_add_back = 0;
1549 devpriv->ai_maskerr = 0x10e;
1551 /* prepare for start/stop conditions */
1552 if (cmd->start_src == TRIG_EXT)
1553 devpriv->ai12_startstop |= START_AI_EXT;
1554 if (cmd->stop_src == TRIG_EXT) {
1555 devpriv->ai_neverending = 1;
1556 devpriv->ai12_startstop |= STOP_AI_EXT;
1558 if (cmd->start_src == TRIG_INT) {
1559 devpriv->ai12_startstop |= START_AI_INT;
1560 devpriv->ai_inttrig_start = cmd->start_arg;
1561 s->async->inttrig = pci9118_ai_inttrig;
1564 if (cmd->stop_src == TRIG_INT) {
1565 devpriv->ai_neverending = 1;
1566 devpriv->ai12_startstop |= STOP_AI_INT;
1569 if (cmd->stop_src == TRIG_NONE)
1570 devpriv->ai_neverending = 1;
1571 if (cmd->stop_src == TRIG_COUNT) {
1572 devpriv->ai_scans = cmd->stop_arg;
1573 devpriv->ai_neverending = 0;
1575 devpriv->ai_scans = 0;
1578 /* use sample&hold signal? */
1579 if (cmd->convert_src == TRIG_NOW)
1580 devpriv->usessh = 1;
1583 devpriv->usessh = 0;
1586 DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
1587 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
1588 devpriv->ai12_startstop);
1591 * use additional sample at end of every scan
1592 * to satisty DMA 32 bit transfer?
1594 devpriv->ai_add_front = 0;
1595 devpriv->ai_add_back = 0;
1596 devpriv->useeoshandle = 0;
1597 if (devpriv->master) {
1598 devpriv->usedma = 1;
1599 if ((cmd->flags & TRIG_WAKE_EOS) &&
1600 (devpriv->ai_n_scanlen == 1)) {
1601 if (cmd->convert_src == TRIG_NOW)
1602 devpriv->ai_add_back = 1;
1603 if (cmd->convert_src == TRIG_TIMER) {
1604 devpriv->usedma = 0;
1606 * use INT transfer if scanlist
1607 * have only one channel
1611 if ((cmd->flags & TRIG_WAKE_EOS) &&
1612 (devpriv->ai_n_scanlen & 1) &&
1613 (devpriv->ai_n_scanlen > 1)) {
1614 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1616 * vpriv->useeoshandle=1; // change DMA transfer
1617 * block to fit EOS on every second call
1619 devpriv->usedma = 0;
1621 * XXX maybe can be corrected to use 16 bit DMA
1624 * well, we must insert one sample
1625 * to end of EOS to meet 32 bit transfer
1627 devpriv->ai_add_back = 1;
1630 } else { /* interrupt transfer don't need any correction */
1631 devpriv->usedma = 0;
1635 * we need software S&H signal?
1636 * It adds two samples before every scan as minimum
1638 if (devpriv->usessh && devpriv->softsshdelay) {
1639 devpriv->ai_add_front = 2;
1640 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1641 /* move it to front */
1642 devpriv->ai_add_front++;
1643 devpriv->ai_add_back = 0;
1645 if (cmd->convert_arg < this_board->ai_ns_min)
1646 cmd->convert_arg = this_board->ai_ns_min;
1647 addchans = devpriv->softsshdelay / cmd->convert_arg;
1648 if (devpriv->softsshdelay % cmd->convert_arg)
1650 if (addchans > (devpriv->ai_add_front - 1)) {
1651 /* uff, still short */
1652 devpriv->ai_add_front = addchans + 1;
1653 if (devpriv->usedma == 1)
1654 if ((devpriv->ai_add_front +
1655 devpriv->ai_n_chan +
1656 devpriv->ai_add_back) & 1)
1657 devpriv->ai_add_front++;
1658 /* round up to 32 bit */
1661 /* well, we now know what must be all added */
1662 devpriv->ai_n_realscanlen = /*
1663 * what we must take from card in real
1664 * to have ai_n_scanlen on output?
1666 (devpriv->ai_add_front + devpriv->ai_n_chan +
1667 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1668 devpriv->ai_n_chan);
1670 DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
1672 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
1673 devpriv->ai_n_chan, devpriv->ai_add_back,
1674 devpriv->ai_n_scanlen);
1676 /* check and setup channel list */
1677 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1678 devpriv->ai_chanlist, devpriv->ai_add_front,
1679 devpriv->ai_add_back))
1681 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1682 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1683 devpriv->ai_add_back, devpriv->usedma,
1684 devpriv->useeoshandle))
1687 /* compute timers settings */
1689 * simplest way, fr=4Mhz/(tim1*tim2),
1690 * channel manipulation without timers effect
1692 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1693 (cmd->scan_begin_src == TRIG_EXT) ||
1694 (cmd->scan_begin_src == TRIG_INT)) &&
1695 (cmd->convert_src == TRIG_TIMER)) {
1696 /* both timer is used for one time */
1697 if (cmd->scan_begin_src == TRIG_EXT)
1701 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1702 &cmd->scan_begin_arg, &cmd->convert_arg,
1704 devpriv->ai_n_realscanlen,
1705 &devpriv->ai_divisor1,
1706 &devpriv->ai_divisor2, devpriv->usessh,
1707 devpriv->ai_add_front);
1708 devpriv->ai_timer2 = cmd->convert_arg;
1711 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1712 ((cmd->convert_src == TRIG_TIMER) ||
1713 (cmd->convert_src == TRIG_NOW))) {
1714 /* double timed action */
1715 if (!devpriv->usedma) {
1717 "cmd->scan_begin_src=TRIG_TIMER works "
1718 "only with bus mastering!");
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_timer1 = cmd->scan_begin_arg;
1731 devpriv->ai_timer2 = cmd->convert_arg;
1734 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1735 && (cmd->convert_src == TRIG_EXT)) {
1739 start_pacer(dev, -1, 0, 0); /* stop pacer */
1741 devpriv->AdControlReg = 0; /*
1742 * bipolar, S.E., use 8254, stop 8354,
1743 * internal trigger, soft trigger,
1746 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1747 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1749 * positive triggers, no S&H, no burst,
1750 * burst stop, no post trigger,
1751 * no about trigger, trigger stop
1753 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1755 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1756 inl(dev->iobase + PCI9118_ADSTAT); /*
1760 inl(dev->iobase + PCI9118_INTSRC);
1762 devpriv->ai_act_scan = 0;
1763 devpriv->ai_act_dmapos = 0;
1764 s->async->cur_chan = 0;
1765 devpriv->ai_buf_ptr = 0;
1767 if (devpriv->usedma)
1768 ret = pci9118_ai_docmd_dma(dev, s);
1770 ret = pci9118_ai_docmd_sampl(dev, s);
1772 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1777 ==============================================================================
1779 static int check_channel_list(struct comedi_device *dev,
1780 struct comedi_subdevice *s, int n_chan,
1781 unsigned int *chanlist, int frontadd, int backadd)
1783 unsigned int i, differencial = 0, bipolar = 0;
1785 /* correct channel and range number check itself comedi/range.c */
1787 comedi_error(dev, "range/channel list is empty!");
1790 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
1792 ("comedi%d: range/channel list is too long for "
1793 "actual configuration (%d>%d)!",
1794 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
1798 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1799 differencial = 1; /* all input must be diff */
1800 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1801 bipolar = 1; /* all input must be bipolar */
1803 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
1804 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
1807 "Differencial and single ended "
1808 "inputs can't be mixtured!");
1811 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
1814 "Bipolar and unipolar ranges "
1815 "can't be mixtured!");
1818 if ((!devpriv->usemux) & (differencial) &
1819 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
1821 "If AREF_DIFF is used then is "
1822 "available only first 8 channels!");
1831 ==============================================================================
1833 static int setup_channel_list(struct comedi_device *dev,
1834 struct comedi_subdevice *s, int n_chan,
1835 unsigned int *chanlist, int rot, int frontadd,
1836 int backadd, int usedma, char useeos)
1838 unsigned int i, differencial = 0, bipolar = 0;
1839 unsigned int scanquad, gain, ssh = 0x00;
1842 ("adl_pci9118 EDBG: BGN: setup_channel_list"
1843 "(%d,.,%d,.,%d,%d,%d,%d)\n",
1844 dev->minor, n_chan, rot, frontadd, backadd, usedma);
1851 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1852 differencial = 1; /* all input must be diff */
1853 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1854 bipolar = 1; /* all input must be bipolar */
1856 /* All is ok, so we can setup channel/range list */
1859 devpriv->AdControlReg |= AdControl_UniP;
1860 /* set unibipolar */
1862 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
1863 /* enable bipolar */
1867 devpriv->AdControlReg |= AdControl_Diff;
1868 /* enable diff inputs */
1870 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
1871 /* set single ended inputs */
1874 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1877 outl(2, dev->iobase + PCI9118_SCANMOD);
1878 /* gods know why this sequence! */
1879 outl(0, dev->iobase + PCI9118_SCANMOD);
1880 outl(1, dev->iobase + PCI9118_SCANMOD);
1882 #ifdef PCI9118_PARANOIDCHECK
1883 devpriv->chanlistlen = n_chan;
1884 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
1885 devpriv->chanlist[i] = 0x55aa;
1888 if (frontadd) { /* insert channels for S&H */
1889 ssh = devpriv->softsshsample;
1890 DPRINTK("FA: %04x: ", ssh);
1891 for (i = 0; i < frontadd; i++) {
1892 /* store range list to card */
1893 scanquad = CR_CHAN(chanlist[0]);
1894 /* get channel number; */
1895 gain = CR_RANGE(chanlist[0]);
1896 /* get gain number */
1897 scanquad |= ((gain & 0x03) << 8);
1898 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1899 DPRINTK("%02x ", scanquad | ssh);
1900 ssh = devpriv->softsshhold;
1905 DPRINTK("SL: ", ssh);
1906 for (i = 0; i < n_chan; i++) { /* store range list to card */
1907 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
1908 #ifdef PCI9118_PARANOIDCHECK
1909 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1911 gain = CR_RANGE(chanlist[i]); /* get gain number */
1912 scanquad |= ((gain & 0x03) << 8);
1913 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1914 DPRINTK("%02x ", scanquad | ssh);
1918 if (backadd) { /* insert channels for fit onto 32bit DMA */
1919 DPRINTK("BA: %04x: ", ssh);
1920 for (i = 0; i < backadd; i++) { /* store range list to card */
1921 scanquad = CR_CHAN(chanlist[0]);
1922 /* get channel number */
1923 gain = CR_RANGE(chanlist[0]); /* get gain number */
1924 scanquad |= ((gain & 0x03) << 8);
1925 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1926 DPRINTK("%02x ", scanquad | ssh);
1930 #ifdef PCI9118_PARANOIDCHECK
1931 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
1932 /* for 32bit operations */
1934 for (i = 1; i < n_chan; i++) { /* store range list to card */
1935 devpriv->chanlist[(n_chan + i) ^ usedma] =
1936 (CR_CHAN(chanlist[i]) & 0xf) << rot;
1938 devpriv->chanlist[(2 * n_chan) ^ usedma] =
1939 devpriv->chanlist[0 ^ usedma];
1940 /* for 32bit operations */
1945 #ifdef PCI9118_EXTDEBUG
1947 for (i = 0; i <= (useeos * n_chan); i++)
1948 DPRINTK("%04x ", devpriv->chanlist[i]);
1953 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
1954 /* udelay(100); important delay, or first sample will be crippled */
1956 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1957 return 1; /* we can serve this with scan logic */
1961 ==============================================================================
1962 calculate 8254 divisors if they are used for dual timing
1964 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1965 struct comedi_subdevice *s,
1966 unsigned int *tim1, unsigned int *tim2,
1967 unsigned int flags, int chans,
1968 unsigned int *div1, unsigned int *div2,
1969 char usessh, unsigned int chnsshfront)
1972 ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors"
1973 "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
1974 mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
1978 if (*tim2 < this_board->ai_ns_min)
1979 *tim2 = this_board->ai_ns_min;
1980 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
1981 tim2, flags & TRIG_ROUND_NEAREST);
1982 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
1983 devpriv->i8254_osc_base, *div1, *div2, *tim1);
1986 if (*tim2 < this_board->ai_ns_min)
1987 *tim2 = this_board->ai_ns_min;
1988 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1990 *div1 = *tim2 / devpriv->i8254_osc_base;
1991 /* convert timer (burst) */
1992 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1994 if (*div1 < this_board->ai_pacer_min)
1995 *div1 = this_board->ai_pacer_min;
1996 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1998 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
1999 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2001 *div2 = *div2 / *div1; /* major timer is c1*c2 */
2002 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2006 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2009 *tim2 = *div1 * devpriv->i8254_osc_base;
2010 /* real convert timer */
2012 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
2013 if (*div2 < (chans + 2))
2016 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2018 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
2019 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
2020 devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
2023 DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
2028 ==============================================================================
2030 static void start_pacer(struct comedi_device *dev, int mode,
2031 unsigned int divisor1, unsigned int divisor2)
2033 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
2034 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
2035 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
2038 if ((mode == 1) || (mode == 2) || (mode == 4)) {
2039 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
2040 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
2041 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
2042 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
2047 ==============================================================================
2049 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
2052 return -1; /* incorrect source */
2053 devpriv->exttrg_users |= (1 << source);
2054 devpriv->IntControlReg |= Int_DTrg;
2055 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2056 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2057 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2058 /* allow INT in AMCC */
2063 ==============================================================================
2065 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
2068 return -1; /* incorrect source */
2069 devpriv->exttrg_users &= ~(1 << source);
2070 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
2071 devpriv->IntControlReg &= ~Int_DTrg;
2072 if (!devpriv->IntControlReg) /* all IRQ disabled */
2073 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
2075 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2076 /* disable int in AMCC */
2077 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2083 ==============================================================================
2085 static int pci9118_ai_cancel(struct comedi_device *dev,
2086 struct comedi_subdevice *s)
2088 if (devpriv->usedma)
2089 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
2090 (~EN_A2P_TRANSFERS),
2091 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
2092 pci9118_exttrg_del(dev, EXTTRG_AI);
2093 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
2094 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2095 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2097 * positive triggers, no S&H, no burst,
2098 * burst stop, no post trigger,
2099 * no about trigger, trigger stop
2101 devpriv->AdControlReg = 0x00;
2102 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2104 * bipolar, S.E., use 8254, stop 8354,
2105 * internal trigger, soft trigger,
2106 * disable INT and DMA
2108 outl(0, dev->iobase + PCI9118_BURST);
2109 outl(1, dev->iobase + PCI9118_SCANMOD);
2110 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
2111 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
2114 devpriv->usedma = 0;
2116 devpriv->ai_act_scan = 0;
2117 devpriv->ai_act_dmapos = 0;
2118 s->async->cur_chan = 0;
2119 s->async->inttrig = NULL;
2120 devpriv->ai_buf_ptr = 0;
2121 devpriv->ai_neverending = 0;
2122 devpriv->dma_actbuf = 0;
2124 if (!devpriv->IntControlReg)
2125 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2126 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2127 /* allow INT in AMCC */
2133 ==============================================================================
2135 static int pci9118_reset(struct comedi_device *dev)
2137 devpriv->IntControlReg = 0;
2138 devpriv->exttrg_users = 0;
2139 inl(dev->iobase + PCI9118_INTCTRL);
2140 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2141 /* disable interrupts source */
2142 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
2143 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
2144 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
2145 devpriv->AdControlReg = 0;
2146 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2148 * bipolar, S.E., use 8254,
2149 * stop 8354, internal trigger,
2151 * disable INT and DMA
2153 outl(0, dev->iobase + PCI9118_BURST);
2154 outl(1, dev->iobase + PCI9118_SCANMOD);
2155 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
2156 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2157 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2159 * positive triggers, no S&H,
2160 * no burst, burst stop,
2166 devpriv->ao_data[0] = 2047;
2167 devpriv->ao_data[1] = 2047;
2168 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
2169 /* reset A/D outs to 0V */
2170 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
2171 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
2173 inl(dev->iobase + PCI9118_AD_DATA);
2174 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
2175 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
2176 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
2177 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
2178 devpriv->AdControlReg = 0;
2179 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2181 * bipolar, S.E., use 8254,
2182 * stop 8354, internal trigger,
2184 * disable INT and DMA
2187 devpriv->cnt0_users = 0;
2188 devpriv->exttrg_users = 0;
2194 ==============================================================================
2196 static int pci9118_attach(struct comedi_device *dev,
2197 struct comedi_devconfig *it)
2199 struct comedi_subdevice *s;
2201 unsigned short master;
2203 unsigned long iobase_a, iobase_9;
2204 struct pci_dev *pcidev;
2205 int opt_bus, opt_slot;
2207 unsigned char pci_bus, pci_slot, pci_func;
2210 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
2212 opt_bus = it->options[0];
2213 opt_slot = it->options[1];
2214 if (it->options[3] & 1)
2215 master = 0; /* user don't want use bus master */
2219 ret = alloc_private(dev, sizeof(struct pci9118_private));
2221 printk(" - Allocation failed!\n");
2225 /* Look for matching PCI device */
2226 errstr = "not found!";
2228 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC,
2229 this_board->device_id,
2231 /* Found matching vendor/device. */
2232 if (opt_bus || opt_slot) {
2233 /* Check bus/slot. */
2234 if (opt_bus != pcidev->bus->number
2235 || opt_slot != PCI_SLOT(pcidev->devfn))
2236 continue; /* no match */
2239 * Look for device that isn't in use.
2240 * Enable PCI device and request regions.
2242 if (comedi_pci_enable(pcidev, "adl_pci9118")) {
2244 "failed to enable PCI device and request regions!";
2251 if (opt_bus || opt_slot) {
2252 printk(KERN_ERR " - Card at b:s %d:%d %s\n",
2253 opt_bus, opt_slot, errstr);
2255 printk(KERN_ERR " - Card %s\n", errstr);
2261 pci_set_master(pcidev);
2264 pci_bus = pcidev->bus->number;
2265 pci_slot = PCI_SLOT(pcidev->devfn);
2266 pci_func = PCI_FUNC(pcidev->devfn);
2268 iobase_a = pci_resource_start(pcidev, 0);
2269 iobase_9 = pci_resource_start(pcidev, 2);
2271 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus,
2272 pci_slot, pci_func, iobase_9, iobase_a);
2274 dev->iobase = iobase_9;
2275 dev->board_name = this_board->name;
2277 devpriv->pcidev = pcidev;
2278 devpriv->iobase_a = iobase_a;
2282 if (it->options[3] & 2)
2283 irq = 0; /* user don't want use IRQ */
2285 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
2286 "ADLink PCI-9118", dev)) {
2287 printk(", unable to allocate IRQ %d, DISABLING IT",
2289 irq = 0; /* Can't use IRQ */
2291 printk(", irq=%u", irq);
2294 printk(", IRQ disabled");
2299 if (master) { /* alloc DMA buffers */
2300 devpriv->dma_doublebuf = 0;
2301 for (i = 0; i < 2; i++) {
2302 for (pages = 4; pages >= 0; pages--) {
2303 devpriv->dmabuf_virt[i] =
2304 (short *)__get_free_pages(GFP_KERNEL,
2306 if (devpriv->dmabuf_virt[i])
2309 if (devpriv->dmabuf_virt[i]) {
2310 devpriv->dmabuf_pages[i] = pages;
2311 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2312 devpriv->dmabuf_samples[i] =
2313 devpriv->dmabuf_size[i] >> 1;
2314 devpriv->dmabuf_hw[i] =
2315 virt_to_bus((void *)
2316 devpriv->dmabuf_virt[i]);
2319 if (!devpriv->dmabuf_virt[0]) {
2320 printk(", Can't allocate DMA buffer, DMA disabled!");
2324 if (devpriv->dmabuf_virt[1])
2325 devpriv->dma_doublebuf = 1;
2329 devpriv->master = master;
2330 if (devpriv->master)
2331 printk(", bus master");
2333 printk(", no bus master");
2335 devpriv->usemux = 0;
2336 if (it->options[2] > 0) {
2337 devpriv->usemux = it->options[2];
2338 if (devpriv->usemux > 256)
2339 devpriv->usemux = 256; /* max 256 channels! */
2340 if (it->options[4] > 0)
2341 if (devpriv->usemux > 128) {
2342 devpriv->usemux = 128;
2343 /* max 128 channels with softare S&H! */
2345 printk(", ext. mux %d channels", devpriv->usemux);
2348 devpriv->softsshdelay = it->options[4];
2349 if (devpriv->softsshdelay < 0) {
2350 /* select sample&hold signal polarity */
2351 devpriv->softsshdelay = -devpriv->softsshdelay;
2352 devpriv->softsshsample = 0x80;
2353 devpriv->softsshhold = 0x00;
2355 devpriv->softsshsample = 0x00;
2356 devpriv->softsshhold = 0x80;
2361 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
2362 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);
2363 /* Enable parity check for parity error */
2365 ret = alloc_subdevices(dev, 4);
2369 s = dev->subdevices + 0;
2370 dev->read_subdev = s;
2371 s->type = COMEDI_SUBD_AI;
2372 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2373 if (devpriv->usemux)
2374 s->n_chan = devpriv->usemux;
2376 s->n_chan = this_board->n_aichan;
2378 s->maxdata = this_board->ai_maxdata;
2379 s->len_chanlist = this_board->n_aichanlist;
2380 s->range_table = this_board->rangelist_ai;
2381 s->cancel = pci9118_ai_cancel;
2382 s->insn_read = pci9118_insn_read_ai;
2384 s->subdev_flags |= SDF_CMD_READ;
2385 s->do_cmdtest = pci9118_ai_cmdtest;
2386 s->do_cmd = pci9118_ai_cmd;
2387 s->munge = pci9118_ai_munge;
2390 s = dev->subdevices + 1;
2391 s->type = COMEDI_SUBD_AO;
2392 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2393 s->n_chan = this_board->n_aochan;
2394 s->maxdata = this_board->ao_maxdata;
2395 s->len_chanlist = this_board->n_aochan;
2396 s->range_table = this_board->rangelist_ao;
2397 s->insn_write = pci9118_insn_write_ao;
2398 s->insn_read = pci9118_insn_read_ao;
2400 s = dev->subdevices + 2;
2401 s->type = COMEDI_SUBD_DI;
2402 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2405 s->len_chanlist = 4;
2406 s->range_table = &range_digital;
2407 s->io_bits = 0; /* all bits input */
2408 s->insn_bits = pci9118_insn_bits_di;
2410 s = dev->subdevices + 3;
2411 s->type = COMEDI_SUBD_DO;
2412 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2415 s->len_chanlist = 4;
2416 s->range_table = &range_digital;
2417 s->io_bits = 0xf; /* all bits output */
2418 s->insn_bits = pci9118_insn_bits_do;
2421 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2422 devpriv->ai_maskharderr = 0x10a;
2423 /* default measure crash condition */
2424 if (it->options[5]) /* disable some requested */
2425 devpriv->ai_maskharderr &= ~it->options[5];
2427 switch (this_board->ai_maxdata) {
2429 devpriv->ai16bits = 1;
2432 devpriv->ai16bits = 0;
2439 ==============================================================================
2441 static int pci9118_detach(struct comedi_device *dev)
2447 free_irq(dev->irq, dev);
2448 if (devpriv->pcidev) {
2450 comedi_pci_disable(devpriv->pcidev);
2452 pci_dev_put(devpriv->pcidev);
2454 if (devpriv->dmabuf_virt[0])
2455 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2456 devpriv->dmabuf_pages[0]);
2457 if (devpriv->dmabuf_virt[1])
2458 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2459 devpriv->dmabuf_pages[1]);
2466 ==============================================================================
2469 MODULE_AUTHOR("Comedi http://www.comedi.org");
2470 MODULE_DESCRIPTION("Comedi low-level driver");
2471 MODULE_LICENSE("GPL");