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 neccessary 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>
71 #include "amcc_s5933.h"
73 #include "comedi_pci.h"
74 #include "comedi_fc.h"
76 #define PCI_VENDOR_ID_AMCC 0x10e8
78 /* paranoid checks are broken */
79 #undef PCI9118_PARANOIDCHECK /*
80 * if defined, then is used code which control
81 * correct channel number on every 12 bit sample
84 #undef PCI9118_EXTDEBUG /*
85 * if defined then driver prints
90 #ifdef PCI9118_EXTDEBUG
91 #define DPRINTK(fmt, args...) printk(fmt, ## args)
93 #define DPRINTK(fmt, args...)
96 #define IORANGE_9118 64 /* I hope */
97 #define PCI9118_CHANLEN 255 /*
98 * len of chanlist, some source say 256,
99 * but reality looks like 255 :-(
102 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
103 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
104 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
105 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
106 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
107 #define PCI9118_DA1 0x10 /* W: D/A registers */
108 #define PCI9118_DA2 0x14
109 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
110 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
111 #define PCI9118_DI 0x1c /* R: digi input register */
112 #define PCI9118_DO 0x1c /* W: digi output register */
113 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
114 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
115 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
116 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
117 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
118 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
119 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
120 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
122 /* bits from A/D control register (PCI9118_ADCNTRL) */
123 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
124 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
125 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
126 #define AdControl_ExtG 0x10 /*
127 * 1=8254 countrol controlled by TGIN(pin 46),
128 * 0=controlled by SoftG
130 #define AdControl_ExtM 0x08 /*
131 * 1=external hardware trigger (pin 44),
134 #define AdControl_TmrTr 0x04 /*
135 * 1=8254 is iternal trigger source,
136 * 0=software trigger is source
137 * (register PCI9118_SOFTTRG)
139 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
140 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
142 /* bits from A/D function register (PCI9118_ADFUNC) */
143 #define AdFunction_PDTrg 0x80 /*
145 * 0=negative digital trigger
146 * (only positive is correct)
148 #define AdFunction_PETrg 0x40 /*
150 * 0=negative external trigger
151 * (only positive is correct)
153 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
154 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
155 #define AdFunction_BS 0x08 /*
156 * 1=burst mode start,
159 #define AdFunction_PM 0x04 /*
160 * 1=post trigger mode,
163 #define AdFunction_AM 0x02 /*
164 * 1=about trigger mode,
165 * 0=not about trigger
167 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
169 /* bits from A/D status register (PCI9118_ADSTAT) */
170 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
171 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
172 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
173 #define AdStatus_Acmp 0x020 /* */
174 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
175 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
176 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
177 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
178 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
180 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
181 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
182 #define Int_Timer 0x08 /* timer interrupt */
183 #define Int_About 0x04 /* about trigger complete */
184 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
185 #define Int_DTrg 0x01 /* external digital trigger */
187 #define START_AI_EXT 0x01 /* start measure on external trigger */
188 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
189 #define START_AI_INT 0x04 /* start measure on internal trigger */
190 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
192 #define EXTTRG_AI 0 /* ext trg is used by AI */
194 static const struct comedi_lrange range_pci9118dg_hr = { 8, {
206 static const struct comedi_lrange range_pci9118hg = { 8, {
218 #define PCI9118_BIPOLAR_RANGES 4 /*
219 * used for test on mixture
223 static int pci9118_attach(struct comedi_device *dev,
224 struct comedi_devconfig *it);
225 static int pci9118_detach(struct comedi_device *dev);
228 const char *name; /* board name */
229 int vendor_id; /* PCI vendor a device ID of card */
231 int iorange_amcc; /* iorange for own S5933 region */
232 int iorange_9118; /* pass thru card region size */
233 int n_aichan; /* num of A/D chans */
234 int n_aichand; /* num of A/D chans in diff mode */
236 * num of A/D chans with
237 * external multiplexor
239 int n_aichanlist; /* len of chanlist */
240 int n_aochan; /* num of D/A chans */
241 int ai_maxdata; /* resolution of A/D */
242 int ao_maxdata; /* resolution of D/A */
243 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
244 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
245 unsigned int ai_ns_min; /* max sample speed of card v ns */
246 unsigned int ai_pacer_min; /*
247 * minimal pacer value
248 * (c1*c2 or c1 in burst)
250 int half_fifo_size; /* size of FIFO/2 */
254 static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
255 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
259 MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
261 static const struct boardtype boardtypes[] = {
262 {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
263 AMCC_OP_REG_SIZE, IORANGE_9118,
264 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
265 &range_pci9118dg_hr, &range_bipolar10,
267 {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
268 AMCC_OP_REG_SIZE, IORANGE_9118,
269 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
270 &range_pci9118hg, &range_bipolar10,
272 {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
273 AMCC_OP_REG_SIZE, IORANGE_9118,
274 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
275 &range_pci9118dg_hr, &range_bipolar10,
279 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
281 static struct comedi_driver driver_pci9118 = {
282 .driver_name = "adl_pci9118",
283 .module = THIS_MODULE,
284 .attach = pci9118_attach,
285 .detach = pci9118_detach,
286 .num_names = n_boardtypes,
287 .board_name = &boardtypes[0].name,
288 .offset = sizeof(struct boardtype),
291 static int __devinit driver_pci9118_pci_probe(struct pci_dev *dev,
292 const struct pci_device_id *ent)
294 return comedi_pci_auto_config(dev, driver_pci9118.driver_name);
297 static void __devexit driver_pci9118_pci_remove(struct pci_dev *dev)
299 comedi_pci_auto_unconfig(dev);
302 static struct pci_driver driver_pci9118_pci_driver = {
303 .id_table = pci9118_pci_table,
304 .probe = &driver_pci9118_pci_probe,
305 .remove = __devexit_p(&driver_pci9118_pci_remove)
308 static int __init driver_pci9118_init_module(void)
312 retval = comedi_driver_register(&driver_pci9118);
316 driver_pci9118_pci_driver.name = (char *)driver_pci9118.driver_name;
317 return pci_register_driver(&driver_pci9118_pci_driver);
320 static void __exit driver_pci9118_cleanup_module(void)
322 pci_unregister_driver(&driver_pci9118_pci_driver);
323 comedi_driver_unregister(&driver_pci9118);
326 module_init(driver_pci9118_init_module);
327 module_exit(driver_pci9118_cleanup_module);
329 struct pci9118_private {
330 unsigned long iobase_a; /* base+size for AMCC chip */
331 unsigned int master; /* master capable */
332 struct pci_dev *pcidev; /* ptr to actual pcidev */
333 unsigned int usemux; /* we want to use external multiplexor! */
334 #ifdef PCI9118_PARANOIDCHECK
335 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
339 unsigned char chanlistlen; /* number of scanlist */
341 unsigned char AdControlReg; /* A/D control register */
342 unsigned char IntControlReg; /* Interrupt control register */
343 unsigned char AdFunctionReg; /* A/D function register */
344 char valid; /* driver is ok */
345 char ai_neverending; /* we do unlimited AI */
346 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
347 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
348 unsigned int ai_act_scan; /* how many scans we finished */
349 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
350 unsigned int ai_n_chan; /* how many channels is measured */
351 unsigned int ai_n_scanlen; /* len of actual scanlist */
352 unsigned int ai_n_realscanlen; /*
353 * what we must transfer for one
354 * outgoing scan include front/back adds
356 unsigned int ai_act_dmapos; /* position in actual real stream */
357 unsigned int ai_add_front; /*
358 * how many channels we must add
359 * before scan to satisfy S&H?
361 unsigned int ai_add_back; /*
362 * how many channels we must add
363 * before scan to satisfy DMA?
365 unsigned int *ai_chanlist; /* actual chanlist */
366 unsigned int ai_timer1;
367 unsigned int ai_timer2;
368 unsigned int ai_flags;
369 char ai12_startstop; /*
370 * measure can start/stop
371 * on external trigger
373 unsigned int ai_divisor1, ai_divisor2; /*
374 * divisors for start of measure
377 unsigned int ai_data_len;
379 short ao_data[2]; /* data output buffer */
380 unsigned int ai_scans; /* number of scans to do */
381 char dma_doublebuf; /* we can use double buffring */
382 unsigned int dma_actbuf; /* which buffer is used now */
383 short *dmabuf_virt[2]; /*
384 * pointers to begin of
387 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
388 unsigned int dmabuf_size[2]; /*
389 * size of dma buffer in bytes
391 unsigned int dmabuf_use_size[2]; /*
392 * which size we may now use
395 unsigned int dmabuf_used_size[2]; /* which size was truly used */
396 unsigned int dmabuf_panic_size[2];
397 unsigned int dmabuf_samples[2]; /* size in samples */
398 int dmabuf_pages[2]; /* number of pages in buffer */
399 unsigned char cnt0_users; /*
400 * bit field of 8254 CNT0 users
401 * (0-unused, 1-AO, 2-DI, 3-DO)
403 unsigned char exttrg_users; /*
404 * bit field of external trigger
405 * users(0-AI, 1-AO, 2-DI, 3-DO)
407 unsigned int cnt0_divisor; /* actual CNT0 divisor */
408 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
412 * ptr to actual interrupt
415 unsigned char ai16bits; /* =1 16 bit card */
416 unsigned char usedma; /* =1 use DMA transfer and not INT */
417 unsigned char useeoshandle; /*
418 * =1 change WAKE_EOS DMA transfer
419 * to fit on every second
421 unsigned char usessh; /* =1 turn on S&H support */
423 * >0 use software S&H,
424 * numer is requested delay in ns
426 unsigned char softsshsample; /*
427 * polarity of S&H signal
430 unsigned char softsshhold; /*
431 * polarity of S&H signal
434 unsigned int ai_maskerr; /* which warning was printed */
435 unsigned int ai_maskharderr; /* on which error bits stops */
436 unsigned int ai_inttrig_start; /* TRIG_INT for start */
439 #define devpriv ((struct pci9118_private *)dev->private)
440 #define this_board ((struct boardtype *)dev->board_ptr)
443 ==============================================================================
446 static int check_channel_list(struct comedi_device *dev,
447 struct comedi_subdevice *s, int n_chan,
448 unsigned int *chanlist, int frontadd,
450 static int setup_channel_list(struct comedi_device *dev,
451 struct comedi_subdevice *s, int n_chan,
452 unsigned int *chanlist, int rot, int frontadd,
453 int backadd, int usedma, char eoshandle);
454 static void start_pacer(struct comedi_device *dev, int mode,
455 unsigned int divisor1, unsigned int divisor2);
456 static int pci9118_reset(struct comedi_device *dev);
457 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
458 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
459 static int pci9118_ai_cancel(struct comedi_device *dev,
460 struct comedi_subdevice *s);
461 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
462 struct comedi_subdevice *s,
463 unsigned int *tim1, unsigned int *tim2,
464 unsigned int flags, int chans,
465 unsigned int *div1, unsigned int *div2,
466 char usessh, unsigned int chnsshfront);
469 ==============================================================================
471 static int pci9118_insn_read_ai(struct comedi_device *dev,
472 struct comedi_subdevice *s,
473 struct comedi_insn *insn, unsigned int *data)
478 devpriv->AdControlReg = AdControl_Int & 0xff;
479 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
480 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
482 * positive triggers, no S&H,
483 * no burst, burst stop,
489 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
492 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
494 for (n = 0; n < insn->n; n++) {
495 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
499 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
504 comedi_error(dev, "A/D insn timeout");
506 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
510 if (devpriv->ai16bits) {
513 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
516 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
520 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
526 ==============================================================================
528 static int pci9118_insn_write_ao(struct comedi_device *dev,
529 struct comedi_subdevice *s,
530 struct comedi_insn *insn, unsigned int *data)
534 ch = CR_CHAN(insn->chanspec);
536 chanreg = PCI9118_DA2;
538 chanreg = PCI9118_DA1;
541 for (n = 0; n < insn->n; n++) {
542 outl(data[n], dev->iobase + chanreg);
543 devpriv->ao_data[ch] = data[n];
550 ==============================================================================
552 static int pci9118_insn_read_ao(struct comedi_device *dev,
553 struct comedi_subdevice *s,
554 struct comedi_insn *insn, unsigned int *data)
558 chan = CR_CHAN(insn->chanspec);
559 for (n = 0; n < insn->n; n++)
560 data[n] = devpriv->ao_data[chan];
566 ==============================================================================
568 static int pci9118_insn_bits_di(struct comedi_device *dev,
569 struct comedi_subdevice *s,
570 struct comedi_insn *insn, unsigned int *data)
572 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
578 ==============================================================================
580 static int pci9118_insn_bits_do(struct comedi_device *dev,
581 struct comedi_subdevice *s,
582 struct comedi_insn *insn, unsigned int *data)
585 s->state &= ~data[0];
586 s->state |= (data[0] & data[1]);
587 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
595 ==============================================================================
597 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
599 devpriv->AdFunctionReg =
600 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
601 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
602 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
603 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
604 dev->iobase + PCI9118_CNT0);
605 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
606 dev->iobase + PCI9118_CNT0);
607 devpriv->AdFunctionReg |= AdFunction_Start;
608 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
611 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
612 struct comedi_subdevice *s,
614 unsigned int num_samples)
616 unsigned int i = 0, j = 0;
617 unsigned int start_pos = devpriv->ai_add_front,
618 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
619 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
620 devpriv->ai_add_back;
622 for (i = 0; i < num_samples; i++) {
623 if (devpriv->ai_act_dmapos >= start_pos &&
624 devpriv->ai_act_dmapos < stop_pos) {
625 dma_buffer[j++] = dma_buffer[i];
627 devpriv->ai_act_dmapos++;
628 devpriv->ai_act_dmapos %= raw_scanlen;
635 ==============================================================================
637 static int move_block_from_dma(struct comedi_device *dev,
638 struct comedi_subdevice *s,
640 unsigned int num_samples)
642 unsigned int num_bytes;
644 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
645 devpriv->ai_act_scan +=
646 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
647 s->async->cur_chan += num_samples;
648 s->async->cur_chan %= devpriv->ai_n_scanlen;
650 cfc_write_array_to_buffer(s, dma_buffer,
651 num_samples * sizeof(short));
652 if (num_bytes < num_samples * sizeof(short))
658 ==============================================================================
660 static char pci9118_decode_error_status(struct comedi_device *dev,
661 struct comedi_subdevice *s,
665 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
666 devpriv->ai_maskerr &= ~0x100L;
670 "A/D Burst Mode Overrun Status (Fatal Error!)");
671 devpriv->ai_maskerr &= ~0x008L;
674 comedi_error(dev, "A/D Over Speed Status (Warning!)");
675 devpriv->ai_maskerr &= ~0x004L;
678 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
679 devpriv->ai_maskerr &= ~0x002L;
681 if (m & devpriv->ai_maskharderr) {
682 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
683 pci9118_ai_cancel(dev, s);
684 comedi_event(dev, s);
691 static void pci9118_ai_munge(struct comedi_device *dev,
692 struct comedi_subdevice *s, void *data,
693 unsigned int num_bytes,
694 unsigned int start_chan_index)
696 unsigned int i, num_samples = num_bytes / sizeof(short);
699 for (i = 0; i < num_samples; i++) {
701 array[i] = be16_to_cpu(array[i]);
702 if (devpriv->ai16bits)
705 array[i] = (array[i] >> 4) & 0x0fff;
711 ==============================================================================
713 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
714 struct comedi_subdevice *s,
715 unsigned short int_adstat,
716 unsigned int int_amcc,
717 unsigned short int_daq)
719 register short sampl;
721 s->async->events = 0;
723 if (int_adstat & devpriv->ai_maskerr)
724 if (pci9118_decode_error_status(dev, s, int_adstat))
727 sampl = inw(dev->iobase + PCI9118_AD_DATA);
729 #ifdef PCI9118_PARANOIDCHECK
730 if (devpriv->ai16bits == 0) {
731 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
734 ("comedi: A/D SAMPL - data dropout: "
735 "received channel %d, expected %d!\n",
737 devpriv->chanlist[s->async->cur_chan]);
738 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
739 pci9118_ai_cancel(dev, s);
740 comedi_event(dev, s);
745 cfc_write_to_buffer(s, sampl);
746 s->async->cur_chan++;
747 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
749 s->async->cur_chan %= devpriv->ai_n_scanlen;
750 devpriv->ai_act_scan++;
751 if (!(devpriv->ai_neverending))
752 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
753 /* all data sampled */
754 pci9118_ai_cancel(dev, s);
755 s->async->events |= COMEDI_CB_EOA;
759 if (s->async->events)
760 comedi_event(dev, s);
764 ==============================================================================
766 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
767 struct comedi_subdevice *s,
768 unsigned short int_adstat,
769 unsigned int int_amcc,
770 unsigned short int_daq)
772 unsigned int next_dma_buf, samplesinbuf, sampls, m;
774 if (int_amcc & MASTER_ABORT_INT) {
775 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
776 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
777 pci9118_ai_cancel(dev, s);
778 comedi_event(dev, s);
782 if (int_amcc & TARGET_ABORT_INT) {
783 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
784 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
785 pci9118_ai_cancel(dev, s);
786 comedi_event(dev, s);
789 if (int_adstat & devpriv->ai_maskerr)
790 /* if (int_adstat & 0x106) */
791 if (pci9118_decode_error_status(dev, s, int_adstat))
794 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
795 /* number of received real samples */
796 /* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
798 if (devpriv->dma_doublebuf) { /*
799 * switch DMA buffers if is used
802 next_dma_buf = 1 - devpriv->dma_actbuf;
803 outl(devpriv->dmabuf_hw[next_dma_buf],
804 devpriv->iobase_a + AMCC_OP_REG_MWAR);
805 outl(devpriv->dmabuf_use_size[next_dma_buf],
806 devpriv->iobase_a + AMCC_OP_REG_MWTC);
807 devpriv->dmabuf_used_size[next_dma_buf] =
808 devpriv->dmabuf_use_size[next_dma_buf];
809 if (devpriv->ai_do == 4)
810 interrupt_pci9118_ai_mode4_switch(dev);
814 m = devpriv->ai_data_len >> 1; /*
815 * how many samples is to
819 * DPRINTK("samps=%d m=%d %d %d\n",
820 * samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
823 move_block_from_dma(dev, s,
824 devpriv->dmabuf_virt[devpriv->dma_actbuf],
826 m = m - sampls; /* m= how many samples was transfered */
828 /* DPRINTK("YYY\n"); */
830 if (!devpriv->ai_neverending)
831 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
832 /* all data sampled */
833 pci9118_ai_cancel(dev, s);
834 s->async->events |= COMEDI_CB_EOA;
837 if (devpriv->dma_doublebuf) { /* switch dma buffers */
838 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
839 } else { /* restart DMA if is not used double buffering */
840 outl(devpriv->dmabuf_hw[0],
841 devpriv->iobase_a + AMCC_OP_REG_MWAR);
842 outl(devpriv->dmabuf_use_size[0],
843 devpriv->iobase_a + AMCC_OP_REG_MWTC);
844 if (devpriv->ai_do == 4)
845 interrupt_pci9118_ai_mode4_switch(dev);
848 comedi_event(dev, s);
852 ==============================================================================
854 static irqreturn_t interrupt_pci9118(int irq, void *d)
856 struct comedi_device *dev = d;
857 unsigned int int_daq = 0, int_amcc, int_adstat;
860 return IRQ_NONE; /* not fully initialized */
862 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
863 /* get IRQ reasons from card */
864 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
865 /* get INT register from AMCC chip */
868 * DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x
869 * MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n",
870 * int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR),
871 * inl(devpriv->iobase_a+AMCC_OP_REG_MWTC),
872 * inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
875 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
876 return IRQ_NONE; /* interrupt from other source */
878 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
879 /* shutdown IRQ reasons in AMCC */
881 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
882 /* get STATUS register */
884 if (devpriv->ai_do) {
885 if (devpriv->ai12_startstop)
886 if ((int_adstat & AdStatus_DTH) &&
887 (int_daq & Int_DTrg)) {
888 /* start stop of measure */
889 if (devpriv->ai12_startstop & START_AI_EXT) {
890 devpriv->ai12_startstop &=
892 if (!(devpriv->ai12_startstop &
896 /* deactivate EXT trigger */
897 start_pacer(dev, devpriv->ai_do,
898 devpriv->ai_divisor1,
899 devpriv->ai_divisor2);
901 outl(devpriv->AdControlReg,
902 dev->iobase + PCI9118_ADCNTRL);
904 if (devpriv->ai12_startstop &
906 devpriv->ai12_startstop &=
910 /* deactivate EXT trigger */
911 devpriv->ai_neverending = 0;
913 * well, on next interrupt from
914 * DMA/EOC measure will stop
920 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
928 ==============================================================================
930 static int pci9118_ai_inttrig(struct comedi_device *dev,
931 struct comedi_subdevice *s, unsigned int trignum)
933 if (trignum != devpriv->ai_inttrig_start)
936 devpriv->ai12_startstop &= ~START_AI_INT;
937 s->async->inttrig = NULL;
939 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
940 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
941 if (devpriv->ai_do != 3) {
942 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
943 devpriv->ai_divisor2);
944 devpriv->AdControlReg |= AdControl_SoftG;
946 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
952 ==============================================================================
954 static int pci9118_ai_cmdtest(struct comedi_device *dev,
955 struct comedi_subdevice *s,
956 struct comedi_cmd *cmd)
960 unsigned int divisor1 = 0, divisor2 = 0;
962 /* step 1: make sure trigger sources are trivially valid */
964 tmp = cmd->start_src;
965 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
966 if (!cmd->start_src || tmp != cmd->start_src)
969 tmp = cmd->scan_begin_src;
971 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
973 cmd->scan_begin_src &= TRIG_FOLLOW;
975 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
978 tmp = cmd->convert_src;
980 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
982 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
984 if (!cmd->convert_src || tmp != cmd->convert_src)
987 tmp = cmd->scan_end_src;
988 cmd->scan_end_src &= TRIG_COUNT;
989 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
993 cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
994 if (!cmd->stop_src || tmp != cmd->stop_src)
1002 * make sure trigger sources are
1003 * unique and mutually compatible
1006 if (cmd->start_src != TRIG_NOW &&
1007 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
1008 cmd->start_src = TRIG_NOW;
1012 if (cmd->scan_begin_src != TRIG_TIMER &&
1013 cmd->scan_begin_src != TRIG_EXT &&
1014 cmd->scan_begin_src != TRIG_INT &&
1015 cmd->scan_begin_src != TRIG_FOLLOW) {
1016 cmd->scan_begin_src = TRIG_FOLLOW;
1020 if (cmd->convert_src != TRIG_TIMER &&
1021 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
1022 cmd->convert_src = TRIG_TIMER;
1026 if (cmd->scan_end_src != TRIG_COUNT) {
1027 cmd->scan_end_src = TRIG_COUNT;
1031 if (cmd->stop_src != TRIG_NONE &&
1032 cmd->stop_src != TRIG_COUNT &&
1033 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
1034 cmd->stop_src = TRIG_COUNT;
1038 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1039 cmd->start_src = TRIG_NOW;
1043 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
1044 cmd->start_src = TRIG_NOW;
1048 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
1049 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
1050 cmd->convert_src = TRIG_TIMER;
1054 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
1055 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
1056 cmd->convert_src = TRIG_TIMER;
1060 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
1061 cmd->stop_src = TRIG_COUNT;
1068 /* step 3: make sure arguments are trivially compatible */
1070 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
1071 if (cmd->start_arg != 0) {
1076 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
1077 if (cmd->scan_begin_arg != 0) {
1078 cmd->scan_begin_arg = 0;
1082 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1083 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
1084 cmd->scan_begin_src = TRIG_FOLLOW;
1085 cmd->convert_arg = cmd->scan_begin_arg;
1086 cmd->scan_begin_arg = 0;
1089 if (cmd->scan_begin_src == TRIG_TIMER)
1090 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1091 cmd->scan_begin_arg = this_board->ai_ns_min;
1095 if (cmd->scan_begin_src == TRIG_EXT)
1096 if (cmd->scan_begin_arg) {
1097 cmd->scan_begin_arg = 0;
1099 if (cmd->scan_end_arg > 65535) {
1100 cmd->scan_end_arg = 65535;
1105 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1106 if (cmd->convert_arg < this_board->ai_ns_min) {
1107 cmd->convert_arg = this_board->ai_ns_min;
1111 if (cmd->convert_src == TRIG_EXT)
1112 if (cmd->convert_arg) {
1113 cmd->convert_arg = 0;
1117 if (cmd->stop_src == TRIG_COUNT) {
1118 if (!cmd->stop_arg) {
1122 } else { /* TRIG_NONE */
1123 if (cmd->stop_arg != 0) {
1129 if (!cmd->chanlist_len) {
1130 cmd->chanlist_len = 1;
1134 if (cmd->chanlist_len > this_board->n_aichanlist) {
1135 cmd->chanlist_len = this_board->n_aichanlist;
1139 if (cmd->scan_end_arg < cmd->chanlist_len) {
1140 cmd->scan_end_arg = cmd->chanlist_len;
1144 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1146 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
1153 /* step 4: fix up any arguments */
1155 if (cmd->scan_begin_src == TRIG_TIMER) {
1156 tmp = cmd->scan_begin_arg;
1157 /* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1158 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1159 &divisor2, &cmd->scan_begin_arg,
1160 cmd->flags & TRIG_ROUND_MASK);
1161 /* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1162 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1163 cmd->scan_begin_arg = this_board->ai_ns_min;
1164 if (tmp != cmd->scan_begin_arg)
1168 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1169 tmp = cmd->convert_arg;
1170 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
1171 &divisor2, &cmd->convert_arg,
1172 cmd->flags & TRIG_ROUND_MASK);
1173 /* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1174 if (cmd->convert_arg < this_board->ai_ns_min)
1175 cmd->convert_arg = this_board->ai_ns_min;
1176 if (tmp != cmd->convert_arg)
1178 if (cmd->scan_begin_src == TRIG_TIMER
1179 && cmd->convert_src == TRIG_NOW) {
1180 if (cmd->convert_arg == 0) {
1181 if (cmd->scan_begin_arg <
1182 this_board->ai_ns_min *
1183 (cmd->scan_end_arg + 2)) {
1184 cmd->scan_begin_arg =
1185 this_board->ai_ns_min *
1186 (cmd->scan_end_arg + 2);
1187 /* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1191 if (cmd->scan_begin_arg <
1192 cmd->convert_arg * cmd->chanlist_len) {
1193 cmd->scan_begin_arg =
1196 /* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1207 if (!check_channel_list(dev, s, cmd->chanlist_len,
1208 cmd->chanlist, 0, 0))
1209 return 5; /* incorrect channels list */
1215 ==============================================================================
1217 static int Compute_and_setup_dma(struct comedi_device *dev)
1219 unsigned int dmalen0, dmalen1, i;
1221 DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
1222 dmalen0 = devpriv->dmabuf_size[0];
1223 dmalen1 = devpriv->dmabuf_size[1];
1224 DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
1225 devpriv->ai_data_len);
1226 /* isn't output buff smaller that our DMA buff? */
1227 if (dmalen0 > (devpriv->ai_data_len)) {
1228 dmalen0 = devpriv->ai_data_len & ~3L; /*
1229 * align to 32bit down
1232 if (dmalen1 > (devpriv->ai_data_len)) {
1233 dmalen1 = devpriv->ai_data_len & ~3L; /*
1234 * align to 32bit down
1237 DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1239 /* we want wake up every scan? */
1240 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1241 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1242 /* uff, too short DMA buffer, disable EOS support! */
1243 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1245 ("comedi%d: WAR: DMA0 buf too short, can't "
1246 "support TRIG_WAKE_EOS (%d<%d)\n",
1247 dev->minor, dmalen0,
1248 devpriv->ai_n_realscanlen << 1);
1250 /* short first DMA buffer to one scan */
1251 dmalen0 = devpriv->ai_n_realscanlen << 1;
1253 ("21 dmalen0=%d ai_n_realscanlen=%d "
1254 "useeoshandle=%d\n",
1255 dmalen0, devpriv->ai_n_realscanlen,
1256 devpriv->useeoshandle);
1257 if (devpriv->useeoshandle)
1261 ("comedi%d: ERR: DMA0 buf len bug? "
1263 dev->minor, dmalen0);
1268 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1269 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1270 /* uff, too short DMA buffer, disable EOS support! */
1271 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1273 ("comedi%d: WAR: DMA1 buf too short, "
1274 "can't support TRIG_WAKE_EOS (%d<%d)\n",
1275 dev->minor, dmalen1,
1276 devpriv->ai_n_realscanlen << 1);
1278 /* short second DMA buffer to one scan */
1279 dmalen1 = devpriv->ai_n_realscanlen << 1;
1281 ("22 dmalen1=%d ai_n_realscanlen=%d "
1282 "useeoshandle=%d\n",
1283 dmalen1, devpriv->ai_n_realscanlen,
1284 devpriv->useeoshandle);
1285 if (devpriv->useeoshandle)
1289 ("comedi%d: ERR: DMA1 buf len bug? "
1291 dev->minor, dmalen1);
1297 DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1298 /* transfer without TRIG_WAKE_EOS */
1299 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1300 /* if it's possible then allign DMA buffers to length of scan */
1303 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1304 (devpriv->ai_n_realscanlen << 1);
1307 dmalen0 = i; /* uff. very long scan? */
1310 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1311 (devpriv->ai_n_realscanlen << 1);
1314 dmalen1 = i; /* uff. very long scan? */
1316 * if measure isn't neverending then test, if it fits whole
1317 * into one or two DMA buffers
1319 if (!devpriv->ai_neverending) {
1320 /* fits whole measure into one DMA buffer? */
1322 ((devpriv->ai_n_realscanlen << 1) *
1323 devpriv->ai_scans)) {
1325 ("3.0 ai_n_realscanlen=%d ai_scans=%d\n",
1326 devpriv->ai_n_realscanlen,
1329 (devpriv->ai_n_realscanlen << 1) *
1331 DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0,
1335 * fits whole measure into
1339 ((devpriv->ai_n_realscanlen << 1) *
1340 devpriv->ai_scans - dmalen0))
1342 (devpriv->ai_n_realscanlen << 1) *
1343 devpriv->ai_scans - dmalen0;
1344 DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0,
1351 DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1353 /* these DMA buffer size will be used */
1354 devpriv->dma_actbuf = 0;
1355 devpriv->dmabuf_use_size[0] = dmalen0;
1356 devpriv->dmabuf_use_size[1] = dmalen1;
1358 DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
1360 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1361 devpriv->dmabuf_panic_size[0] =
1362 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1363 1) * devpriv->ai_n_scanlen * sizeof(short);
1364 devpriv->dmabuf_panic_size[1] =
1365 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1366 1) * devpriv->ai_n_scanlen * sizeof(short);
1368 devpriv->dmabuf_panic_size[0] =
1369 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1370 devpriv->dmabuf_panic_size[1] =
1371 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1375 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1376 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1377 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1378 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1379 /* init DMA transfer */
1380 outl(0x00000000 | AINT_WRITE_COMPL,
1381 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1382 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1384 outl(inl(devpriv->iobase_a +
1385 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1386 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1387 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1388 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1389 /* allow bus mastering */
1391 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1396 ==============================================================================
1398 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1399 struct comedi_subdevice *s)
1401 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
1402 dev->minor, devpriv->ai_do);
1403 switch (devpriv->ai_do) {
1405 devpriv->AdControlReg |= AdControl_TmrTr;
1408 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1411 devpriv->AdControlReg |= AdControl_ExtM;
1414 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1418 "pci9118_ai_docmd_sampl() mode number bug!\n");
1422 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1423 /* transfer function */
1425 if (devpriv->ai12_startstop)
1426 pci9118_exttrg_add(dev, EXTTRG_AI);
1427 /* activate EXT trigger */
1429 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1430 devpriv->IntControlReg |= Int_Timer;
1432 devpriv->AdControlReg |= AdControl_Int;
1434 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1435 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1436 /* allow INT in AMCC */
1438 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1439 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1440 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1441 if (devpriv->ai_do != 3) {
1442 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1443 devpriv->ai_divisor2);
1444 devpriv->AdControlReg |= AdControl_SoftG;
1446 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1449 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
1454 ==============================================================================
1456 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1457 struct comedi_subdevice *s)
1459 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
1460 dev->minor, devpriv->ai_do, devpriv->usedma);
1461 Compute_and_setup_dma(dev);
1463 switch (devpriv->ai_do) {
1465 devpriv->AdControlReg |=
1466 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1469 devpriv->AdControlReg |=
1470 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1471 devpriv->AdFunctionReg =
1472 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1474 if (devpriv->usessh && (!devpriv->softsshdelay))
1475 devpriv->AdFunctionReg |= AdFunction_BSSH;
1476 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1479 devpriv->AdControlReg |=
1480 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1481 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1484 devpriv->AdControlReg |=
1485 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1486 devpriv->AdFunctionReg =
1487 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1488 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1489 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1490 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1491 dev->iobase + PCI9118_CNT0);
1492 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1493 dev->iobase + PCI9118_CNT0);
1494 devpriv->AdFunctionReg |= AdFunction_Start;
1497 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1501 if (devpriv->ai12_startstop) {
1502 pci9118_exttrg_add(dev, EXTTRG_AI);
1503 /* activate EXT trigger */
1506 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1507 /* transfer function */
1509 outl(0x02000000 | AINT_WRITE_COMPL,
1510 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1512 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1513 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1514 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1515 if (devpriv->ai_do != 3) {
1516 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1517 devpriv->ai_divisor2);
1518 devpriv->AdControlReg |= AdControl_SoftG;
1520 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1523 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
1528 ==============================================================================
1530 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1532 struct comedi_cmd *cmd = &s->async->cmd;
1533 unsigned int addchans = 0;
1536 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
1537 devpriv->ai12_startstop = 0;
1538 devpriv->ai_flags = cmd->flags;
1539 devpriv->ai_n_chan = cmd->chanlist_len;
1540 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1541 devpriv->ai_chanlist = cmd->chanlist;
1542 devpriv->ai_data = s->async->prealloc_buf;
1543 devpriv->ai_data_len = s->async->prealloc_bufsz;
1544 devpriv->ai_timer1 = 0;
1545 devpriv->ai_timer2 = 0;
1546 devpriv->ai_add_front = 0;
1547 devpriv->ai_add_back = 0;
1548 devpriv->ai_maskerr = 0x10e;
1550 /* prepare for start/stop conditions */
1551 if (cmd->start_src == TRIG_EXT)
1552 devpriv->ai12_startstop |= START_AI_EXT;
1553 if (cmd->stop_src == TRIG_EXT) {
1554 devpriv->ai_neverending = 1;
1555 devpriv->ai12_startstop |= STOP_AI_EXT;
1557 if (cmd->start_src == TRIG_INT) {
1558 devpriv->ai12_startstop |= START_AI_INT;
1559 devpriv->ai_inttrig_start = cmd->start_arg;
1560 s->async->inttrig = pci9118_ai_inttrig;
1563 if (cmd->stop_src == TRIG_INT) {
1564 devpriv->ai_neverending = 1;
1565 devpriv->ai12_startstop |= STOP_AI_INT;
1568 if (cmd->stop_src == TRIG_NONE)
1569 devpriv->ai_neverending = 1;
1570 if (cmd->stop_src == TRIG_COUNT) {
1571 devpriv->ai_scans = cmd->stop_arg;
1572 devpriv->ai_neverending = 0;
1574 devpriv->ai_scans = 0;
1577 /* use sample&hold signal? */
1578 if (cmd->convert_src == TRIG_NOW)
1579 devpriv->usessh = 1;
1582 devpriv->usessh = 0;
1585 DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
1586 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
1587 devpriv->ai12_startstop);
1590 * use additional sample at end of every scan
1591 * to satisty DMA 32 bit transfer?
1593 devpriv->ai_add_front = 0;
1594 devpriv->ai_add_back = 0;
1595 devpriv->useeoshandle = 0;
1596 if (devpriv->master) {
1597 devpriv->usedma = 1;
1598 if ((cmd->flags & TRIG_WAKE_EOS) &&
1599 (devpriv->ai_n_scanlen == 1)) {
1600 if (cmd->convert_src == TRIG_NOW)
1601 devpriv->ai_add_back = 1;
1602 if (cmd->convert_src == TRIG_TIMER) {
1603 devpriv->usedma = 0;
1605 * use INT transfer if scanlist
1606 * have only one channel
1610 if ((cmd->flags & TRIG_WAKE_EOS) &&
1611 (devpriv->ai_n_scanlen & 1) &&
1612 (devpriv->ai_n_scanlen > 1)) {
1613 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1615 * vpriv->useeoshandle=1; // change DMA transfer
1616 * block to fit EOS on every second call
1618 devpriv->usedma = 0;
1620 * XXX maybe can be corrected to use 16 bit DMA
1623 * well, we must insert one sample
1624 * to end of EOS to meet 32 bit transfer
1626 devpriv->ai_add_back = 1;
1629 } else { /* interrupt transfer don't need any correction */
1630 devpriv->usedma = 0;
1634 * we need software S&H signal?
1635 * It adds two samples before every scan as minimum
1637 if (devpriv->usessh && devpriv->softsshdelay) {
1638 devpriv->ai_add_front = 2;
1639 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1640 /* move it to front */
1641 devpriv->ai_add_front++;
1642 devpriv->ai_add_back = 0;
1644 if (cmd->convert_arg < this_board->ai_ns_min)
1645 cmd->convert_arg = this_board->ai_ns_min;
1646 addchans = devpriv->softsshdelay / cmd->convert_arg;
1647 if (devpriv->softsshdelay % cmd->convert_arg)
1649 if (addchans > (devpriv->ai_add_front - 1)) {
1650 /* uff, still short */
1651 devpriv->ai_add_front = addchans + 1;
1652 if (devpriv->usedma == 1)
1653 if ((devpriv->ai_add_front +
1654 devpriv->ai_n_chan +
1655 devpriv->ai_add_back) & 1)
1656 devpriv->ai_add_front++;
1657 /* round up to 32 bit */
1660 /* well, we now know what must be all added */
1661 devpriv->ai_n_realscanlen = /*
1662 * what we must take from card in real
1663 * to have ai_n_scanlen on output?
1665 (devpriv->ai_add_front + devpriv->ai_n_chan +
1666 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1667 devpriv->ai_n_chan);
1669 DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
1671 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
1672 devpriv->ai_n_chan, devpriv->ai_add_back,
1673 devpriv->ai_n_scanlen);
1675 /* check and setup channel list */
1676 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1677 devpriv->ai_chanlist, devpriv->ai_add_front,
1678 devpriv->ai_add_back))
1680 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1681 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1682 devpriv->ai_add_back, devpriv->usedma,
1683 devpriv->useeoshandle))
1686 /* compute timers settings */
1688 * simplest way, fr=4Mhz/(tim1*tim2),
1689 * channel manipulation without timers effect
1691 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1692 (cmd->scan_begin_src == TRIG_EXT) ||
1693 (cmd->scan_begin_src == TRIG_INT)) &&
1694 (cmd->convert_src == TRIG_TIMER)) {
1695 /* both timer is used for one time */
1696 if (cmd->scan_begin_src == TRIG_EXT)
1700 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1701 &cmd->scan_begin_arg, &cmd->convert_arg,
1703 devpriv->ai_n_realscanlen,
1704 &devpriv->ai_divisor1,
1705 &devpriv->ai_divisor2, devpriv->usessh,
1706 devpriv->ai_add_front);
1707 devpriv->ai_timer2 = cmd->convert_arg;
1710 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1711 ((cmd->convert_src == TRIG_TIMER) ||
1712 (cmd->convert_src == TRIG_NOW))) {
1713 /* double timed action */
1714 if (!devpriv->usedma) {
1716 "cmd->scan_begin_src=TRIG_TIMER works "
1717 "only with bus mastering!");
1722 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1723 &cmd->scan_begin_arg, &cmd->convert_arg,
1725 devpriv->ai_n_realscanlen,
1726 &devpriv->ai_divisor1,
1727 &devpriv->ai_divisor2, devpriv->usessh,
1728 devpriv->ai_add_front);
1729 devpriv->ai_timer1 = cmd->scan_begin_arg;
1730 devpriv->ai_timer2 = cmd->convert_arg;
1733 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1734 && (cmd->convert_src == TRIG_EXT)) {
1738 start_pacer(dev, -1, 0, 0); /* stop pacer */
1740 devpriv->AdControlReg = 0; /*
1741 * bipolar, S.E., use 8254, stop 8354,
1742 * internal trigger, soft trigger,
1745 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1746 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1748 * positive triggers, no S&H, no burst,
1749 * burst stop, no post trigger,
1750 * no about trigger, trigger stop
1752 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1754 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1755 inl(dev->iobase + PCI9118_ADSTAT); /*
1759 inl(dev->iobase + PCI9118_INTSRC);
1761 devpriv->ai_act_scan = 0;
1762 devpriv->ai_act_dmapos = 0;
1763 s->async->cur_chan = 0;
1764 devpriv->ai_buf_ptr = 0;
1766 if (devpriv->usedma)
1767 ret = pci9118_ai_docmd_dma(dev, s);
1769 ret = pci9118_ai_docmd_sampl(dev, s);
1771 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1776 ==============================================================================
1778 static int check_channel_list(struct comedi_device *dev,
1779 struct comedi_subdevice *s, int n_chan,
1780 unsigned int *chanlist, int frontadd, int backadd)
1782 unsigned int i, differencial = 0, bipolar = 0;
1784 /* correct channel and range number check itself comedi/range.c */
1786 comedi_error(dev, "range/channel list is empty!");
1789 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
1791 ("comedi%d: range/channel list is too long for "
1792 "actual configuration (%d>%d)!",
1793 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
1797 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1798 differencial = 1; /* all input must be diff */
1799 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1800 bipolar = 1; /* all input must be bipolar */
1802 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
1803 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
1806 "Differencial and single ended "
1807 "inputs can't be mixtured!");
1810 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
1813 "Bipolar and unipolar ranges "
1814 "can't be mixtured!");
1817 if ((!devpriv->usemux) & (differencial) &
1818 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
1820 "If AREF_DIFF is used then is "
1821 "available only first 8 channels!");
1830 ==============================================================================
1832 static int setup_channel_list(struct comedi_device *dev,
1833 struct comedi_subdevice *s, int n_chan,
1834 unsigned int *chanlist, int rot, int frontadd,
1835 int backadd, int usedma, char useeos)
1837 unsigned int i, differencial = 0, bipolar = 0;
1838 unsigned int scanquad, gain, ssh = 0x00;
1841 ("adl_pci9118 EDBG: BGN: setup_channel_list"
1842 "(%d,.,%d,.,%d,%d,%d,%d)\n",
1843 dev->minor, n_chan, rot, frontadd, backadd, usedma);
1850 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1851 differencial = 1; /* all input must be diff */
1852 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1853 bipolar = 1; /* all input must be bipolar */
1855 /* All is ok, so we can setup channel/range list */
1858 devpriv->AdControlReg |= AdControl_UniP;
1859 /* set unibipolar */
1861 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
1862 /* enable bipolar */
1866 devpriv->AdControlReg |= AdControl_Diff;
1867 /* enable diff inputs */
1869 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
1870 /* set single ended inputs */
1873 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1876 outl(2, dev->iobase + PCI9118_SCANMOD);
1877 /* gods know why this sequence! */
1878 outl(0, dev->iobase + PCI9118_SCANMOD);
1879 outl(1, dev->iobase + PCI9118_SCANMOD);
1881 #ifdef PCI9118_PARANOIDCHECK
1882 devpriv->chanlistlen = n_chan;
1883 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
1884 devpriv->chanlist[i] = 0x55aa;
1887 if (frontadd) { /* insert channels for S&H */
1888 ssh = devpriv->softsshsample;
1889 DPRINTK("FA: %04x: ", ssh);
1890 for (i = 0; i < frontadd; i++) {
1891 /* store range list to card */
1892 scanquad = CR_CHAN(chanlist[0]);
1893 /* get channel number; */
1894 gain = CR_RANGE(chanlist[0]);
1895 /* get gain number */
1896 scanquad |= ((gain & 0x03) << 8);
1897 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1898 DPRINTK("%02x ", scanquad | ssh);
1899 ssh = devpriv->softsshhold;
1904 DPRINTK("SL: ", ssh);
1905 for (i = 0; i < n_chan; i++) { /* store range list to card */
1906 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
1907 #ifdef PCI9118_PARANOIDCHECK
1908 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1910 gain = CR_RANGE(chanlist[i]); /* get gain number */
1911 scanquad |= ((gain & 0x03) << 8);
1912 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1913 DPRINTK("%02x ", scanquad | ssh);
1917 if (backadd) { /* insert channels for fit onto 32bit DMA */
1918 DPRINTK("BA: %04x: ", ssh);
1919 for (i = 0; i < backadd; i++) { /* store range list to card */
1920 scanquad = CR_CHAN(chanlist[0]);
1921 /* get channel number */
1922 gain = CR_RANGE(chanlist[0]); /* get gain number */
1923 scanquad |= ((gain & 0x03) << 8);
1924 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1925 DPRINTK("%02x ", scanquad | ssh);
1929 #ifdef PCI9118_PARANOIDCHECK
1930 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
1931 /* for 32bit operations */
1933 for (i = 1; i < n_chan; i++) { /* store range list to card */
1934 devpriv->chanlist[(n_chan + i) ^ usedma] =
1935 (CR_CHAN(chanlist[i]) & 0xf) << rot;
1937 devpriv->chanlist[(2 * n_chan) ^ usedma] =
1938 devpriv->chanlist[0 ^ usedma];
1939 /* for 32bit operations */
1944 #ifdef PCI9118_EXTDEBUG
1946 for (i = 0; i <= (useeos * n_chan); i++)
1947 DPRINTK("%04x ", devpriv->chanlist[i]);
1952 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
1953 /* udelay(100); important delay, or first sample will be crippled */
1955 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1956 return 1; /* we can serve this with scan logic */
1960 ==============================================================================
1961 calculate 8254 divisors if they are used for dual timing
1963 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1964 struct comedi_subdevice *s,
1965 unsigned int *tim1, unsigned int *tim2,
1966 unsigned int flags, int chans,
1967 unsigned int *div1, unsigned int *div2,
1968 char usessh, unsigned int chnsshfront)
1971 ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors"
1972 "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
1973 mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
1977 if (*tim2 < this_board->ai_ns_min)
1978 *tim2 = this_board->ai_ns_min;
1979 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
1980 tim2, flags & TRIG_ROUND_NEAREST);
1981 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
1982 devpriv->i8254_osc_base, *div1, *div2, *tim1);
1985 if (*tim2 < this_board->ai_ns_min)
1986 *tim2 = this_board->ai_ns_min;
1987 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1989 *div1 = *tim2 / devpriv->i8254_osc_base;
1990 /* convert timer (burst) */
1991 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1993 if (*div1 < this_board->ai_pacer_min)
1994 *div1 = this_board->ai_pacer_min;
1995 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1997 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
1998 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2000 *div2 = *div2 / *div1; /* major timer is c1*c2 */
2001 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2005 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2008 *tim2 = *div1 * devpriv->i8254_osc_base;
2009 /* real convert timer */
2011 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
2012 if (*div2 < (chans + 2))
2015 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
2017 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
2018 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
2019 devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
2022 DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
2027 ==============================================================================
2029 static void start_pacer(struct comedi_device *dev, int mode,
2030 unsigned int divisor1, unsigned int divisor2)
2032 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
2033 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
2034 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
2037 if ((mode == 1) || (mode == 2) || (mode == 4)) {
2038 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
2039 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
2040 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
2041 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
2046 ==============================================================================
2048 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
2051 return -1; /* incorrect source */
2052 devpriv->exttrg_users |= (1 << source);
2053 devpriv->IntControlReg |= Int_DTrg;
2054 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2055 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2056 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2057 /* allow INT in AMCC */
2062 ==============================================================================
2064 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
2067 return -1; /* incorrect source */
2068 devpriv->exttrg_users &= ~(1 << source);
2069 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
2070 devpriv->IntControlReg &= ~Int_DTrg;
2071 if (!devpriv->IntControlReg) /* all IRQ disabled */
2072 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
2074 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2075 /* disable int in AMCC */
2076 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2082 ==============================================================================
2084 static int pci9118_ai_cancel(struct comedi_device *dev,
2085 struct comedi_subdevice *s)
2087 if (devpriv->usedma)
2088 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
2089 (~EN_A2P_TRANSFERS),
2090 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
2091 pci9118_exttrg_del(dev, EXTTRG_AI);
2092 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
2093 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2094 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2096 * positive triggers, no S&H, no burst,
2097 * burst stop, no post trigger,
2098 * no about trigger, trigger stop
2100 devpriv->AdControlReg = 0x00;
2101 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2103 * bipolar, S.E., use 8254, stop 8354,
2104 * internal trigger, soft trigger,
2105 * disable INT and DMA
2107 outl(0, dev->iobase + PCI9118_BURST);
2108 outl(1, dev->iobase + PCI9118_SCANMOD);
2109 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
2110 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
2113 devpriv->usedma = 0;
2115 devpriv->ai_act_scan = 0;
2116 devpriv->ai_act_dmapos = 0;
2117 s->async->cur_chan = 0;
2118 s->async->inttrig = NULL;
2119 devpriv->ai_buf_ptr = 0;
2120 devpriv->ai_neverending = 0;
2121 devpriv->dma_actbuf = 0;
2123 if (!devpriv->IntControlReg)
2124 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2125 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2126 /* allow INT in AMCC */
2132 ==============================================================================
2134 static int pci9118_reset(struct comedi_device *dev)
2136 devpriv->IntControlReg = 0;
2137 devpriv->exttrg_users = 0;
2138 inl(dev->iobase + PCI9118_INTCTRL);
2139 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2140 /* disable interrupts source */
2141 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
2142 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
2143 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
2144 devpriv->AdControlReg = 0;
2145 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2147 * bipolar, S.E., use 8254,
2148 * stop 8354, internal trigger,
2150 * disable INT and DMA
2152 outl(0, dev->iobase + PCI9118_BURST);
2153 outl(1, dev->iobase + PCI9118_SCANMOD);
2154 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
2155 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
2156 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2158 * positive triggers, no S&H,
2159 * no burst, burst stop,
2165 devpriv->ao_data[0] = 2047;
2166 devpriv->ao_data[1] = 2047;
2167 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
2168 /* reset A/D outs to 0V */
2169 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
2170 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
2172 inl(dev->iobase + PCI9118_AD_DATA);
2173 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
2174 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
2175 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
2176 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
2177 devpriv->AdControlReg = 0;
2178 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2180 * bipolar, S.E., use 8254,
2181 * stop 8354, internal trigger,
2183 * disable INT and DMA
2186 devpriv->cnt0_users = 0;
2187 devpriv->exttrg_users = 0;
2193 ==============================================================================
2195 static int pci9118_attach(struct comedi_device *dev,
2196 struct comedi_devconfig *it)
2198 struct comedi_subdevice *s;
2200 unsigned short master;
2202 unsigned long iobase_a, iobase_9;
2203 struct pci_dev *pcidev;
2204 int opt_bus, opt_slot;
2206 unsigned char pci_bus, pci_slot, pci_func;
2209 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
2211 opt_bus = it->options[0];
2212 opt_slot = it->options[1];
2213 if (it->options[3] & 1)
2214 master = 0; /* user don't want use bus master */
2218 ret = alloc_private(dev, sizeof(struct pci9118_private));
2220 printk(" - Allocation failed!\n");
2224 /* Look for matching PCI device */
2225 errstr = "not found!";
2227 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC,
2228 this_board->device_id,
2230 /* Found matching vendor/device. */
2231 if (opt_bus || opt_slot) {
2232 /* Check bus/slot. */
2233 if (opt_bus != pcidev->bus->number
2234 || opt_slot != PCI_SLOT(pcidev->devfn))
2235 continue; /* no match */
2238 * Look for device that isn't in use.
2239 * Enable PCI device and request regions.
2241 if (comedi_pci_enable(pcidev, "adl_pci9118")) {
2243 "failed to enable PCI device and request regions!";
2250 if (opt_bus || opt_slot) {
2251 printk(KERN_ERR " - Card at b:s %d:%d %s\n",
2252 opt_bus, opt_slot, errstr);
2254 printk(KERN_ERR " - Card %s\n", errstr);
2260 pci_set_master(pcidev);
2263 pci_bus = pcidev->bus->number;
2264 pci_slot = PCI_SLOT(pcidev->devfn);
2265 pci_func = PCI_FUNC(pcidev->devfn);
2267 iobase_a = pci_resource_start(pcidev, 0);
2268 iobase_9 = pci_resource_start(pcidev, 2);
2270 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus,
2271 pci_slot, pci_func, iobase_9, iobase_a);
2273 dev->iobase = iobase_9;
2274 dev->board_name = this_board->name;
2276 devpriv->pcidev = pcidev;
2277 devpriv->iobase_a = iobase_a;
2281 if (it->options[3] & 2)
2282 irq = 0; /* user don't want use IRQ */
2284 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
2285 "ADLink PCI-9118", dev)) {
2286 printk(", unable to allocate IRQ %d, DISABLING IT",
2288 irq = 0; /* Can't use IRQ */
2290 printk(", irq=%u", irq);
2293 printk(", IRQ disabled");
2298 if (master) { /* alloc DMA buffers */
2299 devpriv->dma_doublebuf = 0;
2300 for (i = 0; i < 2; i++) {
2301 for (pages = 4; pages >= 0; pages--) {
2302 devpriv->dmabuf_virt[i] =
2303 (short *)__get_free_pages(GFP_KERNEL,
2305 if (devpriv->dmabuf_virt[i])
2308 if (devpriv->dmabuf_virt[i]) {
2309 devpriv->dmabuf_pages[i] = pages;
2310 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2311 devpriv->dmabuf_samples[i] =
2312 devpriv->dmabuf_size[i] >> 1;
2313 devpriv->dmabuf_hw[i] =
2314 virt_to_bus((void *)
2315 devpriv->dmabuf_virt[i]);
2318 if (!devpriv->dmabuf_virt[0]) {
2319 printk(", Can't allocate DMA buffer, DMA disabled!");
2323 if (devpriv->dmabuf_virt[1])
2324 devpriv->dma_doublebuf = 1;
2328 devpriv->master = master;
2329 if (devpriv->master)
2330 printk(", bus master");
2332 printk(", no bus master");
2334 devpriv->usemux = 0;
2335 if (it->options[2] > 0) {
2336 devpriv->usemux = it->options[2];
2337 if (devpriv->usemux > 256)
2338 devpriv->usemux = 256; /* max 256 channels! */
2339 if (it->options[4] > 0)
2340 if (devpriv->usemux > 128) {
2341 devpriv->usemux = 128;
2342 /* max 128 channels with softare S&H! */
2344 printk(", ext. mux %d channels", devpriv->usemux);
2347 devpriv->softsshdelay = it->options[4];
2348 if (devpriv->softsshdelay < 0) {
2349 /* select sample&hold signal polarity */
2350 devpriv->softsshdelay = -devpriv->softsshdelay;
2351 devpriv->softsshsample = 0x80;
2352 devpriv->softsshhold = 0x00;
2354 devpriv->softsshsample = 0x00;
2355 devpriv->softsshhold = 0x80;
2360 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
2361 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);
2362 /* Enable parity check for parity error */
2364 ret = alloc_subdevices(dev, 4);
2368 s = dev->subdevices + 0;
2369 dev->read_subdev = s;
2370 s->type = COMEDI_SUBD_AI;
2371 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2372 if (devpriv->usemux)
2373 s->n_chan = devpriv->usemux;
2375 s->n_chan = this_board->n_aichan;
2377 s->maxdata = this_board->ai_maxdata;
2378 s->len_chanlist = this_board->n_aichanlist;
2379 s->range_table = this_board->rangelist_ai;
2380 s->cancel = pci9118_ai_cancel;
2381 s->insn_read = pci9118_insn_read_ai;
2383 s->subdev_flags |= SDF_CMD_READ;
2384 s->do_cmdtest = pci9118_ai_cmdtest;
2385 s->do_cmd = pci9118_ai_cmd;
2386 s->munge = pci9118_ai_munge;
2389 s = dev->subdevices + 1;
2390 s->type = COMEDI_SUBD_AO;
2391 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2392 s->n_chan = this_board->n_aochan;
2393 s->maxdata = this_board->ao_maxdata;
2394 s->len_chanlist = this_board->n_aochan;
2395 s->range_table = this_board->rangelist_ao;
2396 s->insn_write = pci9118_insn_write_ao;
2397 s->insn_read = pci9118_insn_read_ao;
2399 s = dev->subdevices + 2;
2400 s->type = COMEDI_SUBD_DI;
2401 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2404 s->len_chanlist = 4;
2405 s->range_table = &range_digital;
2406 s->io_bits = 0; /* all bits input */
2407 s->insn_bits = pci9118_insn_bits_di;
2409 s = dev->subdevices + 3;
2410 s->type = COMEDI_SUBD_DO;
2411 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2414 s->len_chanlist = 4;
2415 s->range_table = &range_digital;
2416 s->io_bits = 0xf; /* all bits output */
2417 s->insn_bits = pci9118_insn_bits_do;
2420 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2421 devpriv->ai_maskharderr = 0x10a;
2422 /* default measure crash condition */
2423 if (it->options[5]) /* disable some requested */
2424 devpriv->ai_maskharderr &= ~it->options[5];
2426 switch (this_board->ai_maxdata) {
2428 devpriv->ai16bits = 1;
2431 devpriv->ai16bits = 0;
2438 ==============================================================================
2440 static int pci9118_detach(struct comedi_device *dev)
2446 free_irq(dev->irq, dev);
2447 if (devpriv->pcidev) {
2449 comedi_pci_disable(devpriv->pcidev);
2451 pci_dev_put(devpriv->pcidev);
2453 if (devpriv->dmabuf_virt[0])
2454 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2455 devpriv->dmabuf_pages[0]);
2456 if (devpriv->dmabuf_virt[1])
2457 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2458 devpriv->dmabuf_pages[1]);
2465 ==============================================================================
2468 MODULE_AUTHOR("Comedi http://www.comedi.org");
2469 MODULE_DESCRIPTION("Comedi low-level driver");
2470 MODULE_LICENSE("GPL");