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
57 say how 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"
66 #include "../pci_ids.h"
68 #include <linux/delay.h>
69 #include <linux/gfp.h>
70 #include <linux/interrupt.h>
72 #include "amcc_s5933.h"
74 #include "comedi_pci.h"
75 #include "comedi_fc.h"
77 /* paranoid checks are broken */
78 #undef PCI9118_PARANOIDCHECK /* if defined, then is used code which control correct channel number on every 12 bit sample */
80 #undef PCI9118_EXTDEBUG /* if defined then driver prints a lot of messages */
83 #ifdef PCI9118_EXTDEBUG
84 #define DPRINTK(fmt, args...) printk(fmt, ## args)
86 #define DPRINTK(fmt, args...)
89 #define IORANGE_9118 64 /* I hope */
90 #define PCI9118_CHANLEN 255 /* len of chanlist, some source say 256, but reality looks like 255 :-( */
92 #define PCI9118_CNT0 0x00 /* R/W: 8254 counter 0 */
93 #define PCI9118_CNT1 0x04 /* R/W: 8254 counter 0 */
94 #define PCI9118_CNT2 0x08 /* R/W: 8254 counter 0 */
95 #define PCI9118_CNTCTRL 0x0c /* W: 8254 counter control */
96 #define PCI9118_AD_DATA 0x10 /* R: A/D data */
97 #define PCI9118_DA1 0x10 /* W: D/A registers */
98 #define PCI9118_DA2 0x14
99 #define PCI9118_ADSTAT 0x18 /* R: A/D status register */
100 #define PCI9118_ADCNTRL 0x18 /* W: A/D control register */
101 #define PCI9118_DI 0x1c /* R: digi input register */
102 #define PCI9118_DO 0x1c /* W: digi output register */
103 #define PCI9118_SOFTTRG 0x20 /* W: soft trigger for A/D */
104 #define PCI9118_GAIN 0x24 /* W: A/D gain/channel register */
105 #define PCI9118_BURST 0x28 /* W: A/D burst number register */
106 #define PCI9118_SCANMOD 0x2c /* W: A/D auto scan mode */
107 #define PCI9118_ADFUNC 0x30 /* W: A/D function register */
108 #define PCI9118_DELFIFO 0x34 /* W: A/D data FIFO reset */
109 #define PCI9118_INTSRC 0x38 /* R: interrupt reason register */
110 #define PCI9118_INTCTRL 0x38 /* W: interrupt control register */
112 /* bits from A/D control register (PCI9118_ADCNTRL) */
113 #define AdControl_UniP 0x80 /* 1=bipolar, 0=unipolar */
114 #define AdControl_Diff 0x40 /* 1=differential, 0= single end inputs */
115 #define AdControl_SoftG 0x20 /* 1=8254 counter works, 0=counter stops */
116 #define AdControl_ExtG 0x10 /* 1=8254 countrol controlled by TGIN(pin 46), 0=controled by SoftG */
117 #define AdControl_ExtM 0x08 /* 1=external hardware trigger (pin 44), 0=internal trigger */
118 #define AdControl_TmrTr 0x04 /* 1=8254 is iternal trigger source, 0=software trigger is source (register PCI9118_SOFTTRG) */
119 #define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
120 #define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
122 /* bits from A/D function register (PCI9118_ADFUNC) */
123 #define AdFunction_PDTrg 0x80 /* 1=positive, 0=negative digital trigger (only positive is correct) */
124 #define AdFunction_PETrg 0x40 /* 1=positive, 0=negative external trigger (only positive is correct) */
125 #define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
126 #define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
127 #define AdFunction_BS 0x08 /* 1=burst mode start, 0=burst mode stop */
128 #define AdFunction_PM 0x04 /* 1=post trigger mode, 0=not post trigger */
129 #define AdFunction_AM 0x02 /* 1=about trigger mode, 0=not about trigger */
130 #define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
132 /* bits from A/D status register (PCI9118_ADSTAT) */
133 #define AdStatus_nFull 0x100 /* 0=FIFO full (fatal), 1=not full */
134 #define AdStatus_nHfull 0x080 /* 0=FIFO half full, 1=FIFO not half full */
135 #define AdStatus_nEpty 0x040 /* 0=FIFO empty, 1=FIFO not empty */
136 #define AdStatus_Acmp 0x020 /* */
137 #define AdStatus_DTH 0x010 /* 1=external digital trigger */
138 #define AdStatus_Bover 0x008 /* 1=burst mode overrun (fatal) */
139 #define AdStatus_ADOS 0x004 /* 1=A/D over speed (warning) */
140 #define AdStatus_ADOR 0x002 /* 1=A/D overrun (fatal) */
141 #define AdStatus_ADrdy 0x001 /* 1=A/D already ready, 0=not ready */
143 /* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
144 /* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
145 #define Int_Timer 0x08 /* timer interrupt */
146 #define Int_About 0x04 /* about trigger complete */
147 #define Int_Hfull 0x02 /* A/D FIFO hlaf full */
148 #define Int_DTrg 0x01 /* external digital trigger */
150 #define START_AI_EXT 0x01 /* start measure on external trigger */
151 #define STOP_AI_EXT 0x02 /* stop measure on external trigger */
152 #define START_AI_INT 0x04 /* start measure on internal trigger */
153 #define STOP_AI_INT 0x08 /* stop measure on internal trigger */
155 #define EXTTRG_AI 0 /* ext trg is used by AI */
157 static const struct comedi_lrange range_pci9118dg_hr = { 8, {
169 static const struct comedi_lrange range_pci9118hg = { 8, {
181 #define PCI9118_BIPOLAR_RANGES 4 /* used for test on mixture of BIP/UNI ranges */
183 static int pci9118_attach(struct comedi_device *dev,
184 struct comedi_devconfig *it);
185 static int pci9118_detach(struct comedi_device *dev);
188 const char *name; /* board name */
189 int vendor_id; /* PCI vendor a device ID of card */
191 int iorange_amcc; /* iorange for own S5933 region */
192 int iorange_9118; /* pass thru card region size */
193 int n_aichan; /* num of A/D chans */
194 int n_aichand; /* num of A/D chans in diff mode */
195 int mux_aichan; /* num of A/D chans with external multiplexor */
196 int n_aichanlist; /* len of chanlist */
197 int n_aochan; /* num of D/A chans */
198 int ai_maxdata; /* resolution of A/D */
199 int ao_maxdata; /* resolution of D/A */
200 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
201 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
202 unsigned int ai_ns_min; /* max sample speed of card v ns */
203 unsigned int ai_pacer_min; /* minimal pacer value (c1*c2 or c1 in burst) */
204 int half_fifo_size; /* size of FIFO/2 */
208 static DEFINE_PCI_DEVICE_TABLE(pci9118_pci_table) = {
210 PCI_VENDOR_ID_AMCC, 0x80d9, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, {
214 MODULE_DEVICE_TABLE(pci, pci9118_pci_table);
216 static const struct boardtype boardtypes[] = {
217 {"pci9118dg", PCI_VENDOR_ID_AMCC, 0x80d9,
218 AMCC_OP_REG_SIZE, IORANGE_9118,
219 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
220 &range_pci9118dg_hr, &range_bipolar10,
222 {"pci9118hg", PCI_VENDOR_ID_AMCC, 0x80d9,
223 AMCC_OP_REG_SIZE, IORANGE_9118,
224 16, 8, 256, PCI9118_CHANLEN, 2, 0x0fff, 0x0fff,
225 &range_pci9118hg, &range_bipolar10,
227 {"pci9118hr", PCI_VENDOR_ID_AMCC, 0x80d9,
228 AMCC_OP_REG_SIZE, IORANGE_9118,
229 16, 8, 256, PCI9118_CHANLEN, 2, 0xffff, 0x0fff,
230 &range_pci9118dg_hr, &range_bipolar10,
234 #define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
236 static struct comedi_driver driver_pci9118 = {
237 .driver_name = "adl_pci9118",
238 .module = THIS_MODULE,
239 .attach = pci9118_attach,
240 .detach = pci9118_detach,
241 .num_names = n_boardtypes,
242 .board_name = &boardtypes[0].name,
243 .offset = sizeof(struct boardtype),
246 COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
248 struct pci9118_private {
249 unsigned long iobase_a; /* base+size for AMCC chip */
250 unsigned int master; /* master capable */
251 struct pci_dev *pcidev; /* ptr to actual pcidev */
252 unsigned int usemux; /* we want to use external multiplexor! */
253 #ifdef PCI9118_PARANOIDCHECK
254 unsigned short chanlist[PCI9118_CHANLEN + 1]; /* list of scaned channel */
255 unsigned char chanlistlen; /* number of scanlist */
257 unsigned char AdControlReg; /* A/D control register */
258 unsigned char IntControlReg; /* Interrupt control register */
259 unsigned char AdFunctionReg; /* A/D function register */
260 char valid; /* driver is ok */
261 char ai_neverending; /* we do unlimited AI */
262 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
263 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
264 unsigned int ai_act_scan; /* how many scans we finished */
265 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
266 unsigned int ai_n_chan; /* how many channels is measured */
267 unsigned int ai_n_scanlen; /* len of actual scanlist */
268 unsigned int ai_n_realscanlen; /* what we must transfer for one outgoing scan include front/back adds */
269 unsigned int ai_act_dmapos; /* position in actual real stream */
270 unsigned int ai_add_front; /* how many channels we must add before scan to satisfy S&H? */
271 unsigned int ai_add_back; /* how many channels we must add before scan to satisfy DMA? */
272 unsigned int *ai_chanlist; /* actaul chanlist */
273 unsigned int ai_timer1;
274 unsigned int ai_timer2;
275 unsigned int ai_flags;
276 char ai12_startstop; /* measure can start/stop on external trigger */
277 unsigned int ai_divisor1, ai_divisor2; /* divisors for start of measure on external start */
278 unsigned int ai_data_len;
280 short ao_data[2]; /* data output buffer */
281 unsigned int ai_scans; /* number of scans to do */
282 char dma_doublebuf; /* we can use double buffring */
283 unsigned int dma_actbuf; /* which buffer is used now */
284 short *dmabuf_virt[2]; /* pointers to begin of DMA buffer */
285 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
286 unsigned int dmabuf_size[2]; /* size of dma buffer in bytes */
287 unsigned int dmabuf_use_size[2]; /* which size we may now used for transfer */
288 unsigned int dmabuf_used_size[2]; /* which size was trully used */
289 unsigned int dmabuf_panic_size[2];
290 unsigned int dmabuf_samples[2]; /* size in samples */
291 int dmabuf_pages[2]; /* number of pages in buffer */
292 unsigned char cnt0_users; /* bit field of 8254 CNT0 users (0-unused, 1-AO, 2-DI, 3-DO) */
293 unsigned char exttrg_users; /* bit field of external trigger users (0-AI, 1-AO, 2-DI, 3-DO) */
294 unsigned int cnt0_divisor; /* actual CNT0 divisor */
295 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *, unsigned short, unsigned int, unsigned short); /* ptr to actual interrupt AI function */
296 unsigned char ai16bits; /* =1 16 bit card */
297 unsigned char usedma; /* =1 use DMA transfer and not INT */
298 unsigned char useeoshandle; /* =1 change WAKE_EOS DMA transfer to fit on every second */
299 unsigned char usessh; /* =1 turn on S&H support */
300 int softsshdelay; /* >0 use software S&H, numer is requested delay in ns */
301 unsigned char softsshsample; /* polarity of S&H signal in sample state */
302 unsigned char softsshhold; /* polarity of S&H signal in hold state */
303 unsigned int ai_maskerr; /* which warning was printed */
304 unsigned int ai_maskharderr; /* on which error bits stops */
305 unsigned int ai_inttrig_start; /* TRIG_INT for start */
308 #define devpriv ((struct pci9118_private *)dev->private)
309 #define this_board ((struct boardtype *)dev->board_ptr)
312 ==============================================================================
315 static int check_channel_list(struct comedi_device *dev,
316 struct comedi_subdevice *s, int n_chan,
317 unsigned int *chanlist, int frontadd,
319 static int setup_channel_list(struct comedi_device *dev,
320 struct comedi_subdevice *s, int n_chan,
321 unsigned int *chanlist, int rot, int frontadd,
322 int backadd, int usedma, char eoshandle);
323 static void start_pacer(struct comedi_device *dev, int mode,
324 unsigned int divisor1, unsigned int divisor2);
325 static int pci9118_reset(struct comedi_device *dev);
326 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
327 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
328 static int pci9118_ai_cancel(struct comedi_device *dev,
329 struct comedi_subdevice *s);
330 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
331 struct comedi_subdevice *s,
332 unsigned int *tim1, unsigned int *tim2,
333 unsigned int flags, int chans,
334 unsigned int *div1, unsigned int *div2,
335 char usessh, unsigned int chnsshfront);
338 ==============================================================================
340 static int pci9118_insn_read_ai(struct comedi_device *dev,
341 struct comedi_subdevice *s,
342 struct comedi_insn *insn, unsigned int *data)
347 devpriv->AdControlReg = AdControl_Int & 0xff;
348 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
349 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); /* positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
351 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
354 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
356 for (n = 0; n < insn->n; n++) {
357 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
361 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
366 comedi_error(dev, "A/D insn timeout");
368 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
372 if (devpriv->ai16bits) {
375 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
378 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
382 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
388 ==============================================================================
390 static int pci9118_insn_write_ao(struct comedi_device *dev,
391 struct comedi_subdevice *s,
392 struct comedi_insn *insn, unsigned int *data)
396 ch = CR_CHAN(insn->chanspec);
398 chanreg = PCI9118_DA2;
400 chanreg = PCI9118_DA1;
403 for (n = 0; n < insn->n; n++) {
404 outl(data[n], dev->iobase + chanreg);
405 devpriv->ao_data[ch] = data[n];
412 ==============================================================================
414 static int pci9118_insn_read_ao(struct comedi_device *dev,
415 struct comedi_subdevice *s,
416 struct comedi_insn *insn, unsigned int *data)
420 chan = CR_CHAN(insn->chanspec);
421 for (n = 0; n < insn->n; n++)
422 data[n] = devpriv->ao_data[chan];
428 ==============================================================================
430 static int pci9118_insn_bits_di(struct comedi_device *dev,
431 struct comedi_subdevice *s,
432 struct comedi_insn *insn, unsigned int *data)
434 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
440 ==============================================================================
442 static int pci9118_insn_bits_do(struct comedi_device *dev,
443 struct comedi_subdevice *s,
444 struct comedi_insn *insn, unsigned int *data)
447 s->state &= ~data[0];
448 s->state |= (data[0] & data[1]);
449 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
457 ==============================================================================
459 static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
461 devpriv->AdFunctionReg =
462 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
463 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
464 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
465 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
466 dev->iobase + PCI9118_CNT0);
467 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
468 dev->iobase + PCI9118_CNT0);
469 devpriv->AdFunctionReg |= AdFunction_Start;
470 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
473 static unsigned int defragment_dma_buffer(struct comedi_device *dev,
474 struct comedi_subdevice *s,
476 unsigned int num_samples)
478 unsigned int i = 0, j = 0;
479 unsigned int start_pos = devpriv->ai_add_front,
480 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
481 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
482 devpriv->ai_add_back;
484 for (i = 0; i < num_samples; i++) {
485 if (devpriv->ai_act_dmapos >= start_pos &&
486 devpriv->ai_act_dmapos < stop_pos) {
487 dma_buffer[j++] = dma_buffer[i];
489 devpriv->ai_act_dmapos++;
490 devpriv->ai_act_dmapos %= raw_scanlen;
497 ==============================================================================
499 static unsigned int move_block_from_dma(struct comedi_device *dev,
500 struct comedi_subdevice *s,
502 unsigned int num_samples)
504 unsigned int num_bytes;
506 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
507 devpriv->ai_act_scan +=
508 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
509 s->async->cur_chan += num_samples;
510 s->async->cur_chan %= devpriv->ai_n_scanlen;
512 cfc_write_array_to_buffer(s, dma_buffer,
513 num_samples * sizeof(short));
514 if (num_bytes < num_samples * sizeof(short))
520 ==============================================================================
522 static char pci9118_decode_error_status(struct comedi_device *dev,
523 struct comedi_subdevice *s,
527 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
528 devpriv->ai_maskerr &= ~0x100L;
532 "A/D Burst Mode Overrun Status (Fatal Error!)");
533 devpriv->ai_maskerr &= ~0x008L;
536 comedi_error(dev, "A/D Over Speed Status (Warning!)");
537 devpriv->ai_maskerr &= ~0x004L;
540 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
541 devpriv->ai_maskerr &= ~0x002L;
543 if (m & devpriv->ai_maskharderr) {
544 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
545 pci9118_ai_cancel(dev, s);
546 comedi_event(dev, s);
553 static void pci9118_ai_munge(struct comedi_device *dev,
554 struct comedi_subdevice *s, void *data,
555 unsigned int num_bytes,
556 unsigned int start_chan_index)
558 unsigned int i, num_samples = num_bytes / sizeof(short);
561 for (i = 0; i < num_samples; i++) {
563 array[i] = be16_to_cpu(array[i]);
564 if (devpriv->ai16bits) {
567 array[i] = (array[i] >> 4) & 0x0fff;
573 ==============================================================================
575 static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
576 struct comedi_subdevice *s,
577 unsigned short int_adstat,
578 unsigned int int_amcc,
579 unsigned short int_daq)
581 register short sampl;
583 s->async->events = 0;
585 if (int_adstat & devpriv->ai_maskerr)
586 if (pci9118_decode_error_status(dev, s, int_adstat))
589 sampl = inw(dev->iobase + PCI9118_AD_DATA);
591 #ifdef PCI9118_PARANOIDCHECK
592 if (devpriv->ai16bits == 0) {
593 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) { /* data dropout! */
595 ("comedi: A/D SAMPL - data dropout: received channel %d, expected %d!\n",
597 devpriv->chanlist[s->async->cur_chan]);
598 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
599 pci9118_ai_cancel(dev, s);
600 comedi_event(dev, s);
605 cfc_write_to_buffer(s, sampl);
606 s->async->cur_chan++;
607 if (s->async->cur_chan >= devpriv->ai_n_scanlen) { /* one scan done */
608 s->async->cur_chan %= devpriv->ai_n_scanlen;
609 devpriv->ai_act_scan++;
610 if (!(devpriv->ai_neverending))
611 if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */
612 pci9118_ai_cancel(dev, s);
613 s->async->events |= COMEDI_CB_EOA;
617 if (s->async->events)
618 comedi_event(dev, s);
622 ==============================================================================
624 static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
625 struct comedi_subdevice *s,
626 unsigned short int_adstat,
627 unsigned int int_amcc,
628 unsigned short int_daq)
630 unsigned int next_dma_buf, samplesinbuf, sampls, m;
632 if (int_amcc & MASTER_ABORT_INT) {
633 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
634 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
635 pci9118_ai_cancel(dev, s);
636 comedi_event(dev, s);
640 if (int_amcc & TARGET_ABORT_INT) {
641 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
642 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
643 pci9118_ai_cancel(dev, s);
644 comedi_event(dev, s);
648 if (int_adstat & devpriv->ai_maskerr)
649 /* if (int_adstat & 0x106) */
650 if (pci9118_decode_error_status(dev, s, int_adstat))
653 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1; /* number of received real samples */
654 /* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
656 if (devpriv->dma_doublebuf) { /* switch DMA buffers if is used double buffering */
657 next_dma_buf = 1 - devpriv->dma_actbuf;
658 outl(devpriv->dmabuf_hw[next_dma_buf],
659 devpriv->iobase_a + AMCC_OP_REG_MWAR);
660 outl(devpriv->dmabuf_use_size[next_dma_buf],
661 devpriv->iobase_a + AMCC_OP_REG_MWTC);
662 devpriv->dmabuf_used_size[next_dma_buf] =
663 devpriv->dmabuf_use_size[next_dma_buf];
664 if (devpriv->ai_do == 4)
665 interrupt_pci9118_ai_mode4_switch(dev);
669 m = devpriv->ai_data_len >> 1; /* how many samples is to end of buffer */
670 /* DPRINTK("samps=%d m=%d %d %d\n",samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr); */
672 move_block_from_dma(dev, s,
673 devpriv->dmabuf_virt[devpriv->dma_actbuf],
675 m = m - sampls; /* m= how many samples was transfered */
677 /* DPRINTK("YYY\n"); */
679 if (!devpriv->ai_neverending)
680 if (devpriv->ai_act_scan >= devpriv->ai_scans) { /* all data sampled */
681 pci9118_ai_cancel(dev, s);
682 s->async->events |= COMEDI_CB_EOA;
685 if (devpriv->dma_doublebuf) { /* switch dma buffers */
686 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
687 } else { /* restart DMA if is not used double buffering */
688 outl(devpriv->dmabuf_hw[0],
689 devpriv->iobase_a + AMCC_OP_REG_MWAR);
690 outl(devpriv->dmabuf_use_size[0],
691 devpriv->iobase_a + AMCC_OP_REG_MWTC);
692 if (devpriv->ai_do == 4)
693 interrupt_pci9118_ai_mode4_switch(dev);
696 comedi_event(dev, s);
700 ==============================================================================
702 static irqreturn_t interrupt_pci9118(int irq, void *d)
704 struct comedi_device *dev = d;
705 unsigned int int_daq = 0, int_amcc, int_adstat;
708 return IRQ_NONE; /* not fully initialized */
710 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf; /* get IRQ reasons from card */
711 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* get INT register from AMCC chip */
713 /* DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n", int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR), inl(devpriv->iobase_a+AMCC_OP_REG_MWTC), inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do); */
715 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
716 return IRQ_NONE; /* interrupt from other source */
718 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* shutdown IRQ reasons in AMCC */
720 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff; /* get STATUS register */
722 if (devpriv->ai_do) {
723 if (devpriv->ai12_startstop)
724 if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) { /* start stop of measure */
725 if (devpriv->ai12_startstop & START_AI_EXT) {
726 devpriv->ai12_startstop &=
728 if (!(devpriv->ai12_startstop &
730 pci9118_exttrg_del(dev, EXTTRG_AI); /* deactivate EXT trigger */
731 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1, devpriv->ai_divisor2); /* start pacer */
732 outl(devpriv->AdControlReg,
733 dev->iobase + PCI9118_ADCNTRL);
735 if (devpriv->ai12_startstop &
737 devpriv->ai12_startstop &=
739 pci9118_exttrg_del(dev, EXTTRG_AI); /* deactivate EXT trigger */
740 devpriv->ai_neverending = 0; /* well, on next interrupt from DMA/EOC measure will stop */
745 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
753 ==============================================================================
755 static int pci9118_ai_inttrig(struct comedi_device *dev,
756 struct comedi_subdevice *s, unsigned int trignum)
758 if (trignum != devpriv->ai_inttrig_start)
761 devpriv->ai12_startstop &= ~START_AI_INT;
762 s->async->inttrig = NULL;
764 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
765 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
766 if (devpriv->ai_do != 3) {
767 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
768 devpriv->ai_divisor2);
769 devpriv->AdControlReg |= AdControl_SoftG;
771 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
777 ==============================================================================
779 static int pci9118_ai_cmdtest(struct comedi_device *dev,
780 struct comedi_subdevice *s,
781 struct comedi_cmd *cmd)
784 int tmp, divisor1 = 0, divisor2 = 0;
786 /* step 1: make sure trigger sources are trivially valid */
788 tmp = cmd->start_src;
789 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
790 if (!cmd->start_src || tmp != cmd->start_src)
793 tmp = cmd->scan_begin_src;
794 if (devpriv->master) {
795 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
797 cmd->scan_begin_src &= TRIG_FOLLOW;
799 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
802 tmp = cmd->convert_src;
803 if (devpriv->master) {
804 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
806 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
808 if (!cmd->convert_src || tmp != cmd->convert_src)
811 tmp = cmd->scan_end_src;
812 cmd->scan_end_src &= TRIG_COUNT;
813 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
817 cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
818 if (!cmd->stop_src || tmp != cmd->stop_src)
824 /* step 2: make sure trigger sources are unique and mutually compatible */
826 if (cmd->start_src != TRIG_NOW &&
827 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
828 cmd->start_src = TRIG_NOW;
832 if (cmd->scan_begin_src != TRIG_TIMER &&
833 cmd->scan_begin_src != TRIG_EXT &&
834 cmd->scan_begin_src != TRIG_INT &&
835 cmd->scan_begin_src != TRIG_FOLLOW) {
836 cmd->scan_begin_src = TRIG_FOLLOW;
840 if (cmd->convert_src != TRIG_TIMER &&
841 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
842 cmd->convert_src = TRIG_TIMER;
846 if (cmd->scan_end_src != TRIG_COUNT) {
847 cmd->scan_end_src = TRIG_COUNT;
851 if (cmd->stop_src != TRIG_NONE &&
852 cmd->stop_src != TRIG_COUNT &&
853 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
854 cmd->stop_src = TRIG_COUNT;
858 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
859 cmd->start_src = TRIG_NOW;
863 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
864 cmd->start_src = TRIG_NOW;
868 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
869 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
870 cmd->convert_src = TRIG_TIMER;
874 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
875 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
876 cmd->convert_src = TRIG_TIMER;
880 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
881 cmd->stop_src = TRIG_COUNT;
888 /* step 3: make sure arguments are trivially compatible */
890 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
891 if (cmd->start_arg != 0) {
896 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
897 if (cmd->scan_begin_arg != 0) {
898 cmd->scan_begin_arg = 0;
902 if ((cmd->scan_begin_src == TRIG_TIMER) &&
903 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
904 cmd->scan_begin_src = TRIG_FOLLOW;
905 cmd->convert_arg = cmd->scan_begin_arg;
906 cmd->scan_begin_arg = 0;
909 if (cmd->scan_begin_src == TRIG_TIMER)
910 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
911 cmd->scan_begin_arg = this_board->ai_ns_min;
915 if (cmd->scan_begin_src == TRIG_EXT)
916 if (cmd->scan_begin_arg) {
917 cmd->scan_begin_arg = 0;
919 if (cmd->scan_end_arg > 65535) {
920 cmd->scan_end_arg = 65535;
925 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
926 if (cmd->convert_arg < this_board->ai_ns_min) {
927 cmd->convert_arg = this_board->ai_ns_min;
931 if (cmd->convert_src == TRIG_EXT)
932 if (cmd->convert_arg) {
933 cmd->convert_arg = 0;
937 if (cmd->stop_src == TRIG_COUNT) {
938 if (!cmd->stop_arg) {
942 } else { /* TRIG_NONE */
943 if (cmd->stop_arg != 0) {
949 if (!cmd->chanlist_len) {
950 cmd->chanlist_len = 1;
954 if (cmd->chanlist_len > this_board->n_aichanlist) {
955 cmd->chanlist_len = this_board->n_aichanlist;
959 if (cmd->scan_end_arg < cmd->chanlist_len) {
960 cmd->scan_end_arg = cmd->chanlist_len;
964 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
966 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
973 /* step 4: fix up any arguments */
975 if (cmd->scan_begin_src == TRIG_TIMER) {
976 tmp = cmd->scan_begin_arg;
977 /* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
978 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
979 &divisor2, &cmd->scan_begin_arg,
980 cmd->flags & TRIG_ROUND_MASK);
981 /* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
982 if (cmd->scan_begin_arg < this_board->ai_ns_min)
983 cmd->scan_begin_arg = this_board->ai_ns_min;
984 if (tmp != cmd->scan_begin_arg)
988 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
989 tmp = cmd->convert_arg;
990 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
991 &divisor2, &cmd->convert_arg,
992 cmd->flags & TRIG_ROUND_MASK);
993 /* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
994 if (cmd->convert_arg < this_board->ai_ns_min)
995 cmd->convert_arg = this_board->ai_ns_min;
996 if (tmp != cmd->convert_arg)
998 if (cmd->scan_begin_src == TRIG_TIMER
999 && cmd->convert_src == TRIG_NOW) {
1000 if (cmd->convert_arg == 0) {
1001 if (cmd->scan_begin_arg <
1002 this_board->ai_ns_min *
1003 (cmd->scan_end_arg + 2)) {
1004 cmd->scan_begin_arg =
1005 this_board->ai_ns_min *
1006 (cmd->scan_end_arg + 2);
1007 /* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1011 if (cmd->scan_begin_arg <
1012 cmd->convert_arg * cmd->chanlist_len) {
1013 cmd->scan_begin_arg =
1016 /* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
1027 if (!check_channel_list(dev, s, cmd->chanlist_len,
1028 cmd->chanlist, 0, 0))
1029 return 5; /* incorrect channels list */
1035 ==============================================================================
1037 static int Compute_and_setup_dma(struct comedi_device *dev)
1039 unsigned int dmalen0, dmalen1, i;
1041 DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
1042 dmalen0 = devpriv->dmabuf_size[0];
1043 dmalen1 = devpriv->dmabuf_size[1];
1044 DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
1045 devpriv->ai_data_len);
1046 /* isn't output buff smaller that our DMA buff? */
1047 if (dmalen0 > (devpriv->ai_data_len)) {
1048 dmalen0 = devpriv->ai_data_len & ~3L; /* allign to 32bit down */
1050 if (dmalen1 > (devpriv->ai_data_len)) {
1051 dmalen1 = devpriv->ai_data_len & ~3L; /* allign to 32bit down */
1053 DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
1055 /* we want wake up every scan? */
1056 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1057 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1058 /* uff, too short DMA buffer, disable EOS support! */
1059 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1061 ("comedi%d: WAR: DMA0 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
1062 dev->minor, dmalen0,
1063 devpriv->ai_n_realscanlen << 1);
1065 /* short first DMA buffer to one scan */
1066 dmalen0 = devpriv->ai_n_realscanlen << 1;
1068 ("21 dmalen0=%d ai_n_realscanlen=%d useeoshandle=%d\n",
1069 dmalen0, devpriv->ai_n_realscanlen,
1070 devpriv->useeoshandle);
1071 if (devpriv->useeoshandle)
1075 ("comedi%d: ERR: DMA0 buf len bug? (%d<4)\n",
1076 dev->minor, dmalen0);
1081 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1082 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
1083 /* uff, too short DMA buffer, disable EOS support! */
1084 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
1086 ("comedi%d: WAR: DMA1 buf too short, cann't support TRIG_WAKE_EOS (%d<%d)\n",
1087 dev->minor, dmalen1,
1088 devpriv->ai_n_realscanlen << 1);
1090 /* short second DMA buffer to one scan */
1091 dmalen1 = devpriv->ai_n_realscanlen << 1;
1093 ("22 dmalen1=%d ai_n_realscanlen=%d useeoshandle=%d\n",
1094 dmalen1, devpriv->ai_n_realscanlen,
1095 devpriv->useeoshandle);
1096 if (devpriv->useeoshandle)
1100 ("comedi%d: ERR: DMA1 buf len bug? (%d<4)\n",
1101 dev->minor, dmalen1);
1107 DPRINTK("3 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
1108 /* transfer without TRIG_WAKE_EOS */
1109 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1110 /* if it's possible then allign DMA buffers to length of scan */
1113 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1114 (devpriv->ai_n_realscanlen << 1);
1117 dmalen0 = i; /* uff. very long scan? */
1120 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1121 (devpriv->ai_n_realscanlen << 1);
1124 dmalen1 = i; /* uff. very long scan? */
1125 /* if measure isn't neverending then test, if it whole fits into one or two DMA buffers */
1126 if (!devpriv->ai_neverending) {
1127 /* fits whole measure into one DMA buffer? */
1129 ((devpriv->ai_n_realscanlen << 1) *
1130 devpriv->ai_scans)) {
1132 ("3.0 ai_n_realscanlen=%d ai_scans=%d \n",
1133 devpriv->ai_n_realscanlen,
1136 (devpriv->ai_n_realscanlen << 1) *
1138 DPRINTK("3.1 dmalen0=%d dmalen1=%d \n", dmalen0,
1141 } else { /* fits whole measure into two DMA buffer? */
1143 ((devpriv->ai_n_realscanlen << 1) *
1144 devpriv->ai_scans - dmalen0))
1146 (devpriv->ai_n_realscanlen << 1) *
1147 devpriv->ai_scans - dmalen0;
1148 DPRINTK("3.2 dmalen0=%d dmalen1=%d \n", dmalen0,
1155 DPRINTK("4 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
1157 /* these DMA buffer size we'll be used */
1158 devpriv->dma_actbuf = 0;
1159 devpriv->dmabuf_use_size[0] = dmalen0;
1160 devpriv->dmabuf_use_size[1] = dmalen1;
1162 DPRINTK("5 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
1164 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1165 devpriv->dmabuf_panic_size[0] =
1166 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1167 1) * devpriv->ai_n_scanlen * sizeof(short);
1168 devpriv->dmabuf_panic_size[1] =
1169 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1170 1) * devpriv->ai_n_scanlen * sizeof(short);
1172 devpriv->dmabuf_panic_size[0] =
1173 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
1174 devpriv->dmabuf_panic_size[1] =
1175 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
1179 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1180 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1181 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
1182 /* init DMA transfer */
1183 outl(0x00000000 | AINT_WRITE_COMPL,
1184 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1185 /* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
1187 outl(inl(devpriv->iobase_a +
1188 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1189 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
1190 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow bus mastering */
1192 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1197 ==============================================================================
1199 static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1200 struct comedi_subdevice *s)
1202 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
1203 dev->minor, devpriv->ai_do);
1204 switch (devpriv->ai_do) {
1206 devpriv->AdControlReg |= AdControl_TmrTr;
1209 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1212 devpriv->AdControlReg |= AdControl_ExtM;
1215 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1219 "pci9118_ai_docmd_sampl() mode number bug!\n");
1223 devpriv->int_ai_func = interrupt_pci9118_ai_onesample; /* transfer function */
1225 if (devpriv->ai12_startstop)
1226 pci9118_exttrg_add(dev, EXTTRG_AI); /* activate EXT trigger */
1228 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1229 devpriv->IntControlReg |= Int_Timer;
1231 devpriv->AdControlReg |= AdControl_Int;
1233 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */
1235 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1236 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1237 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1238 if (devpriv->ai_do != 3) {
1239 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1240 devpriv->ai_divisor2);
1241 devpriv->AdControlReg |= AdControl_SoftG;
1243 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1246 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
1251 ==============================================================================
1253 static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1254 struct comedi_subdevice *s)
1256 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
1257 dev->minor, devpriv->ai_do, devpriv->usedma);
1258 Compute_and_setup_dma(dev);
1260 switch (devpriv->ai_do) {
1262 devpriv->AdControlReg |=
1263 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1266 devpriv->AdControlReg |=
1267 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1268 devpriv->AdFunctionReg =
1269 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1271 if (devpriv->usessh && (!devpriv->softsshdelay))
1272 devpriv->AdFunctionReg |= AdFunction_BSSH;
1273 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1276 devpriv->AdControlReg |=
1277 ((AdControl_ExtM | AdControl_Dma) & 0xff);
1278 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1281 devpriv->AdControlReg |=
1282 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
1283 devpriv->AdFunctionReg =
1284 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
1285 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1286 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1287 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
1288 dev->iobase + PCI9118_CNT0);
1289 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
1290 dev->iobase + PCI9118_CNT0);
1291 devpriv->AdFunctionReg |= AdFunction_Start;
1294 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1298 if (devpriv->ai12_startstop) {
1299 pci9118_exttrg_add(dev, EXTTRG_AI); /* activate EXT trigger */
1302 devpriv->int_ai_func = interrupt_pci9118_ai_dma; /* transfer function */
1304 outl(0x02000000 | AINT_WRITE_COMPL,
1305 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1307 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1308 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1309 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1310 if (devpriv->ai_do != 3) {
1311 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
1312 devpriv->ai_divisor2);
1313 devpriv->AdControlReg |= AdControl_SoftG;
1315 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1318 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
1323 ==============================================================================
1325 static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1327 struct comedi_cmd *cmd = &s->async->cmd;
1328 unsigned int addchans = 0;
1331 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
1332 devpriv->ai12_startstop = 0;
1333 devpriv->ai_flags = cmd->flags;
1334 devpriv->ai_n_chan = cmd->chanlist_len;
1335 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1336 devpriv->ai_chanlist = cmd->chanlist;
1337 devpriv->ai_data = s->async->prealloc_buf;
1338 devpriv->ai_data_len = s->async->prealloc_bufsz;
1339 devpriv->ai_timer1 = 0;
1340 devpriv->ai_timer2 = 0;
1341 devpriv->ai_add_front = 0;
1342 devpriv->ai_add_back = 0;
1343 devpriv->ai_maskerr = 0x10e;
1345 /* prepare for start/stop conditions */
1346 if (cmd->start_src == TRIG_EXT)
1347 devpriv->ai12_startstop |= START_AI_EXT;
1348 if (cmd->stop_src == TRIG_EXT) {
1349 devpriv->ai_neverending = 1;
1350 devpriv->ai12_startstop |= STOP_AI_EXT;
1352 if (cmd->start_src == TRIG_INT) {
1353 devpriv->ai12_startstop |= START_AI_INT;
1354 devpriv->ai_inttrig_start = cmd->start_arg;
1355 s->async->inttrig = pci9118_ai_inttrig;
1358 if (cmd->stop_src == TRIG_INT) {
1359 devpriv->ai_neverending = 1;
1360 devpriv->ai12_startstop |= STOP_AI_INT;
1363 if (cmd->stop_src == TRIG_NONE)
1364 devpriv->ai_neverending = 1;
1365 if (cmd->stop_src == TRIG_COUNT) {
1366 devpriv->ai_scans = cmd->stop_arg;
1367 devpriv->ai_neverending = 0;
1369 devpriv->ai_scans = 0;
1372 /* use sample&hold signal? */
1373 if (cmd->convert_src == TRIG_NOW) {
1374 devpriv->usessh = 1;
1377 devpriv->usessh = 0;
1380 DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
1381 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
1382 devpriv->ai12_startstop);
1384 /* use additional sample at end of every scan to satisty DMA 32 bit transfer? */
1385 devpriv->ai_add_front = 0;
1386 devpriv->ai_add_back = 0;
1387 devpriv->useeoshandle = 0;
1388 if (devpriv->master) {
1389 devpriv->usedma = 1;
1390 if ((cmd->flags & TRIG_WAKE_EOS) &&
1391 (devpriv->ai_n_scanlen == 1)) {
1392 if (cmd->convert_src == TRIG_NOW) {
1393 devpriv->ai_add_back = 1;
1395 if (cmd->convert_src == TRIG_TIMER) {
1396 devpriv->usedma = 0; /* use INT transfer if scanlist have only one channel */
1399 if ((cmd->flags & TRIG_WAKE_EOS) &&
1400 (devpriv->ai_n_scanlen & 1) &&
1401 (devpriv->ai_n_scanlen > 1)) {
1402 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1403 /* vpriv->useeoshandle=1; // change DMA transfer block to fit EOS on every second call */
1404 devpriv->usedma = 0; /* XXX maybe can be corrected to use 16 bit DMA */
1405 } else { /* well, we must insert one sample to end of EOS to meet 32 bit transfer */
1406 devpriv->ai_add_back = 1;
1409 } else { /* interrupt transfer don't need any correction */
1410 devpriv->usedma = 0;
1413 /* we need software S&H signal? It add two samples before every scan as minimum */
1414 if (devpriv->usessh && devpriv->softsshdelay) {
1415 devpriv->ai_add_front = 2;
1416 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) { /* move it to front */
1417 devpriv->ai_add_front++;
1418 devpriv->ai_add_back = 0;
1420 if (cmd->convert_arg < this_board->ai_ns_min)
1421 cmd->convert_arg = this_board->ai_ns_min;
1422 addchans = devpriv->softsshdelay / cmd->convert_arg;
1423 if (devpriv->softsshdelay % cmd->convert_arg)
1425 if (addchans > (devpriv->ai_add_front - 1)) { /* uff, still short :-( */
1426 devpriv->ai_add_front = addchans + 1;
1427 if (devpriv->usedma == 1)
1428 if ((devpriv->ai_add_front +
1429 devpriv->ai_n_chan +
1430 devpriv->ai_add_back) & 1)
1431 devpriv->ai_add_front++; /* round up to 32 bit */
1434 /* well, we now know what must be all added */
1435 devpriv->ai_n_realscanlen = /* what we must take from card in real to have ai_n_scanlen on output? */
1436 (devpriv->ai_add_front + devpriv->ai_n_chan +
1437 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1438 devpriv->ai_n_chan);
1440 DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
1442 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
1443 devpriv->ai_n_chan, devpriv->ai_add_back,
1444 devpriv->ai_n_scanlen);
1446 /* check and setup channel list */
1447 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
1448 devpriv->ai_chanlist, devpriv->ai_add_front,
1449 devpriv->ai_add_back))
1451 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
1452 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1453 devpriv->ai_add_back, devpriv->usedma,
1454 devpriv->useeoshandle))
1457 /* compute timers settings */
1458 /* simplest way, fr=4Mhz/(tim1*tim2), channel manipulation without timers effect */
1459 if (((cmd->scan_begin_src == TRIG_FOLLOW) || (cmd->scan_begin_src == TRIG_EXT) || (cmd->scan_begin_src == TRIG_INT)) && (cmd->convert_src == TRIG_TIMER)) { /* both timer is used for one time */
1460 if (cmd->scan_begin_src == TRIG_EXT) {
1465 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1466 &cmd->scan_begin_arg, &cmd->convert_arg,
1468 devpriv->ai_n_realscanlen,
1469 &devpriv->ai_divisor1,
1470 &devpriv->ai_divisor2, devpriv->usessh,
1471 devpriv->ai_add_front);
1472 devpriv->ai_timer2 = cmd->convert_arg;
1475 if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) { /* double timed action */
1476 if (!devpriv->usedma) {
1478 "cmd->scan_begin_src=TRIG_TIMER works only with bus mastering!");
1483 pci9118_calc_divisors(devpriv->ai_do, dev, s,
1484 &cmd->scan_begin_arg, &cmd->convert_arg,
1486 devpriv->ai_n_realscanlen,
1487 &devpriv->ai_divisor1,
1488 &devpriv->ai_divisor2, devpriv->usessh,
1489 devpriv->ai_add_front);
1490 devpriv->ai_timer1 = cmd->scan_begin_arg;
1491 devpriv->ai_timer2 = cmd->convert_arg;
1494 if ((cmd->scan_begin_src == TRIG_FOLLOW)
1495 && (cmd->convert_src == TRIG_EXT)) {
1499 start_pacer(dev, -1, 0, 0); /* stop pacer */
1501 devpriv->AdControlReg = 0; /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA */
1502 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1503 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg; /* positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
1504 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1506 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1507 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D and INT status register */
1508 inl(dev->iobase + PCI9118_INTSRC);
1510 devpriv->ai_act_scan = 0;
1511 devpriv->ai_act_dmapos = 0;
1512 s->async->cur_chan = 0;
1513 devpriv->ai_buf_ptr = 0;
1515 if (devpriv->usedma)
1516 ret = pci9118_ai_docmd_dma(dev, s);
1518 ret = pci9118_ai_docmd_sampl(dev, s);
1520 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1525 ==============================================================================
1527 static int check_channel_list(struct comedi_device *dev,
1528 struct comedi_subdevice *s, int n_chan,
1529 unsigned int *chanlist, int frontadd, int backadd)
1531 unsigned int i, differencial = 0, bipolar = 0;
1533 /* correct channel and range number check itself comedi/range.c */
1535 comedi_error(dev, "range/channel list is empty!");
1538 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
1540 ("comedi%d: range/channel list is too long for actual configuration (%d>%d)!",
1541 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
1545 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1546 differencial = 1; /* all input must be diff */
1547 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1548 bipolar = 1; /* all input must be bipolar */
1550 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
1551 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
1554 "Differencial and single ended inputs cann't be mixtured!");
1557 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
1560 "Bipolar and unipolar ranges cann't be mixtured!");
1563 if ((!devpriv->usemux) & (differencial) &
1564 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
1566 "If AREF_DIFF is used then is available only first 8 channels!");
1575 ==============================================================================
1577 static int setup_channel_list(struct comedi_device *dev,
1578 struct comedi_subdevice *s, int n_chan,
1579 unsigned int *chanlist, int rot, int frontadd,
1580 int backadd, int usedma, char useeos)
1582 unsigned int i, differencial = 0, bipolar = 0;
1583 unsigned int scanquad, gain, ssh = 0x00;
1586 ("adl_pci9118 EDBG: BGN: setup_channel_list(%d,.,%d,.,%d,%d,%d,%d)\n",
1587 dev->minor, n_chan, rot, frontadd, backadd, usedma);
1594 if (CR_AREF(chanlist[0]) == AREF_DIFF)
1595 differencial = 1; /* all input must be diff */
1596 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1597 bipolar = 1; /* all input must be bipolar */
1599 /* All is ok, so we can setup channel/range list */
1602 devpriv->AdControlReg |= AdControl_UniP; /* set unibipolar */
1604 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff); /* enable bipolar */
1608 devpriv->AdControlReg |= AdControl_Diff; /* enable diff inputs */
1610 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff); /* set single ended inputs */
1613 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* setup mode */
1615 outl(2, dev->iobase + PCI9118_SCANMOD); /* gods know why this sequence! */
1616 outl(0, dev->iobase + PCI9118_SCANMOD);
1617 outl(1, dev->iobase + PCI9118_SCANMOD);
1619 #ifdef PCI9118_PARANOIDCHECK
1620 devpriv->chanlistlen = n_chan;
1621 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
1622 devpriv->chanlist[i] = 0x55aa;
1625 if (frontadd) { /* insert channels for S&H */
1626 ssh = devpriv->softsshsample;
1627 DPRINTK("FA: %04x: ", ssh);
1628 for (i = 0; i < frontadd; i++) { /* store range list to card */
1629 scanquad = CR_CHAN(chanlist[0]); /* get channel number; */
1630 gain = CR_RANGE(chanlist[0]); /* get gain number */
1631 scanquad |= ((gain & 0x03) << 8);
1632 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1633 DPRINTK("%02x ", scanquad | ssh);
1634 ssh = devpriv->softsshhold;
1639 DPRINTK("SL: ", ssh);
1640 for (i = 0; i < n_chan; i++) { /* store range list to card */
1641 scanquad = CR_CHAN(chanlist[i]); /* get channel number; */
1642 #ifdef PCI9118_PARANOIDCHECK
1643 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1645 gain = CR_RANGE(chanlist[i]); /* get gain number */
1646 scanquad |= ((gain & 0x03) << 8);
1647 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1648 DPRINTK("%02x ", scanquad | ssh);
1652 if (backadd) { /* insert channels for fit onto 32bit DMA */
1653 DPRINTK("BA: %04x: ", ssh);
1654 for (i = 0; i < backadd; i++) { /* store range list to card */
1655 scanquad = CR_CHAN(chanlist[0]); /* get channel number; */
1656 gain = CR_RANGE(chanlist[0]); /* get gain number */
1657 scanquad |= ((gain & 0x03) << 8);
1658 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1659 DPRINTK("%02x ", scanquad | ssh);
1663 #ifdef PCI9118_PARANOIDCHECK
1664 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma]; /* for 32bit oerations */
1666 for (i = 1; i < n_chan; i++) { /* store range list to card */
1667 devpriv->chanlist[(n_chan + i) ^ usedma] =
1668 (CR_CHAN(chanlist[i]) & 0xf) << rot;
1670 devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma]; /* for 32bit oerations */
1675 #ifdef PCI9118_EXTDEBUG
1677 for (i = 0; i <= (useeos * n_chan); i++) {
1678 DPRINTK("%04x ", devpriv->chanlist[i]);
1683 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
1684 /* udelay(100); important delay, or first sample will be cripled */
1686 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1687 return 1; /* we can serve this with scan logic */
1691 ==============================================================================
1692 calculate 8254 divisors if they are used for dual timing
1694 static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1695 struct comedi_subdevice *s,
1696 unsigned int *tim1, unsigned int *tim2,
1697 unsigned int flags, int chans,
1698 unsigned int *div1, unsigned int *div2,
1699 char usessh, unsigned int chnsshfront)
1702 ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
1703 mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
1707 if (*tim2 < this_board->ai_ns_min)
1708 *tim2 = this_board->ai_ns_min;
1709 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
1710 tim2, flags & TRIG_ROUND_NEAREST);
1711 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
1712 devpriv->i8254_osc_base, *div1, *div2, *tim1);
1715 if (*tim2 < this_board->ai_ns_min)
1716 *tim2 = this_board->ai_ns_min;
1717 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1719 *div1 = *tim2 / devpriv->i8254_osc_base; /* convert timer (burst) */
1720 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1722 if (*div1 < this_board->ai_pacer_min)
1723 *div1 = this_board->ai_pacer_min;
1724 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1726 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
1727 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1729 *div2 = *div2 / *div1; /* major timer is c1*c2 */
1730 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1734 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1737 *tim2 = *div1 * devpriv->i8254_osc_base; /* real convert timer */
1739 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
1740 if (*div2 < (chans + 2))
1743 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1745 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
1746 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
1747 devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
1750 DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
1755 ==============================================================================
1757 static void start_pacer(struct comedi_device *dev, int mode,
1758 unsigned int divisor1, unsigned int divisor2)
1760 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
1761 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
1762 /* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
1765 if ((mode == 1) || (mode == 2) || (mode == 4)) {
1766 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
1767 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
1768 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
1769 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
1774 ==============================================================================
1776 static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
1779 return -1; /* incorrect source */
1780 devpriv->exttrg_users |= (1 << source);
1781 devpriv->IntControlReg |= Int_DTrg;
1782 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1783 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */
1788 ==============================================================================
1790 static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
1793 return -1; /* incorrect source */
1794 devpriv->exttrg_users &= ~(1 << source);
1795 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
1796 devpriv->IntControlReg &= ~Int_DTrg;
1797 if (!devpriv->IntControlReg) /* all IRQ disabled */
1798 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) & (~0x00001f00), devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* disable int in AMCC */
1799 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1805 ==============================================================================
1807 static int pci9118_ai_cancel(struct comedi_device *dev,
1808 struct comedi_subdevice *s)
1810 if (devpriv->usedma)
1811 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
1812 pci9118_exttrg_del(dev, EXTTRG_AI);
1813 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
1814 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1815 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); /* positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
1816 devpriv->AdControlReg = 0x00;
1817 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1818 outl(0, dev->iobase + PCI9118_BURST);
1819 outl(1, dev->iobase + PCI9118_SCANMOD);
1820 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1821 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1824 devpriv->usedma = 0;
1826 devpriv->ai_act_scan = 0;
1827 devpriv->ai_act_dmapos = 0;
1828 s->async->cur_chan = 0;
1829 s->async->inttrig = NULL;
1830 devpriv->ai_buf_ptr = 0;
1831 devpriv->ai_neverending = 0;
1832 devpriv->dma_actbuf = 0;
1834 if (!devpriv->IntControlReg)
1835 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR); /* allow INT in AMCC */
1841 ==============================================================================
1843 static int pci9118_reset(struct comedi_device *dev)
1845 devpriv->IntControlReg = 0;
1846 devpriv->exttrg_users = 0;
1847 inl(dev->iobase + PCI9118_INTCTRL);
1848 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL); /* disable interrupts source */
1849 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1850 /* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1851 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
1852 devpriv->AdControlReg = 0;
1853 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1854 outl(0, dev->iobase + PCI9118_BURST);
1855 outl(1, dev->iobase + PCI9118_SCANMOD);
1856 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
1857 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1858 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC); /* positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
1860 devpriv->ao_data[0] = 2047;
1861 devpriv->ao_data[1] = 2047;
1862 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1); /* reset A/D outs to 0V */
1863 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1864 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
1866 inl(dev->iobase + PCI9118_AD_DATA);
1867 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1868 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
1869 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
1870 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
1871 devpriv->AdControlReg = 0;
1872 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL); /* bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1874 devpriv->cnt0_users = 0;
1875 devpriv->exttrg_users = 0;
1881 ==============================================================================
1883 static int pci9118_attach(struct comedi_device *dev,
1884 struct comedi_devconfig *it)
1886 struct comedi_subdevice *s;
1888 unsigned short master;
1890 unsigned long iobase_a, iobase_9;
1891 struct pci_dev *pcidev;
1892 int opt_bus, opt_slot;
1894 unsigned char pci_bus, pci_slot, pci_func;
1897 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
1899 opt_bus = it->options[0];
1900 opt_slot = it->options[1];
1901 if (it->options[3] & 1) {
1902 master = 0; /* user don't want use bus master */
1907 ret = alloc_private(dev, sizeof(struct pci9118_private));
1909 printk(" - Allocation failed!\n");
1913 /* Look for matching PCI device */
1914 errstr = "not found!";
1916 while (NULL != (pcidev = pci_get_device(PCI_VENDOR_ID_AMCC,
1917 this_board->device_id,
1919 /* Found matching vendor/device. */
1920 if (opt_bus || opt_slot) {
1921 /* Check bus/slot. */
1922 if (opt_bus != pcidev->bus->number
1923 || opt_slot != PCI_SLOT(pcidev->devfn))
1924 continue; /* no match */
1927 * Look for device that isn't in use.
1928 * Enable PCI device and request regions.
1930 if (comedi_pci_enable(pcidev, "adl_pci9118")) {
1932 "failed to enable PCI device and request regions!";
1939 if (opt_bus || opt_slot) {
1940 printk(" - Card at b:s %d:%d %s\n",
1941 opt_bus, opt_slot, errstr);
1943 printk(" - Card %s\n", errstr);
1949 pci_set_master(pcidev);
1952 pci_bus = pcidev->bus->number;
1953 pci_slot = PCI_SLOT(pcidev->devfn);
1954 pci_func = PCI_FUNC(pcidev->devfn);
1956 iobase_a = pci_resource_start(pcidev, 0);
1957 iobase_9 = pci_resource_start(pcidev, 2);
1959 printk(", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx", pci_bus, pci_slot,
1960 pci_func, iobase_9, iobase_a);
1962 dev->iobase = iobase_9;
1963 dev->board_name = this_board->name;
1965 devpriv->pcidev = pcidev;
1966 devpriv->iobase_a = iobase_a;
1970 if (it->options[3] & 2)
1971 irq = 0; /* user don't want use IRQ */
1973 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
1974 "ADLink PCI-9118", dev)) {
1975 printk(", unable to allocate IRQ %d, DISABLING IT",
1977 irq = 0; /* Can't use IRQ */
1979 printk(", irq=%u", irq);
1982 printk(", IRQ disabled");
1987 if (master) { /* alloc DMA buffers */
1988 devpriv->dma_doublebuf = 0;
1989 for (i = 0; i < 2; i++) {
1990 for (pages = 4; pages >= 0; pages--) {
1991 devpriv->dmabuf_virt[i] =
1992 (short *)__get_free_pages(GFP_KERNEL,
1994 if (devpriv->dmabuf_virt[i])
1997 if (devpriv->dmabuf_virt[i]) {
1998 devpriv->dmabuf_pages[i] = pages;
1999 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2000 devpriv->dmabuf_samples[i] =
2001 devpriv->dmabuf_size[i] >> 1;
2002 devpriv->dmabuf_hw[i] =
2003 virt_to_bus((void *)
2004 devpriv->dmabuf_virt[i]);
2007 if (!devpriv->dmabuf_virt[0]) {
2008 printk(", Can't allocate DMA buffer, DMA disabled!");
2012 if (devpriv->dmabuf_virt[1])
2013 devpriv->dma_doublebuf = 1;
2017 devpriv->master = master;
2018 if (devpriv->master)
2019 printk(", bus master");
2021 printk(", no bus master");
2023 devpriv->usemux = 0;
2024 if (it->options[2] > 0) {
2025 devpriv->usemux = it->options[2];
2026 if (devpriv->usemux > 256)
2027 devpriv->usemux = 256; /* max 256 channels! */
2028 if (it->options[4] > 0)
2029 if (devpriv->usemux > 128) {
2030 devpriv->usemux = 128; /* max 128 channels with softare S&H! */
2032 printk(", ext. mux %d channels", devpriv->usemux);
2035 devpriv->softsshdelay = it->options[4];
2036 if (devpriv->softsshdelay < 0) { /* select sample&hold signal polarity */
2037 devpriv->softsshdelay = -devpriv->softsshdelay;
2038 devpriv->softsshsample = 0x80;
2039 devpriv->softsshhold = 0x00;
2041 devpriv->softsshsample = 0x00;
2042 devpriv->softsshhold = 0x80;
2047 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
2048 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64); /* Enable parity check for parity error */
2050 ret = alloc_subdevices(dev, 4);
2054 s = dev->subdevices + 0;
2055 dev->read_subdev = s;
2056 s->type = COMEDI_SUBD_AI;
2057 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2058 if (devpriv->usemux) {
2059 s->n_chan = devpriv->usemux;
2061 s->n_chan = this_board->n_aichan;
2063 s->maxdata = this_board->ai_maxdata;
2064 s->len_chanlist = this_board->n_aichanlist;
2065 s->range_table = this_board->rangelist_ai;
2066 s->cancel = pci9118_ai_cancel;
2067 s->insn_read = pci9118_insn_read_ai;
2069 s->subdev_flags |= SDF_CMD_READ;
2070 s->do_cmdtest = pci9118_ai_cmdtest;
2071 s->do_cmd = pci9118_ai_cmd;
2072 s->munge = pci9118_ai_munge;
2075 s = dev->subdevices + 1;
2076 s->type = COMEDI_SUBD_AO;
2077 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2078 s->n_chan = this_board->n_aochan;
2079 s->maxdata = this_board->ao_maxdata;
2080 s->len_chanlist = this_board->n_aochan;
2081 s->range_table = this_board->rangelist_ao;
2082 s->insn_write = pci9118_insn_write_ao;
2083 s->insn_read = pci9118_insn_read_ao;
2085 s = dev->subdevices + 2;
2086 s->type = COMEDI_SUBD_DI;
2087 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2090 s->len_chanlist = 4;
2091 s->range_table = &range_digital;
2092 s->io_bits = 0; /* all bits input */
2093 s->insn_bits = pci9118_insn_bits_di;
2095 s = dev->subdevices + 3;
2096 s->type = COMEDI_SUBD_DO;
2097 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2100 s->len_chanlist = 4;
2101 s->range_table = &range_digital;
2102 s->io_bits = 0xf; /* all bits output */
2103 s->insn_bits = pci9118_insn_bits_do;
2106 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2107 devpriv->ai_maskharderr = 0x10a; /* default measure crash condition */
2108 if (it->options[5]) /* disable some requested */
2109 devpriv->ai_maskharderr &= ~it->options[5];
2111 switch (this_board->ai_maxdata) {
2113 devpriv->ai16bits = 1;
2116 devpriv->ai16bits = 0;
2123 ==============================================================================
2125 static int pci9118_detach(struct comedi_device *dev)
2131 free_irq(dev->irq, dev);
2132 if (devpriv->pcidev) {
2134 comedi_pci_disable(devpriv->pcidev);
2136 pci_dev_put(devpriv->pcidev);
2138 if (devpriv->dmabuf_virt[0])
2139 free_pages((unsigned long)devpriv->dmabuf_virt[0],
2140 devpriv->dmabuf_pages[0]);
2141 if (devpriv->dmabuf_virt[1])
2142 free_pages((unsigned long)devpriv->dmabuf_virt[1],
2143 devpriv->dmabuf_pages[1]);
2150 ==============================================================================