]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/blame - drivers/staging/comedi/drivers/adl_pci9118.c
staging: comedi: fix return value for insn_bits functions
[mirror_ubuntu-hirsute-kernel.git] / drivers / staging / comedi / drivers / adl_pci9118.c
CommitLineData
3063d6de
MD
1/*
2 * comedi/drivers/adl_pci9118.c
3 *
4 * hardware driver for ADLink cards:
5 * card: PCI-9118DG, PCI-9118HG, PCI-9118HR
6 * driver: pci9118dg, pci9118hg, pci9118hr
7 *
8 * Author: Michal Dobes <dobes@tesnet.cz>
9 *
10*/
11/*
12Driver: adl_pci9118
13Description: Adlink PCI-9118DG, PCI-9118HG, PCI-9118HR
14Author: Michal Dobes <dobes@tesnet.cz>
15Devices: [ADLink] PCI-9118DG (pci9118dg), PCI-9118HG (pci9118hg),
16 PCI-9118HR (pci9118hr)
17Status: works
18
19This driver supports AI, AO, DI and DO subdevices.
20AI subdevice supports cmd and insn interface,
21other subdevices support only insn interface.
22For AI:
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).
25985edc 26- It is not necessary to have cmd.scan_end_arg=cmd.chanlist_len but
3063d6de
MD
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
30 ranges).
31
32There are some hardware limitations:
33a) You cann't use mixture of unipolar/bipoar ranges or differencial/single
34 ended inputs.
35b) 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.
41c) If isn't used DMA then you can use only mode where
42 cmd->scan_begin_src=TRIG_FOLLOW.
43
44Configuration options:
45 [0] - PCI bus of device (optional)
46 [1] - PCI slot of device (optional)
d607c781
MD
47 If bus/slot is not specified, then first available PCI
48 card will be used.
3063d6de 49 [2] - 0= standard 8 DIFF/16 SE channels configuration
d607c781 50 n = external multiplexer connected, 1 <= n <= 256
3063d6de 51 [3] - 0=autoselect DMA or EOC interrupts operation
d607c781
MD
52 1 = disable DMA mode
53 3 = disable DMA and INT, only insn interface will work
3063d6de 54 [4] - sample&hold signal - card can generate signal for external S&H board
d607c781
MD
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)
3063d6de 59 [5] - 0=stop measure on all hardware errors
d607c781 60 2 | = ignore ADOR - A/D Overrun status
3063d6de
MD
61 8|=ignore Bover - A/D Burst Mode Overrun status
62 256|=ignore nFull - A/D FIFO Full status
63
64*/
65#include "../comedidev.h"
3063d6de
MD
66
67#include <linux/delay.h>
5a0e3ad6 68#include <linux/gfp.h>
70265d24 69#include <linux/interrupt.h>
845d131e 70#include <linux/io.h>
3063d6de
MD
71
72#include "amcc_s5933.h"
73#include "8253.h"
3063d6de
MD
74#include "comedi_fc.h"
75
47c92858
GKH
76#define PCI_VENDOR_ID_AMCC 0x10e8
77
3063d6de 78/* paranoid checks are broken */
242467bd
MD
79#undef PCI9118_PARANOIDCHECK /*
80 * if defined, then is used code which control
81 * correct channel number on every 12 bit sample
82 */
3063d6de 83
242467bd
MD
84#undef PCI9118_EXTDEBUG /*
85 * if defined then driver prints
86 * a lot of messages
87 */
3063d6de
MD
88
89#undef DPRINTK
90#ifdef PCI9118_EXTDEBUG
5f74ea14 91#define DPRINTK(fmt, args...) printk(fmt, ## args)
3063d6de
MD
92#else
93#define DPRINTK(fmt, args...)
94#endif
95
96#define IORANGE_9118 64 /* I hope */
242467bd
MD
97#define PCI9118_CHANLEN 255 /*
98 * len of chanlist, some source say 256,
99 * but reality looks like 255 :-(
100 */
3063d6de 101
d5a2ffd8
UKK
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 */
3063d6de
MD
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 */
121
0f04c356 122/* bits from A/D control register (PCI9118_ADCNTRL) */
3063d6de
MD
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 */
242467bd
MD
126#define AdControl_ExtG 0x10 /*
127 * 1=8254 countrol controlled by TGIN(pin 46),
128 * 0=controlled by SoftG
129 */
130#define AdControl_ExtM 0x08 /*
131 * 1=external hardware trigger (pin 44),
132 * 0=internal trigger
133 */
134#define AdControl_TmrTr 0x04 /*
135 * 1=8254 is iternal trigger source,
136 * 0=software trigger is source
137 * (register PCI9118_SOFTTRG)
138 */
3063d6de
MD
139#define AdControl_Int 0x02 /* 1=enable INT, 0=disable */
140#define AdControl_Dma 0x01 /* 1=enable DMA, 0=disable */
141
0f04c356 142/* bits from A/D function register (PCI9118_ADFUNC) */
242467bd
MD
143#define AdFunction_PDTrg 0x80 /*
144 * 1=positive,
145 * 0=negative digital trigger
146 * (only positive is correct)
147 */
148#define AdFunction_PETrg 0x40 /*
149 * 1=positive,
150 * 0=negative external trigger
151 * (only positive is correct)
152 */
3063d6de
MD
153#define AdFunction_BSSH 0x20 /* 1=with sample&hold, 0=without */
154#define AdFunction_BM 0x10 /* 1=burst mode, 0=normal mode */
242467bd
MD
155#define AdFunction_BS 0x08 /*
156 * 1=burst mode start,
157 * 0=burst mode stop
158 */
159#define AdFunction_PM 0x04 /*
160 * 1=post trigger mode,
161 * 0=not post trigger
162 */
163#define AdFunction_AM 0x02 /*
164 * 1=about trigger mode,
165 * 0=not about trigger
166 */
3063d6de
MD
167#define AdFunction_Start 0x01 /* 1=trigger start, 0=trigger stop */
168
0f04c356 169/* bits from A/D status register (PCI9118_ADSTAT) */
3063d6de
MD
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 */
179
0f04c356
BP
180/* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
181/* 1=interrupt occur, enable source, 0=interrupt not occur, disable source */
3063d6de
MD
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 */
186
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 */
191
192#define EXTTRG_AI 0 /* ext trg is used by AI */
193
9ced1de6 194static const struct comedi_lrange range_pci9118dg_hr = { 8, {
0a85b6f0
MT
195 BIP_RANGE(5),
196 BIP_RANGE(2.5),
197 BIP_RANGE(1.25),
198 BIP_RANGE(0.625),
199 UNI_RANGE(10),
200 UNI_RANGE(5),
201 UNI_RANGE(2.5),
202 UNI_RANGE(1.25)
203 }
3063d6de
MD
204};
205
9ced1de6 206static const struct comedi_lrange range_pci9118hg = { 8, {
0a85b6f0
MT
207 BIP_RANGE(5),
208 BIP_RANGE(0.5),
209 BIP_RANGE(0.05),
210 BIP_RANGE(0.005),
211 UNI_RANGE(10),
212 UNI_RANGE(1),
213 UNI_RANGE(0.1),
214 UNI_RANGE(0.01)
215 }
3063d6de
MD
216};
217
242467bd
MD
218#define PCI9118_BIPOLAR_RANGES 4 /*
219 * used for test on mixture
220 * of BIP/UNI ranges
221 */
3063d6de 222
193a21e4 223struct boardtype {
242467bd
MD
224 const char *name; /* board name */
225 int vendor_id; /* PCI vendor a device ID of card */
3063d6de 226 int device_id;
242467bd
MD
227 int iorange_amcc; /* iorange for own S5933 region */
228 int iorange_9118; /* pass thru card region size */
229 int n_aichan; /* num of A/D chans */
230 int n_aichand; /* num of A/D chans in diff mode */
231 int mux_aichan; /*
232 * num of A/D chans with
233 * external multiplexor
234 */
235 int n_aichanlist; /* len of chanlist */
236 int n_aochan; /* num of D/A chans */
237 int ai_maxdata; /* resolution of A/D */
238 int ao_maxdata; /* resolution of D/A */
239 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
240 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
241 unsigned int ai_ns_min; /* max sample speed of card v ns */
242 unsigned int ai_pacer_min; /*
243 * minimal pacer value
244 * (c1*c2 or c1 in burst)
245 */
246 int half_fifo_size; /* size of FIFO/2 */
3063d6de 247
193a21e4 248};
3063d6de 249
5b5fc21b 250struct pci9118_private {
242467bd
MD
251 unsigned long iobase_a; /* base+size for AMCC chip */
252 unsigned int master; /* master capable */
253 struct pci_dev *pcidev; /* ptr to actual pcidev */
254 unsigned int usemux; /* we want to use external multiplexor! */
3063d6de 255#ifdef PCI9118_PARANOIDCHECK
242467bd
MD
256 unsigned short chanlist[PCI9118_CHANLEN + 1]; /*
257 * list of
258 * scanned channel
259 */
260 unsigned char chanlistlen; /* number of scanlist */
3063d6de 261#endif
242467bd
MD
262 unsigned char AdControlReg; /* A/D control register */
263 unsigned char IntControlReg; /* Interrupt control register */
264 unsigned char AdFunctionReg; /* A/D function register */
265 char valid; /* driver is ok */
266 char ai_neverending; /* we do unlimited AI */
267 unsigned int i8254_osc_base; /* frequence of onboard oscilator */
268 unsigned int ai_do; /* what do AI? 0=nothing, 1 to 4 mode */
269 unsigned int ai_act_scan; /* how many scans we finished */
270 unsigned int ai_buf_ptr; /* data buffer ptr in samples */
271 unsigned int ai_n_chan; /* how many channels is measured */
272 unsigned int ai_n_scanlen; /* len of actual scanlist */
273 unsigned int ai_n_realscanlen; /*
274 * what we must transfer for one
275 * outgoing scan include front/back adds
276 */
277 unsigned int ai_act_dmapos; /* position in actual real stream */
278 unsigned int ai_add_front; /*
279 * how many channels we must add
280 * before scan to satisfy S&H?
281 */
282 unsigned int ai_add_back; /*
283 * how many channels we must add
284 * before scan to satisfy DMA?
285 */
286 unsigned int *ai_chanlist; /* actual chanlist */
3063d6de
MD
287 unsigned int ai_timer1;
288 unsigned int ai_timer2;
289 unsigned int ai_flags;
242467bd
MD
290 char ai12_startstop; /*
291 * measure can start/stop
292 * on external trigger
293 */
294 unsigned int ai_divisor1, ai_divisor2; /*
295 * divisors for start of measure
296 * on external start
297 */
3063d6de 298 unsigned int ai_data_len;
790c5541 299 short *ai_data;
242467bd
MD
300 short ao_data[2]; /* data output buffer */
301 unsigned int ai_scans; /* number of scans to do */
bc04bec0 302 char dma_doublebuf; /* we can use double buffering */
242467bd
MD
303 unsigned int dma_actbuf; /* which buffer is used now */
304 short *dmabuf_virt[2]; /*
305 * pointers to begin of
306 * DMA buffer
307 */
308 unsigned long dmabuf_hw[2]; /* hw address of DMA buff */
309 unsigned int dmabuf_size[2]; /*
310 * size of dma buffer in bytes
311 */
312 unsigned int dmabuf_use_size[2]; /*
313 * which size we may now use
314 * for transfer
315 */
316 unsigned int dmabuf_used_size[2]; /* which size was truly used */
3063d6de 317 unsigned int dmabuf_panic_size[2];
242467bd
MD
318 unsigned int dmabuf_samples[2]; /* size in samples */
319 int dmabuf_pages[2]; /* number of pages in buffer */
320 unsigned char cnt0_users; /*
321 * bit field of 8254 CNT0 users
322 * (0-unused, 1-AO, 2-DI, 3-DO)
323 */
324 unsigned char exttrg_users; /*
325 * bit field of external trigger
326 * users(0-AI, 1-AO, 2-DI, 3-DO)
327 */
328 unsigned int cnt0_divisor; /* actual CNT0 divisor */
329 void (*int_ai_func) (struct comedi_device *, struct comedi_subdevice *,
330 unsigned short,
331 unsigned int,
332 unsigned short); /*
333 * ptr to actual interrupt
334 * AI function
335 */
336 unsigned char ai16bits; /* =1 16 bit card */
337 unsigned char usedma; /* =1 use DMA transfer and not INT */
338 unsigned char useeoshandle; /*
339 * =1 change WAKE_EOS DMA transfer
340 * to fit on every second
341 */
342 unsigned char usessh; /* =1 turn on S&H support */
343 int softsshdelay; /*
344 * >0 use software S&H,
345 * numer is requested delay in ns
346 */
347 unsigned char softsshsample; /*
348 * polarity of S&H signal
349 * in sample state
350 */
351 unsigned char softsshhold; /*
352 * polarity of S&H signal
353 * in hold state
354 */
355 unsigned int ai_maskerr; /* which warning was printed */
356 unsigned int ai_maskharderr; /* on which error bits stops */
357 unsigned int ai_inttrig_start; /* TRIG_INT for start */
5b5fc21b 358};
3063d6de 359
5b5fc21b 360#define devpriv ((struct pci9118_private *)dev->private)
193a21e4 361#define this_board ((struct boardtype *)dev->board_ptr)
3063d6de
MD
362
363/*
364==============================================================================
365*/
366
0a85b6f0
MT
367static int check_channel_list(struct comedi_device *dev,
368 struct comedi_subdevice *s, int n_chan,
369 unsigned int *chanlist, int frontadd,
370 int backadd);
371static int setup_channel_list(struct comedi_device *dev,
372 struct comedi_subdevice *s, int n_chan,
373 unsigned int *chanlist, int rot, int frontadd,
374 int backadd, int usedma, char eoshandle);
375static void start_pacer(struct comedi_device *dev, int mode,
376 unsigned int divisor1, unsigned int divisor2);
da91b269
BP
377static int pci9118_reset(struct comedi_device *dev);
378static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source);
379static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source);
0a85b6f0
MT
380static int pci9118_ai_cancel(struct comedi_device *dev,
381 struct comedi_subdevice *s);
da91b269 382static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
0a85b6f0
MT
383 struct comedi_subdevice *s,
384 unsigned int *tim1, unsigned int *tim2,
385 unsigned int flags, int chans,
386 unsigned int *div1, unsigned int *div2,
387 char usessh, unsigned int chnsshfront);
3063d6de
MD
388
389/*
390==============================================================================
391*/
0a85b6f0
MT
392static int pci9118_insn_read_ai(struct comedi_device *dev,
393 struct comedi_subdevice *s,
394 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
395{
396
397 int n, timeout;
398
399 devpriv->AdControlReg = AdControl_Int & 0xff;
400 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
242467bd
MD
401 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
402 /*
403 * positive triggers, no S&H,
404 * no burst, burst stop,
405 * no post trigger,
406 * no about trigger,
407 * trigger stop
408 */
3063d6de
MD
409
410 if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
411 return -EINVAL;
412
242467bd 413 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
414
415 for (n = 0; n < insn->n; n++) {
416 outw(0, dev->iobase + PCI9118_SOFTTRG); /* start conversion */
5f74ea14 417 udelay(2);
3063d6de
MD
418 timeout = 100;
419 while (timeout--) {
420 if (inl(dev->iobase + PCI9118_ADSTAT) & AdStatus_ADrdy)
421 goto conv_finish;
5f74ea14 422 udelay(1);
3063d6de
MD
423 }
424
425 comedi_error(dev, "A/D insn timeout");
426 data[n] = 0;
242467bd 427 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
428 return -ETIME;
429
0a85b6f0 430conv_finish:
3063d6de
MD
431 if (devpriv->ai16bits) {
432 data[n] =
0a85b6f0
MT
433 (inl(dev->iobase +
434 PCI9118_AD_DATA) & 0xffff) ^ 0x8000;
3063d6de
MD
435 } else {
436 data[n] =
0a85b6f0 437 (inw(dev->iobase + PCI9118_AD_DATA) >> 4) & 0xfff;
3063d6de
MD
438 }
439 }
440
242467bd 441 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
442 return n;
443
444}
445
446/*
447==============================================================================
448*/
0a85b6f0
MT
449static int pci9118_insn_write_ao(struct comedi_device *dev,
450 struct comedi_subdevice *s,
451 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
452{
453 int n, chanreg, ch;
454
455 ch = CR_CHAN(insn->chanspec);
a41aec1b 456 if (ch)
3063d6de 457 chanreg = PCI9118_DA2;
a41aec1b 458 else
3063d6de 459 chanreg = PCI9118_DA1;
a41aec1b 460
3063d6de
MD
461
462 for (n = 0; n < insn->n; n++) {
463 outl(data[n], dev->iobase + chanreg);
464 devpriv->ao_data[ch] = data[n];
465 }
466
467 return n;
468}
469
470/*
471==============================================================================
472*/
0a85b6f0
MT
473static int pci9118_insn_read_ao(struct comedi_device *dev,
474 struct comedi_subdevice *s,
475 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
476{
477 int n, chan;
478
479 chan = CR_CHAN(insn->chanspec);
480 for (n = 0; n < insn->n; n++)
481 data[n] = devpriv->ao_data[chan];
482
483 return n;
484}
485
486/*
487==============================================================================
488*/
0a85b6f0
MT
489static int pci9118_insn_bits_di(struct comedi_device *dev,
490 struct comedi_subdevice *s,
491 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
492{
493 data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
494
a2714e3e 495 return insn->n;
3063d6de
MD
496}
497
498/*
499==============================================================================
500*/
0a85b6f0
MT
501static int pci9118_insn_bits_do(struct comedi_device *dev,
502 struct comedi_subdevice *s,
503 struct comedi_insn *insn, unsigned int *data)
3063d6de
MD
504{
505 if (data[0]) {
506 s->state &= ~data[0];
507 s->state |= (data[0] & data[1]);
508 outl(s->state & 0x0f, dev->iobase + PCI9118_DO);
509 }
510 data[1] = s->state;
511
a2714e3e 512 return insn->n;
3063d6de
MD
513}
514
515/*
516==============================================================================
517*/
da91b269 518static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
3063d6de
MD
519{
520 devpriv->AdFunctionReg =
0a85b6f0 521 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
3063d6de
MD
522 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
523 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
524 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 1) & 0xff,
0a85b6f0 525 dev->iobase + PCI9118_CNT0);
3063d6de 526 outl((devpriv->dmabuf_hw[1 - devpriv->dma_actbuf] >> 9) & 0xff,
0a85b6f0 527 dev->iobase + PCI9118_CNT0);
3063d6de
MD
528 devpriv->AdFunctionReg |= AdFunction_Start;
529 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
530}
531
da91b269 532static unsigned int defragment_dma_buffer(struct comedi_device *dev,
0a85b6f0
MT
533 struct comedi_subdevice *s,
534 short *dma_buffer,
535 unsigned int num_samples)
3063d6de
MD
536{
537 unsigned int i = 0, j = 0;
538 unsigned int start_pos = devpriv->ai_add_front,
0a85b6f0 539 stop_pos = devpriv->ai_add_front + devpriv->ai_n_chan;
3063d6de 540 unsigned int raw_scanlen = devpriv->ai_add_front + devpriv->ai_n_chan +
0a85b6f0 541 devpriv->ai_add_back;
3063d6de
MD
542
543 for (i = 0; i < num_samples; i++) {
544 if (devpriv->ai_act_dmapos >= start_pos &&
0a85b6f0 545 devpriv->ai_act_dmapos < stop_pos) {
3063d6de
MD
546 dma_buffer[j++] = dma_buffer[i];
547 }
548 devpriv->ai_act_dmapos++;
549 devpriv->ai_act_dmapos %= raw_scanlen;
550 }
551
552 return j;
553}
554
555/*
556==============================================================================
557*/
d6269644 558static int move_block_from_dma(struct comedi_device *dev,
0a85b6f0
MT
559 struct comedi_subdevice *s,
560 short *dma_buffer,
561 unsigned int num_samples)
3063d6de
MD
562{
563 unsigned int num_bytes;
564
565 num_samples = defragment_dma_buffer(dev, s, dma_buffer, num_samples);
566 devpriv->ai_act_scan +=
0a85b6f0 567 (s->async->cur_chan + num_samples) / devpriv->ai_n_scanlen;
3063d6de
MD
568 s->async->cur_chan += num_samples;
569 s->async->cur_chan %= devpriv->ai_n_scanlen;
570 num_bytes =
0a85b6f0
MT
571 cfc_write_array_to_buffer(s, dma_buffer,
572 num_samples * sizeof(short));
790c5541 573 if (num_bytes < num_samples * sizeof(short))
3063d6de
MD
574 return -1;
575 return 0;
576}
577
578/*
579==============================================================================
580*/
da91b269 581static char pci9118_decode_error_status(struct comedi_device *dev,
0a85b6f0
MT
582 struct comedi_subdevice *s,
583 unsigned char m)
3063d6de
MD
584{
585 if (m & 0x100) {
586 comedi_error(dev, "A/D FIFO Full status (Fatal Error!)");
587 devpriv->ai_maskerr &= ~0x100L;
588 }
589 if (m & 0x008) {
590 comedi_error(dev,
0a85b6f0 591 "A/D Burst Mode Overrun Status (Fatal Error!)");
3063d6de
MD
592 devpriv->ai_maskerr &= ~0x008L;
593 }
594 if (m & 0x004) {
595 comedi_error(dev, "A/D Over Speed Status (Warning!)");
596 devpriv->ai_maskerr &= ~0x004L;
597 }
598 if (m & 0x002) {
599 comedi_error(dev, "A/D Overrun Status (Fatal Error!)");
600 devpriv->ai_maskerr &= ~0x002L;
601 }
602 if (m & devpriv->ai_maskharderr) {
603 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
604 pci9118_ai_cancel(dev, s);
605 comedi_event(dev, s);
606 return 1;
607 }
608
609 return 0;
610}
611
0a85b6f0
MT
612static void pci9118_ai_munge(struct comedi_device *dev,
613 struct comedi_subdevice *s, void *data,
614 unsigned int num_bytes,
615 unsigned int start_chan_index)
3063d6de 616{
790c5541
BP
617 unsigned int i, num_samples = num_bytes / sizeof(short);
618 short *array = data;
3063d6de
MD
619
620 for (i = 0; i < num_samples; i++) {
621 if (devpriv->usedma)
622 array[i] = be16_to_cpu(array[i]);
a41aec1b 623 if (devpriv->ai16bits)
3063d6de 624 array[i] ^= 0x8000;
a41aec1b 625 else
3063d6de 626 array[i] = (array[i] >> 4) & 0x0fff;
a41aec1b 627
3063d6de
MD
628 }
629}
630
631/*
632==============================================================================
633*/
da91b269 634static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
0a85b6f0
MT
635 struct comedi_subdevice *s,
636 unsigned short int_adstat,
637 unsigned int int_amcc,
638 unsigned short int_daq)
3063d6de 639{
790c5541 640 register short sampl;
3063d6de
MD
641
642 s->async->events = 0;
643
644 if (int_adstat & devpriv->ai_maskerr)
645 if (pci9118_decode_error_status(dev, s, int_adstat))
646 return;
647
648 sampl = inw(dev->iobase + PCI9118_AD_DATA);
649
650#ifdef PCI9118_PARANOIDCHECK
651 if (devpriv->ai16bits == 0) {
242467bd
MD
652 if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {
653 /* data dropout! */
5f74ea14 654 printk
242467bd
MD
655 ("comedi: A/D SAMPL - data dropout: "
656 "received channel %d, expected %d!\n",
657 sampl & 0x000f,
658 devpriv->chanlist[s->async->cur_chan]);
3063d6de
MD
659 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
660 pci9118_ai_cancel(dev, s);
661 comedi_event(dev, s);
662 return;
663 }
664 }
665#endif
666 cfc_write_to_buffer(s, sampl);
667 s->async->cur_chan++;
242467bd
MD
668 if (s->async->cur_chan >= devpriv->ai_n_scanlen) {
669 /* one scan done */
3063d6de
MD
670 s->async->cur_chan %= devpriv->ai_n_scanlen;
671 devpriv->ai_act_scan++;
672 if (!(devpriv->ai_neverending))
242467bd
MD
673 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
674 /* all data sampled */
3063d6de
MD
675 pci9118_ai_cancel(dev, s);
676 s->async->events |= COMEDI_CB_EOA;
677 }
678 }
679
680 if (s->async->events)
681 comedi_event(dev, s);
682}
683
684/*
685==============================================================================
686*/
0a85b6f0
MT
687static void interrupt_pci9118_ai_dma(struct comedi_device *dev,
688 struct comedi_subdevice *s,
689 unsigned short int_adstat,
690 unsigned int int_amcc,
691 unsigned short int_daq)
3063d6de
MD
692{
693 unsigned int next_dma_buf, samplesinbuf, sampls, m;
694
695 if (int_amcc & MASTER_ABORT_INT) {
696 comedi_error(dev, "AMCC IRQ - MASTER DMA ABORT!");
697 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
698 pci9118_ai_cancel(dev, s);
699 comedi_event(dev, s);
700 return;
701 }
702
703 if (int_amcc & TARGET_ABORT_INT) {
704 comedi_error(dev, "AMCC IRQ - TARGET DMA ABORT!");
705 s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
706 pci9118_ai_cancel(dev, s);
707 comedi_event(dev, s);
708 return;
709 }
3063d6de 710 if (int_adstat & devpriv->ai_maskerr)
cf8d3af5 711 /* if (int_adstat & 0x106) */
3063d6de
MD
712 if (pci9118_decode_error_status(dev, s, int_adstat))
713 return;
714
242467bd
MD
715 samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;
716 /* number of received real samples */
0f04c356 717/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
3063d6de 718
242467bd
MD
719 if (devpriv->dma_doublebuf) { /*
720 * switch DMA buffers if is used
721 * double buffering
722 */
3063d6de
MD
723 next_dma_buf = 1 - devpriv->dma_actbuf;
724 outl(devpriv->dmabuf_hw[next_dma_buf],
0a85b6f0 725 devpriv->iobase_a + AMCC_OP_REG_MWAR);
3063d6de 726 outl(devpriv->dmabuf_use_size[next_dma_buf],
0a85b6f0 727 devpriv->iobase_a + AMCC_OP_REG_MWTC);
3063d6de 728 devpriv->dmabuf_used_size[next_dma_buf] =
0a85b6f0 729 devpriv->dmabuf_use_size[next_dma_buf];
3063d6de
MD
730 if (devpriv->ai_do == 4)
731 interrupt_pci9118_ai_mode4_switch(dev);
732 }
733
734 if (samplesinbuf) {
242467bd
MD
735 m = devpriv->ai_data_len >> 1; /*
736 * how many samples is to
737 * end of buffer
738 */
739/*
740 * DPRINTK("samps=%d m=%d %d %d\n",
741 * samplesinbuf,m,s->async->buf_int_count,s->async->buf_int_ptr);
742 */
3063d6de
MD
743 sampls = m;
744 move_block_from_dma(dev, s,
0a85b6f0
MT
745 devpriv->dmabuf_virt[devpriv->dma_actbuf],
746 samplesinbuf);
25985edc 747 m = m - sampls; /* m= how many samples was transferred */
3063d6de 748 }
0f04c356 749/* DPRINTK("YYY\n"); */
3063d6de
MD
750
751 if (!devpriv->ai_neverending)
242467bd
MD
752 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
753 /* all data sampled */
3063d6de
MD
754 pci9118_ai_cancel(dev, s);
755 s->async->events |= COMEDI_CB_EOA;
756 }
757
242467bd 758 if (devpriv->dma_doublebuf) { /* switch dma buffers */
3063d6de 759 devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
242467bd 760 } else { /* restart DMA if is not used double buffering */
3063d6de 761 outl(devpriv->dmabuf_hw[0],
0a85b6f0 762 devpriv->iobase_a + AMCC_OP_REG_MWAR);
3063d6de 763 outl(devpriv->dmabuf_use_size[0],
0a85b6f0 764 devpriv->iobase_a + AMCC_OP_REG_MWTC);
3063d6de
MD
765 if (devpriv->ai_do == 4)
766 interrupt_pci9118_ai_mode4_switch(dev);
767 }
768
769 comedi_event(dev, s);
770}
771
772/*
773==============================================================================
774*/
70265d24 775static irqreturn_t interrupt_pci9118(int irq, void *d)
3063d6de 776{
71b5f4f1 777 struct comedi_device *dev = d;
3063d6de
MD
778 unsigned int int_daq = 0, int_amcc, int_adstat;
779
780 if (!dev->attached)
242467bd 781 return IRQ_NONE; /* not fully initialized */
3063d6de 782
242467bd
MD
783 int_daq = inl(dev->iobase + PCI9118_INTSRC) & 0xf;
784 /* get IRQ reasons from card */
785 int_amcc = inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR);
786 /* get INT register from AMCC chip */
3063d6de 787
242467bd
MD
788/*
789 * DPRINTK("INT daq=0x%01x amcc=0x%08x MWAR=0x%08x
790 * MWTC=0x%08x ADSTAT=0x%02x ai_do=%d\n",
791 * int_daq, int_amcc, inl(devpriv->iobase_a+AMCC_OP_REG_MWAR),
792 * inl(devpriv->iobase_a+AMCC_OP_REG_MWTC),
793 * inw(dev->iobase+PCI9118_ADSTAT)&0x1ff,devpriv->ai_do);
794 */
3063d6de
MD
795
796 if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
242467bd 797 return IRQ_NONE; /* interrupt from other source */
3063d6de 798
242467bd
MD
799 outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);
800 /* shutdown IRQ reasons in AMCC */
3063d6de 801
242467bd
MD
802 int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;
803 /* get STATUS register */
3063d6de
MD
804
805 if (devpriv->ai_do) {
806 if (devpriv->ai12_startstop)
242467bd
MD
807 if ((int_adstat & AdStatus_DTH) &&
808 (int_daq & Int_DTrg)) {
809 /* start stop of measure */
3063d6de
MD
810 if (devpriv->ai12_startstop & START_AI_EXT) {
811 devpriv->ai12_startstop &=
0a85b6f0 812 ~START_AI_EXT;
3063d6de 813 if (!(devpriv->ai12_startstop &
242467bd
MD
814 STOP_AI_EXT))
815 pci9118_exttrg_del
816 (dev, EXTTRG_AI);
817 /* deactivate EXT trigger */
818 start_pacer(dev, devpriv->ai_do,
819 devpriv->ai_divisor1,
820 devpriv->ai_divisor2);
821 /* start pacer */
3063d6de 822 outl(devpriv->AdControlReg,
242467bd 823 dev->iobase + PCI9118_ADCNTRL);
3063d6de 824 } else {
0a85b6f0 825 if (devpriv->ai12_startstop &
242467bd 826 STOP_AI_EXT) {
3063d6de 827 devpriv->ai12_startstop &=
242467bd
MD
828 ~STOP_AI_EXT;
829 pci9118_exttrg_del
830 (dev, EXTTRG_AI);
831 /* deactivate EXT trigger */
832 devpriv->ai_neverending = 0;
833 /*
834 * well, on next interrupt from
835 * DMA/EOC measure will stop
836 */
3063d6de
MD
837 }
838 }
839 }
840
841 (devpriv->int_ai_func) (dev, dev->subdevices + 0, int_adstat,
0a85b6f0 842 int_amcc, int_daq);
3063d6de
MD
843
844 }
845 return IRQ_HANDLED;
846}
847
848/*
849==============================================================================
850*/
0a85b6f0
MT
851static int pci9118_ai_inttrig(struct comedi_device *dev,
852 struct comedi_subdevice *s, unsigned int trignum)
3063d6de
MD
853{
854 if (trignum != devpriv->ai_inttrig_start)
855 return -EINVAL;
856
857 devpriv->ai12_startstop &= ~START_AI_INT;
858 s->async->inttrig = NULL;
859
860 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
861 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
862 if (devpriv->ai_do != 3) {
863 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 864 devpriv->ai_divisor2);
3063d6de
MD
865 devpriv->AdControlReg |= AdControl_SoftG;
866 }
867 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
868
869 return 1;
870}
871
872/*
873==============================================================================
874*/
0a85b6f0
MT
875static int pci9118_ai_cmdtest(struct comedi_device *dev,
876 struct comedi_subdevice *s,
877 struct comedi_cmd *cmd)
3063d6de
MD
878{
879 int err = 0;
5f35f3f1
GKH
880 int tmp;
881 unsigned int divisor1 = 0, divisor2 = 0;
3063d6de
MD
882
883 /* step 1: make sure trigger sources are trivially valid */
884
885 tmp = cmd->start_src;
886 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT;
887 if (!cmd->start_src || tmp != cmd->start_src)
888 err++;
889
890 tmp = cmd->scan_begin_src;
a41aec1b 891 if (devpriv->master)
3063d6de 892 cmd->scan_begin_src &= TRIG_TIMER | TRIG_EXT | TRIG_FOLLOW;
a41aec1b 893 else
3063d6de 894 cmd->scan_begin_src &= TRIG_FOLLOW;
a41aec1b 895
3063d6de
MD
896 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
897 err++;
898
899 tmp = cmd->convert_src;
a41aec1b 900 if (devpriv->master)
3063d6de 901 cmd->convert_src &= TRIG_TIMER | TRIG_EXT | TRIG_NOW;
a41aec1b 902 else
3063d6de 903 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
a41aec1b 904
3063d6de
MD
905 if (!cmd->convert_src || tmp != cmd->convert_src)
906 err++;
907
908 tmp = cmd->scan_end_src;
909 cmd->scan_end_src &= TRIG_COUNT;
910 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
911 err++;
912
913 tmp = cmd->stop_src;
914 cmd->stop_src &= TRIG_COUNT | TRIG_NONE | TRIG_EXT;
915 if (!cmd->stop_src || tmp != cmd->stop_src)
916 err++;
917
918 if (err)
919 return 1;
920
242467bd
MD
921 /*
922 * step 2:
923 * make sure trigger sources are
924 * unique and mutually compatible
925 */
3063d6de
MD
926
927 if (cmd->start_src != TRIG_NOW &&
0a85b6f0 928 cmd->start_src != TRIG_INT && cmd->start_src != TRIG_EXT) {
3063d6de
MD
929 cmd->start_src = TRIG_NOW;
930 err++;
931 }
932
933 if (cmd->scan_begin_src != TRIG_TIMER &&
0a85b6f0
MT
934 cmd->scan_begin_src != TRIG_EXT &&
935 cmd->scan_begin_src != TRIG_INT &&
936 cmd->scan_begin_src != TRIG_FOLLOW) {
3063d6de
MD
937 cmd->scan_begin_src = TRIG_FOLLOW;
938 err++;
939 }
940
941 if (cmd->convert_src != TRIG_TIMER &&
0a85b6f0 942 cmd->convert_src != TRIG_EXT && cmd->convert_src != TRIG_NOW) {
3063d6de
MD
943 cmd->convert_src = TRIG_TIMER;
944 err++;
945 }
946
947 if (cmd->scan_end_src != TRIG_COUNT) {
948 cmd->scan_end_src = TRIG_COUNT;
949 err++;
950 }
951
952 if (cmd->stop_src != TRIG_NONE &&
0a85b6f0
MT
953 cmd->stop_src != TRIG_COUNT &&
954 cmd->stop_src != TRIG_INT && cmd->stop_src != TRIG_EXT) {
3063d6de
MD
955 cmd->stop_src = TRIG_COUNT;
956 err++;
957 }
958
959 if (cmd->start_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
960 cmd->start_src = TRIG_NOW;
961 err++;
962 }
963
964 if (cmd->start_src == TRIG_INT && cmd->scan_begin_src == TRIG_INT) {
965 cmd->start_src = TRIG_NOW;
966 err++;
967 }
968
969 if ((cmd->scan_begin_src & (TRIG_TIMER | TRIG_EXT)) &&
0a85b6f0 970 (!(cmd->convert_src & (TRIG_TIMER | TRIG_NOW)))) {
3063d6de
MD
971 cmd->convert_src = TRIG_TIMER;
972 err++;
973 }
974
975 if ((cmd->scan_begin_src == TRIG_FOLLOW) &&
0a85b6f0 976 (!(cmd->convert_src & (TRIG_TIMER | TRIG_EXT)))) {
3063d6de
MD
977 cmd->convert_src = TRIG_TIMER;
978 err++;
979 }
980
981 if (cmd->stop_src == TRIG_EXT && cmd->scan_begin_src == TRIG_EXT) {
982 cmd->stop_src = TRIG_COUNT;
983 err++;
984 }
985
986 if (err)
987 return 2;
988
989 /* step 3: make sure arguments are trivially compatible */
990
991 if (cmd->start_src & (TRIG_NOW | TRIG_EXT))
992 if (cmd->start_arg != 0) {
993 cmd->start_arg = 0;
994 err++;
995 }
996
997 if (cmd->scan_begin_src & (TRIG_FOLLOW | TRIG_EXT))
998 if (cmd->scan_begin_arg != 0) {
999 cmd->scan_begin_arg = 0;
1000 err++;
1001 }
1002
1003 if ((cmd->scan_begin_src == TRIG_TIMER) &&
0a85b6f0 1004 (cmd->convert_src == TRIG_TIMER) && (cmd->scan_end_arg == 1)) {
3063d6de
MD
1005 cmd->scan_begin_src = TRIG_FOLLOW;
1006 cmd->convert_arg = cmd->scan_begin_arg;
1007 cmd->scan_begin_arg = 0;
1008 }
1009
1010 if (cmd->scan_begin_src == TRIG_TIMER)
1011 if (cmd->scan_begin_arg < this_board->ai_ns_min) {
1012 cmd->scan_begin_arg = this_board->ai_ns_min;
1013 err++;
1014 }
1015
1016 if (cmd->scan_begin_src == TRIG_EXT)
1017 if (cmd->scan_begin_arg) {
1018 cmd->scan_begin_arg = 0;
1019 err++;
1020 if (cmd->scan_end_arg > 65535) {
1021 cmd->scan_end_arg = 65535;
1022 err++;
1023 }
1024 }
1025
1026 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW))
1027 if (cmd->convert_arg < this_board->ai_ns_min) {
1028 cmd->convert_arg = this_board->ai_ns_min;
1029 err++;
1030 }
1031
1032 if (cmd->convert_src == TRIG_EXT)
1033 if (cmd->convert_arg) {
1034 cmd->convert_arg = 0;
1035 err++;
1036 }
1037
1038 if (cmd->stop_src == TRIG_COUNT) {
1039 if (!cmd->stop_arg) {
1040 cmd->stop_arg = 1;
1041 err++;
1042 }
1043 } else { /* TRIG_NONE */
1044 if (cmd->stop_arg != 0) {
1045 cmd->stop_arg = 0;
1046 err++;
1047 }
1048 }
1049
1050 if (!cmd->chanlist_len) {
1051 cmd->chanlist_len = 1;
1052 err++;
1053 }
1054
1055 if (cmd->chanlist_len > this_board->n_aichanlist) {
1056 cmd->chanlist_len = this_board->n_aichanlist;
1057 err++;
1058 }
1059
1060 if (cmd->scan_end_arg < cmd->chanlist_len) {
1061 cmd->scan_end_arg = cmd->chanlist_len;
1062 err++;
1063 }
1064
1065 if ((cmd->scan_end_arg % cmd->chanlist_len)) {
1066 cmd->scan_end_arg =
0a85b6f0 1067 cmd->chanlist_len * (cmd->scan_end_arg / cmd->chanlist_len);
3063d6de
MD
1068 err++;
1069 }
1070
1071 if (err)
1072 return 3;
1073
1074 /* step 4: fix up any arguments */
1075
1076 if (cmd->scan_begin_src == TRIG_TIMER) {
1077 tmp = cmd->scan_begin_arg;
5f74ea14 1078/* printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
3063d6de 1079 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
0a85b6f0
MT
1080 &divisor2, &cmd->scan_begin_arg,
1081 cmd->flags & TRIG_ROUND_MASK);
5f74ea14 1082/* printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
3063d6de
MD
1083 if (cmd->scan_begin_arg < this_board->ai_ns_min)
1084 cmd->scan_begin_arg = this_board->ai_ns_min;
1085 if (tmp != cmd->scan_begin_arg)
1086 err++;
1087 }
1088
1089 if (cmd->convert_src & (TRIG_TIMER | TRIG_NOW)) {
1090 tmp = cmd->convert_arg;
1091 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
0a85b6f0
MT
1092 &divisor2, &cmd->convert_arg,
1093 cmd->flags & TRIG_ROUND_MASK);
5f74ea14 1094/* printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
3063d6de
MD
1095 if (cmd->convert_arg < this_board->ai_ns_min)
1096 cmd->convert_arg = this_board->ai_ns_min;
1097 if (tmp != cmd->convert_arg)
1098 err++;
1099 if (cmd->scan_begin_src == TRIG_TIMER
0a85b6f0 1100 && cmd->convert_src == TRIG_NOW) {
3063d6de
MD
1101 if (cmd->convert_arg == 0) {
1102 if (cmd->scan_begin_arg <
0a85b6f0
MT
1103 this_board->ai_ns_min *
1104 (cmd->scan_end_arg + 2)) {
3063d6de 1105 cmd->scan_begin_arg =
0a85b6f0
MT
1106 this_board->ai_ns_min *
1107 (cmd->scan_end_arg + 2);
5f74ea14 1108/* printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
3063d6de
MD
1109 err++;
1110 }
1111 } else {
1112 if (cmd->scan_begin_arg <
0a85b6f0 1113 cmd->convert_arg * cmd->chanlist_len) {
3063d6de 1114 cmd->scan_begin_arg =
0a85b6f0
MT
1115 cmd->convert_arg *
1116 cmd->chanlist_len;
5f74ea14 1117/* printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
3063d6de
MD
1118 err++;
1119 }
1120 }
1121 }
1122 }
1123
1124 if (err)
1125 return 4;
1126
1127 if (cmd->chanlist)
1128 if (!check_channel_list(dev, s, cmd->chanlist_len,
0a85b6f0 1129 cmd->chanlist, 0, 0))
242467bd 1130 return 5; /* incorrect channels list */
3063d6de
MD
1131
1132 return 0;
1133}
1134
1135/*
1136==============================================================================
1137*/
da91b269 1138static int Compute_and_setup_dma(struct comedi_device *dev)
3063d6de
MD
1139{
1140 unsigned int dmalen0, dmalen1, i;
1141
1142 DPRINTK("adl_pci9118 EDBG: BGN: Compute_and_setup_dma()\n");
1143 dmalen0 = devpriv->dmabuf_size[0];
1144 dmalen1 = devpriv->dmabuf_size[1];
1145 DPRINTK("1 dmalen0=%d dmalen1=%d ai_data_len=%d\n", dmalen0, dmalen1,
1146 devpriv->ai_data_len);
242467bd 1147 /* isn't output buff smaller that our DMA buff? */
3063d6de 1148 if (dmalen0 > (devpriv->ai_data_len)) {
242467bd
MD
1149 dmalen0 = devpriv->ai_data_len & ~3L; /*
1150 * align to 32bit down
1151 */
3063d6de
MD
1152 }
1153 if (dmalen1 > (devpriv->ai_data_len)) {
242467bd
MD
1154 dmalen1 = devpriv->ai_data_len & ~3L; /*
1155 * align to 32bit down
1156 */
3063d6de 1157 }
a285bf99 1158 DPRINTK("2 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
3063d6de 1159
242467bd 1160 /* we want wake up every scan? */
3063d6de
MD
1161 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1162 if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
242467bd 1163 /* uff, too short DMA buffer, disable EOS support! */
3063d6de 1164 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
5f74ea14 1165 printk
242467bd
MD
1166 ("comedi%d: WAR: DMA0 buf too short, can't "
1167 "support TRIG_WAKE_EOS (%d<%d)\n",
0a85b6f0
MT
1168 dev->minor, dmalen0,
1169 devpriv->ai_n_realscanlen << 1);
3063d6de 1170 } else {
242467bd 1171 /* short first DMA buffer to one scan */
3063d6de 1172 dmalen0 = devpriv->ai_n_realscanlen << 1;
0a85b6f0 1173 DPRINTK
242467bd
MD
1174 ("21 dmalen0=%d ai_n_realscanlen=%d "
1175 "useeoshandle=%d\n",
1176 dmalen0, devpriv->ai_n_realscanlen,
1177 devpriv->useeoshandle);
3063d6de
MD
1178 if (devpriv->useeoshandle)
1179 dmalen0 += 2;
1180 if (dmalen0 < 4) {
5f74ea14 1181 printk
242467bd
MD
1182 ("comedi%d: ERR: DMA0 buf len bug? "
1183 "(%d<4)\n",
1184 dev->minor, dmalen0);
3063d6de
MD
1185 dmalen0 = 4;
1186 }
1187 }
1188 }
1189 if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1190 if (dmalen1 < (devpriv->ai_n_realscanlen << 1)) {
242467bd 1191 /* uff, too short DMA buffer, disable EOS support! */
3063d6de 1192 devpriv->ai_flags &= (~TRIG_WAKE_EOS);
5f74ea14 1193 printk
242467bd
MD
1194 ("comedi%d: WAR: DMA1 buf too short, "
1195 "can't support TRIG_WAKE_EOS (%d<%d)\n",
0a85b6f0
MT
1196 dev->minor, dmalen1,
1197 devpriv->ai_n_realscanlen << 1);
3063d6de 1198 } else {
242467bd 1199 /* short second DMA buffer to one scan */
3063d6de 1200 dmalen1 = devpriv->ai_n_realscanlen << 1;
0a85b6f0 1201 DPRINTK
242467bd
MD
1202 ("22 dmalen1=%d ai_n_realscanlen=%d "
1203 "useeoshandle=%d\n",
0a85b6f0
MT
1204 dmalen1, devpriv->ai_n_realscanlen,
1205 devpriv->useeoshandle);
3063d6de
MD
1206 if (devpriv->useeoshandle)
1207 dmalen1 -= 2;
1208 if (dmalen1 < 4) {
5f74ea14 1209 printk
242467bd
MD
1210 ("comedi%d: ERR: DMA1 buf len bug? "
1211 "(%d<4)\n",
1212 dev->minor, dmalen1);
3063d6de
MD
1213 dmalen1 = 4;
1214 }
1215 }
1216 }
1217
a285bf99 1218 DPRINTK("3 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
242467bd 1219 /* transfer without TRIG_WAKE_EOS */
3063d6de 1220 if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
25985edc 1221 /* if it's possible then align DMA buffers to length of scan */
3063d6de
MD
1222 i = dmalen0;
1223 dmalen0 =
0a85b6f0
MT
1224 (dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1225 (devpriv->ai_n_realscanlen << 1);
3063d6de
MD
1226 dmalen0 &= ~3L;
1227 if (!dmalen0)
242467bd 1228 dmalen0 = i; /* uff. very long scan? */
3063d6de
MD
1229 i = dmalen1;
1230 dmalen1 =
0a85b6f0
MT
1231 (dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1232 (devpriv->ai_n_realscanlen << 1);
3063d6de
MD
1233 dmalen1 &= ~3L;
1234 if (!dmalen1)
242467bd
MD
1235 dmalen1 = i; /* uff. very long scan? */
1236 /*
1237 * if measure isn't neverending then test, if it fits whole
1238 * into one or two DMA buffers
1239 */
3063d6de 1240 if (!devpriv->ai_neverending) {
242467bd 1241 /* fits whole measure into one DMA buffer? */
3063d6de 1242 if (dmalen0 >
0a85b6f0
MT
1243 ((devpriv->ai_n_realscanlen << 1) *
1244 devpriv->ai_scans)) {
1245 DPRINTK
a285bf99 1246 ("3.0 ai_n_realscanlen=%d ai_scans=%d\n",
0a85b6f0
MT
1247 devpriv->ai_n_realscanlen,
1248 devpriv->ai_scans);
3063d6de 1249 dmalen0 =
0a85b6f0
MT
1250 (devpriv->ai_n_realscanlen << 1) *
1251 devpriv->ai_scans;
a285bf99 1252 DPRINTK("3.1 dmalen0=%d dmalen1=%d\n", dmalen0,
3063d6de
MD
1253 dmalen1);
1254 dmalen0 &= ~3L;
242467bd
MD
1255 } else { /*
1256 * fits whole measure into
1257 * two DMA buffer?
1258 */
3063d6de 1259 if (dmalen1 >
0a85b6f0
MT
1260 ((devpriv->ai_n_realscanlen << 1) *
1261 devpriv->ai_scans - dmalen0))
3063d6de 1262 dmalen1 =
0a85b6f0
MT
1263 (devpriv->ai_n_realscanlen << 1) *
1264 devpriv->ai_scans - dmalen0;
a285bf99 1265 DPRINTK("3.2 dmalen0=%d dmalen1=%d\n", dmalen0,
3063d6de
MD
1266 dmalen1);
1267 dmalen1 &= ~3L;
1268 }
1269 }
1270 }
1271
a285bf99 1272 DPRINTK("4 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
3063d6de 1273
242467bd 1274 /* these DMA buffer size will be used */
3063d6de
MD
1275 devpriv->dma_actbuf = 0;
1276 devpriv->dmabuf_use_size[0] = dmalen0;
1277 devpriv->dmabuf_use_size[1] = dmalen1;
1278
a285bf99 1279 DPRINTK("5 dmalen0=%d dmalen1=%d\n", dmalen0, dmalen1);
3063d6de
MD
1280#if 0
1281 if (devpriv->ai_n_scanlen < this_board->half_fifo_size) {
1282 devpriv->dmabuf_panic_size[0] =
0a85b6f0
MT
1283 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1284 1) * devpriv->ai_n_scanlen * sizeof(short);
3063d6de 1285 devpriv->dmabuf_panic_size[1] =
0a85b6f0
MT
1286 (this_board->half_fifo_size / devpriv->ai_n_scanlen +
1287 1) * devpriv->ai_n_scanlen * sizeof(short);
3063d6de
MD
1288 } else {
1289 devpriv->dmabuf_panic_size[0] =
0a85b6f0 1290 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[0];
3063d6de 1291 devpriv->dmabuf_panic_size[1] =
0a85b6f0 1292 (devpriv->ai_n_scanlen << 1) % devpriv->dmabuf_size[1];
3063d6de
MD
1293 }
1294#endif
1295
242467bd
MD
1296 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS),
1297 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
3063d6de
MD
1298 outl(devpriv->dmabuf_hw[0], devpriv->iobase_a + AMCC_OP_REG_MWAR);
1299 outl(devpriv->dmabuf_use_size[0], devpriv->iobase_a + AMCC_OP_REG_MWTC);
242467bd 1300 /* init DMA transfer */
3063d6de 1301 outl(0x00000000 | AINT_WRITE_COMPL,
0a85b6f0 1302 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
0f04c356 1303/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
3063d6de
MD
1304
1305 outl(inl(devpriv->iobase_a +
0a85b6f0
MT
1306 AMCC_OP_REG_MCSR) | RESET_A2P_FLAGS | A2P_HI_PRIORITY |
1307 EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_MCSR);
242467bd
MD
1308 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS,
1309 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1310 /* allow bus mastering */
3063d6de
MD
1311
1312 DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1313 return 0;
1314}
1315
1316/*
1317==============================================================================
1318*/
0a85b6f0
MT
1319static int pci9118_ai_docmd_sampl(struct comedi_device *dev,
1320 struct comedi_subdevice *s)
3063d6de
MD
1321{
1322 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_sampl(%d,) [%d]\n",
1323 dev->minor, devpriv->ai_do);
1324 switch (devpriv->ai_do) {
1325 case 1:
1326 devpriv->AdControlReg |= AdControl_TmrTr;
1327 break;
1328 case 2:
1329 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 2 bug!\n");
1330 return -EIO;
1331 case 3:
1332 devpriv->AdControlReg |= AdControl_ExtM;
1333 break;
1334 case 4:
1335 comedi_error(dev, "pci9118_ai_docmd_sampl() mode 4 bug!\n");
1336 return -EIO;
1337 default:
1338 comedi_error(dev,
0a85b6f0 1339 "pci9118_ai_docmd_sampl() mode number bug!\n");
3063d6de 1340 return -EIO;
95cd17c9 1341 }
3063d6de 1342
242467bd
MD
1343 devpriv->int_ai_func = interrupt_pci9118_ai_onesample;
1344 /* transfer function */
3063d6de
MD
1345
1346 if (devpriv->ai12_startstop)
242467bd
MD
1347 pci9118_exttrg_add(dev, EXTTRG_AI);
1348 /* activate EXT trigger */
3063d6de
MD
1349
1350 if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1351 devpriv->IntControlReg |= Int_Timer;
1352
1353 devpriv->AdControlReg |= AdControl_Int;
1354
242467bd
MD
1355 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1356 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1357 /* allow INT in AMCC */
3063d6de
MD
1358
1359 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1360 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1361 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1362 if (devpriv->ai_do != 3) {
1363 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 1364 devpriv->ai_divisor2);
3063d6de
MD
1365 devpriv->AdControlReg |= AdControl_SoftG;
1366 }
1367 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1368 }
1369
1370 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_docmd_sampl()\n");
1371 return 0;
1372}
1373
1374/*
1375==============================================================================
1376*/
0a85b6f0
MT
1377static int pci9118_ai_docmd_dma(struct comedi_device *dev,
1378 struct comedi_subdevice *s)
3063d6de
MD
1379{
1380 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma(%d,) [%d,%d]\n",
1381 dev->minor, devpriv->ai_do, devpriv->usedma);
1382 Compute_and_setup_dma(dev);
1383
1384 switch (devpriv->ai_do) {
1385 case 1:
1386 devpriv->AdControlReg |=
0a85b6f0 1387 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de
MD
1388 break;
1389 case 2:
1390 devpriv->AdControlReg |=
0a85b6f0 1391 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de 1392 devpriv->AdFunctionReg =
0a85b6f0
MT
1393 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_BM |
1394 AdFunction_BS;
3063d6de
MD
1395 if (devpriv->usessh && (!devpriv->softsshdelay))
1396 devpriv->AdFunctionReg |= AdFunction_BSSH;
1397 outl(devpriv->ai_n_realscanlen, dev->iobase + PCI9118_BURST);
1398 break;
1399 case 3:
1400 devpriv->AdControlReg |=
0a85b6f0 1401 ((AdControl_ExtM | AdControl_Dma) & 0xff);
3063d6de
MD
1402 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1403 break;
1404 case 4:
1405 devpriv->AdControlReg |=
0a85b6f0 1406 ((AdControl_TmrTr | AdControl_Dma) & 0xff);
3063d6de 1407 devpriv->AdFunctionReg =
0a85b6f0 1408 AdFunction_PDTrg | AdFunction_PETrg | AdFunction_AM;
3063d6de
MD
1409 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1410 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1411 outl((devpriv->dmabuf_hw[0] >> 1) & 0xff,
0a85b6f0 1412 dev->iobase + PCI9118_CNT0);
3063d6de 1413 outl((devpriv->dmabuf_hw[0] >> 9) & 0xff,
0a85b6f0 1414 dev->iobase + PCI9118_CNT0);
3063d6de
MD
1415 devpriv->AdFunctionReg |= AdFunction_Start;
1416 break;
1417 default:
1418 comedi_error(dev, "pci9118_ai_docmd_dma() mode number bug!\n");
1419 return -EIO;
95cd17c9 1420 }
3063d6de
MD
1421
1422 if (devpriv->ai12_startstop) {
242467bd
MD
1423 pci9118_exttrg_add(dev, EXTTRG_AI);
1424 /* activate EXT trigger */
3063d6de
MD
1425 }
1426
242467bd
MD
1427 devpriv->int_ai_func = interrupt_pci9118_ai_dma;
1428 /* transfer function */
3063d6de
MD
1429
1430 outl(0x02000000 | AINT_WRITE_COMPL,
0a85b6f0 1431 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
3063d6de
MD
1432
1433 if (!(devpriv->ai12_startstop & (START_AI_EXT | START_AI_INT))) {
1434 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1435 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1436 if (devpriv->ai_do != 3) {
1437 start_pacer(dev, devpriv->ai_do, devpriv->ai_divisor1,
0a85b6f0 1438 devpriv->ai_divisor2);
3063d6de
MD
1439 devpriv->AdControlReg |= AdControl_SoftG;
1440 }
1441 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1442 }
1443
1444 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_docmd_dma()\n");
1445 return 0;
1446}
1447
1448/*
1449==============================================================================
1450*/
da91b269 1451static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
3063d6de 1452{
ea6d0d4c 1453 struct comedi_cmd *cmd = &s->async->cmd;
3063d6de
MD
1454 unsigned int addchans = 0;
1455 int ret = 0;
1456
1457 DPRINTK("adl_pci9118 EDBG: BGN: pci9118_ai_cmd(%d,)\n", dev->minor);
1458 devpriv->ai12_startstop = 0;
1459 devpriv->ai_flags = cmd->flags;
1460 devpriv->ai_n_chan = cmd->chanlist_len;
1461 devpriv->ai_n_scanlen = cmd->scan_end_arg;
1462 devpriv->ai_chanlist = cmd->chanlist;
1463 devpriv->ai_data = s->async->prealloc_buf;
1464 devpriv->ai_data_len = s->async->prealloc_bufsz;
1465 devpriv->ai_timer1 = 0;
1466 devpriv->ai_timer2 = 0;
1467 devpriv->ai_add_front = 0;
1468 devpriv->ai_add_back = 0;
1469 devpriv->ai_maskerr = 0x10e;
1470
242467bd 1471 /* prepare for start/stop conditions */
3063d6de
MD
1472 if (cmd->start_src == TRIG_EXT)
1473 devpriv->ai12_startstop |= START_AI_EXT;
1474 if (cmd->stop_src == TRIG_EXT) {
1475 devpriv->ai_neverending = 1;
1476 devpriv->ai12_startstop |= STOP_AI_EXT;
1477 }
1478 if (cmd->start_src == TRIG_INT) {
1479 devpriv->ai12_startstop |= START_AI_INT;
1480 devpriv->ai_inttrig_start = cmd->start_arg;
1481 s->async->inttrig = pci9118_ai_inttrig;
1482 }
1483#if 0
1484 if (cmd->stop_src == TRIG_INT) {
1485 devpriv->ai_neverending = 1;
1486 devpriv->ai12_startstop |= STOP_AI_INT;
1487 }
1488#endif
1489 if (cmd->stop_src == TRIG_NONE)
1490 devpriv->ai_neverending = 1;
1491 if (cmd->stop_src == TRIG_COUNT) {
1492 devpriv->ai_scans = cmd->stop_arg;
1493 devpriv->ai_neverending = 0;
1494 } else {
1495 devpriv->ai_scans = 0;
1496 }
1497
242467bd 1498 /* use sample&hold signal? */
beb50909 1499 if (cmd->convert_src == TRIG_NOW)
3063d6de 1500 devpriv->usessh = 1;
beb50909
MD
1501 /* yes */
1502 else
3063d6de 1503 devpriv->usessh = 0;
beb50909 1504 /* no */
3063d6de
MD
1505
1506 DPRINTK("1 neverending=%d scans=%u usessh=%d ai_startstop=0x%2x\n",
1507 devpriv->ai_neverending, devpriv->ai_scans, devpriv->usessh,
1508 devpriv->ai12_startstop);
1509
242467bd
MD
1510 /*
1511 * use additional sample at end of every scan
1512 * to satisty DMA 32 bit transfer?
1513 */
3063d6de
MD
1514 devpriv->ai_add_front = 0;
1515 devpriv->ai_add_back = 0;
1516 devpriv->useeoshandle = 0;
1517 if (devpriv->master) {
1518 devpriv->usedma = 1;
1519 if ((cmd->flags & TRIG_WAKE_EOS) &&
0a85b6f0 1520 (devpriv->ai_n_scanlen == 1)) {
beb50909 1521 if (cmd->convert_src == TRIG_NOW)
3063d6de 1522 devpriv->ai_add_back = 1;
3063d6de 1523 if (cmd->convert_src == TRIG_TIMER) {
242467bd
MD
1524 devpriv->usedma = 0;
1525 /*
1526 * use INT transfer if scanlist
1527 * have only one channel
1528 */
3063d6de
MD
1529 }
1530 }
1531 if ((cmd->flags & TRIG_WAKE_EOS) &&
0a85b6f0
MT
1532 (devpriv->ai_n_scanlen & 1) &&
1533 (devpriv->ai_n_scanlen > 1)) {
3063d6de 1534 if (cmd->scan_begin_src == TRIG_FOLLOW) {
242467bd
MD
1535 /*
1536 * vpriv->useeoshandle=1; // change DMA transfer
1537 * block to fit EOS on every second call
1538 */
1539 devpriv->usedma = 0;
1540 /*
1541 * XXX maybe can be corrected to use 16 bit DMA
1542 */
1543 } else { /*
1544 * well, we must insert one sample
1545 * to end of EOS to meet 32 bit transfer
1546 */
3063d6de
MD
1547 devpriv->ai_add_back = 1;
1548 }
1549 }
242467bd 1550 } else { /* interrupt transfer don't need any correction */
3063d6de
MD
1551 devpriv->usedma = 0;
1552 }
1553
242467bd
MD
1554 /*
1555 * we need software S&H signal?
1556 * It adds two samples before every scan as minimum
1557 */
3063d6de
MD
1558 if (devpriv->usessh && devpriv->softsshdelay) {
1559 devpriv->ai_add_front = 2;
242467bd
MD
1560 if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {
1561 /* move it to front */
3063d6de
MD
1562 devpriv->ai_add_front++;
1563 devpriv->ai_add_back = 0;
1564 }
1565 if (cmd->convert_arg < this_board->ai_ns_min)
1566 cmd->convert_arg = this_board->ai_ns_min;
1567 addchans = devpriv->softsshdelay / cmd->convert_arg;
1568 if (devpriv->softsshdelay % cmd->convert_arg)
1569 addchans++;
242467bd
MD
1570 if (addchans > (devpriv->ai_add_front - 1)) {
1571 /* uff, still short */
3063d6de
MD
1572 devpriv->ai_add_front = addchans + 1;
1573 if (devpriv->usedma == 1)
1574 if ((devpriv->ai_add_front +
0a85b6f0
MT
1575 devpriv->ai_n_chan +
1576 devpriv->ai_add_back) & 1)
242467bd
MD
1577 devpriv->ai_add_front++;
1578 /* round up to 32 bit */
3063d6de 1579 }
0a85b6f0 1580 }
242467bd
MD
1581 /* well, we now know what must be all added */
1582 devpriv->ai_n_realscanlen = /*
1583 * what we must take from card in real
1584 * to have ai_n_scanlen on output?
1585 */
0a85b6f0
MT
1586 (devpriv->ai_add_front + devpriv->ai_n_chan +
1587 devpriv->ai_add_back) * (devpriv->ai_n_scanlen /
1588 devpriv->ai_n_chan);
3063d6de
MD
1589
1590 DPRINTK("2 usedma=%d realscan=%d af=%u n_chan=%d ab=%d n_scanlen=%d\n",
1591 devpriv->usedma,
1592 devpriv->ai_n_realscanlen, devpriv->ai_add_front,
1593 devpriv->ai_n_chan, devpriv->ai_add_back,
1594 devpriv->ai_n_scanlen);
1595
242467bd 1596 /* check and setup channel list */
3063d6de 1597 if (!check_channel_list(dev, s, devpriv->ai_n_chan,
0a85b6f0
MT
1598 devpriv->ai_chanlist, devpriv->ai_add_front,
1599 devpriv->ai_add_back))
3063d6de
MD
1600 return -EINVAL;
1601 if (!setup_channel_list(dev, s, devpriv->ai_n_chan,
0a85b6f0
MT
1602 devpriv->ai_chanlist, 0, devpriv->ai_add_front,
1603 devpriv->ai_add_back, devpriv->usedma,
1604 devpriv->useeoshandle))
3063d6de
MD
1605 return -EINVAL;
1606
242467bd
MD
1607 /* compute timers settings */
1608 /*
1609 * simplest way, fr=4Mhz/(tim1*tim2),
1610 * channel manipulation without timers effect
1611 */
1612 if (((cmd->scan_begin_src == TRIG_FOLLOW) ||
1613 (cmd->scan_begin_src == TRIG_EXT) ||
1614 (cmd->scan_begin_src == TRIG_INT)) &&
1615 (cmd->convert_src == TRIG_TIMER)) {
1616 /* both timer is used for one time */
beb50909 1617 if (cmd->scan_begin_src == TRIG_EXT)
3063d6de 1618 devpriv->ai_do = 4;
beb50909 1619 else
3063d6de 1620 devpriv->ai_do = 1;
3063d6de 1621 pci9118_calc_divisors(devpriv->ai_do, dev, s,
0a85b6f0
MT
1622 &cmd->scan_begin_arg, &cmd->convert_arg,
1623 devpriv->ai_flags,
1624 devpriv->ai_n_realscanlen,
1625 &devpriv->ai_divisor1,
1626 &devpriv->ai_divisor2, devpriv->usessh,
1627 devpriv->ai_add_front);
3063d6de
MD
1628 devpriv->ai_timer2 = cmd->convert_arg;
1629 }
1630
242467bd
MD
1631 if ((cmd->scan_begin_src == TRIG_TIMER) &&
1632 ((cmd->convert_src == TRIG_TIMER) ||
1633 (cmd->convert_src == TRIG_NOW))) {
1634 /* double timed action */
3063d6de
MD
1635 if (!devpriv->usedma) {
1636 comedi_error(dev,
242467bd
MD
1637 "cmd->scan_begin_src=TRIG_TIMER works "
1638 "only with bus mastering!");
3063d6de
MD
1639 return -EIO;
1640 }
1641
1642 devpriv->ai_do = 2;
1643 pci9118_calc_divisors(devpriv->ai_do, dev, s,
0a85b6f0
MT
1644 &cmd->scan_begin_arg, &cmd->convert_arg,
1645 devpriv->ai_flags,
1646 devpriv->ai_n_realscanlen,
1647 &devpriv->ai_divisor1,
1648 &devpriv->ai_divisor2, devpriv->usessh,
1649 devpriv->ai_add_front);
3063d6de
MD
1650 devpriv->ai_timer1 = cmd->scan_begin_arg;
1651 devpriv->ai_timer2 = cmd->convert_arg;
1652 }
1653
1654 if ((cmd->scan_begin_src == TRIG_FOLLOW)
0a85b6f0 1655 && (cmd->convert_src == TRIG_EXT)) {
3063d6de
MD
1656 devpriv->ai_do = 3;
1657 }
1658
242467bd 1659 start_pacer(dev, -1, 0, 0); /* stop pacer */
3063d6de 1660
242467bd
MD
1661 devpriv->AdControlReg = 0; /*
1662 * bipolar, S.E., use 8254, stop 8354,
1663 * internal trigger, soft trigger,
1664 * disable DMA
1665 */
3063d6de 1666 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
242467bd
MD
1667 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
1668 /*
1669 * positive triggers, no S&H, no burst,
1670 * burst stop, no post trigger,
1671 * no about trigger, trigger stop
1672 */
3063d6de 1673 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
5f74ea14 1674 udelay(1);
242467bd
MD
1675 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
1676 inl(dev->iobase + PCI9118_ADSTAT); /*
1677 * flush A/D and INT
1678 * status register
1679 */
3063d6de
MD
1680 inl(dev->iobase + PCI9118_INTSRC);
1681
1682 devpriv->ai_act_scan = 0;
1683 devpriv->ai_act_dmapos = 0;
1684 s->async->cur_chan = 0;
1685 devpriv->ai_buf_ptr = 0;
1686
c3744138 1687 if (devpriv->usedma)
3063d6de 1688 ret = pci9118_ai_docmd_dma(dev, s);
c3744138 1689 else
3063d6de 1690 ret = pci9118_ai_docmd_sampl(dev, s);
3063d6de
MD
1691
1692 DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1693 return ret;
1694}
1695
1696/*
1697==============================================================================
1698*/
0a85b6f0
MT
1699static int check_channel_list(struct comedi_device *dev,
1700 struct comedi_subdevice *s, int n_chan,
1701 unsigned int *chanlist, int frontadd, int backadd)
3063d6de
MD
1702{
1703 unsigned int i, differencial = 0, bipolar = 0;
1704
1705 /* correct channel and range number check itself comedi/range.c */
1706 if (n_chan < 1) {
1707 comedi_error(dev, "range/channel list is empty!");
1708 return 0;
1709 }
1710 if ((frontadd + n_chan + backadd) > s->len_chanlist) {
5f74ea14 1711 printk
242467bd
MD
1712 ("comedi%d: range/channel list is too long for "
1713 "actual configuration (%d>%d)!",
0a85b6f0 1714 dev->minor, n_chan, s->len_chanlist - frontadd - backadd);
3063d6de
MD
1715 return 0;
1716 }
1717
1718 if (CR_AREF(chanlist[0]) == AREF_DIFF)
242467bd 1719 differencial = 1; /* all input must be diff */
3063d6de 1720 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
242467bd 1721 bipolar = 1; /* all input must be bipolar */
3063d6de 1722 if (n_chan > 1)
242467bd 1723 for (i = 1; i < n_chan; i++) { /* check S.E/diff */
3063d6de 1724 if ((CR_AREF(chanlist[i]) == AREF_DIFF) !=
0a85b6f0 1725 (differencial)) {
3063d6de 1726 comedi_error(dev,
242467bd
MD
1727 "Differencial and single ended "
1728 "inputs can't be mixtured!");
3063d6de
MD
1729 return 0;
1730 }
1731 if ((CR_RANGE(chanlist[i]) < PCI9118_BIPOLAR_RANGES) !=
0a85b6f0 1732 (bipolar)) {
3063d6de 1733 comedi_error(dev,
242467bd
MD
1734 "Bipolar and unipolar ranges "
1735 "can't be mixtured!");
3063d6de
MD
1736 return 0;
1737 }
0bdf8ec0 1738 if (!devpriv->usemux && differencial &&
0a85b6f0 1739 (CR_CHAN(chanlist[i]) >= this_board->n_aichand)) {
3063d6de 1740 comedi_error(dev,
242467bd
MD
1741 "If AREF_DIFF is used then is "
1742 "available only first 8 channels!");
3063d6de
MD
1743 return 0;
1744 }
1745 }
1746
1747 return 1;
1748}
1749
1750/*
1751==============================================================================
1752*/
0a85b6f0
MT
1753static int setup_channel_list(struct comedi_device *dev,
1754 struct comedi_subdevice *s, int n_chan,
1755 unsigned int *chanlist, int rot, int frontadd,
1756 int backadd, int usedma, char useeos)
3063d6de
MD
1757{
1758 unsigned int i, differencial = 0, bipolar = 0;
1759 unsigned int scanquad, gain, ssh = 0x00;
1760
0a85b6f0 1761 DPRINTK
242467bd
MD
1762 ("adl_pci9118 EDBG: BGN: setup_channel_list"
1763 "(%d,.,%d,.,%d,%d,%d,%d)\n",
0a85b6f0 1764 dev->minor, n_chan, rot, frontadd, backadd, usedma);
3063d6de
MD
1765
1766 if (usedma == 1) {
1767 rot = 8;
1768 usedma = 0;
1769 }
1770
1771 if (CR_AREF(chanlist[0]) == AREF_DIFF)
242467bd 1772 differencial = 1; /* all input must be diff */
3063d6de 1773 if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
242467bd 1774 bipolar = 1; /* all input must be bipolar */
3063d6de 1775
242467bd 1776 /* All is ok, so we can setup channel/range list */
3063d6de
MD
1777
1778 if (!bipolar) {
242467bd
MD
1779 devpriv->AdControlReg |= AdControl_UniP;
1780 /* set unibipolar */
3063d6de 1781 } else {
242467bd
MD
1782 devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);
1783 /* enable bipolar */
3063d6de
MD
1784 }
1785
1786 if (differencial) {
242467bd
MD
1787 devpriv->AdControlReg |= AdControl_Diff;
1788 /* enable diff inputs */
3063d6de 1789 } else {
242467bd
MD
1790 devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);
1791 /* set single ended inputs */
3063d6de
MD
1792 }
1793
242467bd
MD
1794 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1795 /* setup mode */
3063d6de 1796
242467bd
MD
1797 outl(2, dev->iobase + PCI9118_SCANMOD);
1798 /* gods know why this sequence! */
3063d6de
MD
1799 outl(0, dev->iobase + PCI9118_SCANMOD);
1800 outl(1, dev->iobase + PCI9118_SCANMOD);
1801
1802#ifdef PCI9118_PARANOIDCHECK
1803 devpriv->chanlistlen = n_chan;
1804 for (i = 0; i < (PCI9118_CHANLEN + 1); i++)
1805 devpriv->chanlist[i] = 0x55aa;
1806#endif
1807
242467bd 1808 if (frontadd) { /* insert channels for S&H */
3063d6de
MD
1809 ssh = devpriv->softsshsample;
1810 DPRINTK("FA: %04x: ", ssh);
242467bd
MD
1811 for (i = 0; i < frontadd; i++) {
1812 /* store range list to card */
1813 scanquad = CR_CHAN(chanlist[0]);
1814 /* get channel number; */
1815 gain = CR_RANGE(chanlist[0]);
1816 /* get gain number */
3063d6de
MD
1817 scanquad |= ((gain & 0x03) << 8);
1818 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1819 DPRINTK("%02x ", scanquad | ssh);
1820 ssh = devpriv->softsshhold;
1821 }
1822 DPRINTK("\n ");
1823 }
1824
1825 DPRINTK("SL: ", ssh);
242467bd
MD
1826 for (i = 0; i < n_chan; i++) { /* store range list to card */
1827 scanquad = CR_CHAN(chanlist[i]); /* get channel number */
3063d6de
MD
1828#ifdef PCI9118_PARANOIDCHECK
1829 devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1830#endif
242467bd 1831 gain = CR_RANGE(chanlist[i]); /* get gain number */
3063d6de
MD
1832 scanquad |= ((gain & 0x03) << 8);
1833 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1834 DPRINTK("%02x ", scanquad | ssh);
1835 }
1836 DPRINTK("\n ");
1837
242467bd 1838 if (backadd) { /* insert channels for fit onto 32bit DMA */
3063d6de 1839 DPRINTK("BA: %04x: ", ssh);
242467bd
MD
1840 for (i = 0; i < backadd; i++) { /* store range list to card */
1841 scanquad = CR_CHAN(chanlist[0]);
1842 /* get channel number */
1843 gain = CR_RANGE(chanlist[0]); /* get gain number */
3063d6de
MD
1844 scanquad |= ((gain & 0x03) << 8);
1845 outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1846 DPRINTK("%02x ", scanquad | ssh);
1847 }
1848 DPRINTK("\n ");
1849 }
1850#ifdef PCI9118_PARANOIDCHECK
242467bd
MD
1851 devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];
1852 /* for 32bit operations */
3063d6de 1853 if (useeos) {
242467bd 1854 for (i = 1; i < n_chan; i++) { /* store range list to card */
3063d6de 1855 devpriv->chanlist[(n_chan + i) ^ usedma] =
0a85b6f0 1856 (CR_CHAN(chanlist[i]) & 0xf) << rot;
3063d6de 1857 }
242467bd
MD
1858 devpriv->chanlist[(2 * n_chan) ^ usedma] =
1859 devpriv->chanlist[0 ^ usedma];
1860 /* for 32bit operations */
3063d6de
MD
1861 useeos = 2;
1862 } else {
1863 useeos = 1;
1864 }
1865#ifdef PCI9118_EXTDEBUG
1866 DPRINTK("CHL: ");
a41aec1b 1867 for (i = 0; i <= (useeos * n_chan); i++)
3063d6de 1868 DPRINTK("%04x ", devpriv->chanlist[i]);
a41aec1b 1869
3063d6de
MD
1870 DPRINTK("\n ");
1871#endif
1872#endif
242467bd
MD
1873 outl(0, dev->iobase + PCI9118_SCANMOD); /* close scan queue */
1874 /* udelay(100); important delay, or first sample will be crippled */
3063d6de
MD
1875
1876 DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
242467bd 1877 return 1; /* we can serve this with scan logic */
3063d6de
MD
1878}
1879
1880/*
1881==============================================================================
1882 calculate 8254 divisors if they are used for dual timing
1883*/
da91b269 1884static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
0a85b6f0
MT
1885 struct comedi_subdevice *s,
1886 unsigned int *tim1, unsigned int *tim2,
1887 unsigned int flags, int chans,
1888 unsigned int *div1, unsigned int *div2,
1889 char usessh, unsigned int chnsshfront)
3063d6de 1890{
0a85b6f0 1891 DPRINTK
242467bd
MD
1892 ("adl_pci9118 EDBG: BGN: pci9118_calc_divisors"
1893 "(%d,%d,.,%u,%u,%u,%d,.,.,,%u,%u)\n",
0a85b6f0 1894 mode, dev->minor, *tim1, *tim2, flags, chans, usessh, chnsshfront);
3063d6de
MD
1895 switch (mode) {
1896 case 1:
1897 case 4:
1898 if (*tim2 < this_board->ai_ns_min)
1899 *tim2 = this_board->ai_ns_min;
1900 i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, div1, div2,
0a85b6f0 1901 tim2, flags & TRIG_ROUND_NEAREST);
3063d6de
MD
1902 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u\n",
1903 devpriv->i8254_osc_base, *div1, *div2, *tim1);
1904 break;
1905 case 2:
1906 if (*tim2 < this_board->ai_ns_min)
1907 *tim2 = this_board->ai_ns_min;
1908 DPRINTK("1 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1909 *tim1, *tim2);
242467bd
MD
1910 *div1 = *tim2 / devpriv->i8254_osc_base;
1911 /* convert timer (burst) */
3063d6de
MD
1912 DPRINTK("2 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1913 *tim1, *tim2);
1914 if (*div1 < this_board->ai_pacer_min)
1915 *div1 = this_board->ai_pacer_min;
1916 DPRINTK("3 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1917 *tim1, *tim2);
242467bd 1918 *div2 = *tim1 / devpriv->i8254_osc_base; /* scan timer */
3063d6de
MD
1919 DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1920 *tim1, *tim2);
242467bd 1921 *div2 = *div2 / *div1; /* major timer is c1*c2 */
3063d6de
MD
1922 DPRINTK("5 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1923 *tim1, *tim2);
1924 if (*div2 < chans)
1925 *div2 = chans;
1926 DPRINTK("6 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1927 *tim1, *tim2);
1928
242467bd
MD
1929 *tim2 = *div1 * devpriv->i8254_osc_base;
1930 /* real convert timer */
3063d6de 1931
242467bd 1932 if (usessh & (chnsshfront == 0)) /* use BSSH signal */
3063d6de
MD
1933 if (*div2 < (chans + 2))
1934 *div2 = chans + 2;
1935
1936 DPRINTK("7 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1937 *tim1, *tim2);
1938 *tim1 = *div1 * *div2 * devpriv->i8254_osc_base;
1939 DPRINTK("OSC base=%u div1=%u div2=%u timer1=%u timer2=%u\n",
1940 devpriv->i8254_osc_base, *div1, *div2, *tim1, *tim2);
1941 break;
1942 }
1943 DPRINTK("adl_pci9118 EDBG: END: pci9118_calc_divisors(%u,%u)\n",
1944 *div1, *div2);
1945}
1946
1947/*
1948==============================================================================
1949*/
0a85b6f0
MT
1950static void start_pacer(struct comedi_device *dev, int mode,
1951 unsigned int divisor1, unsigned int divisor2)
3063d6de
MD
1952{
1953 outl(0x74, dev->iobase + PCI9118_CNTCTRL);
1954 outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
0f04c356 1955/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
5f74ea14 1956 udelay(1);
3063d6de
MD
1957
1958 if ((mode == 1) || (mode == 2) || (mode == 4)) {
1959 outl(divisor2 & 0xff, dev->iobase + PCI9118_CNT2);
1960 outl((divisor2 >> 8) & 0xff, dev->iobase + PCI9118_CNT2);
1961 outl(divisor1 & 0xff, dev->iobase + PCI9118_CNT1);
1962 outl((divisor1 >> 8) & 0xff, dev->iobase + PCI9118_CNT1);
1963 }
1964}
1965
1966/*
1967==============================================================================
1968*/
da91b269 1969static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
3063d6de
MD
1970{
1971 if (source > 3)
242467bd 1972 return -1; /* incorrect source */
3063d6de
MD
1973 devpriv->exttrg_users |= (1 << source);
1974 devpriv->IntControlReg |= Int_DTrg;
1975 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
242467bd
MD
1976 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
1977 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1978 /* allow INT in AMCC */
3063d6de
MD
1979 return 0;
1980}
1981
1982/*
1983==============================================================================
1984*/
da91b269 1985static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
3063d6de
MD
1986{
1987 if (source > 3)
242467bd 1988 return -1; /* incorrect source */
3063d6de 1989 devpriv->exttrg_users &= ~(1 << source);
242467bd 1990 if (!devpriv->exttrg_users) { /* shutdown ext trg intterrupts */
3063d6de 1991 devpriv->IntControlReg &= ~Int_DTrg;
242467bd
MD
1992 if (!devpriv->IntControlReg) /* all IRQ disabled */
1993 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) &
1994 (~0x00001f00),
1995 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1996 /* disable int in AMCC */
3063d6de
MD
1997 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1998 }
1999 return 0;
2000}
2001
2002/*
2003==============================================================================
2004*/
0a85b6f0
MT
2005static int pci9118_ai_cancel(struct comedi_device *dev,
2006 struct comedi_subdevice *s)
3063d6de
MD
2007{
2008 if (devpriv->usedma)
242467bd
MD
2009 outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) &
2010 (~EN_A2P_TRANSFERS),
2011 devpriv->iobase_a + AMCC_OP_REG_MCSR); /* stop DMA */
3063d6de 2012 pci9118_exttrg_del(dev, EXTTRG_AI);
242467bd 2013 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
3063d6de 2014 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
242467bd
MD
2015 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2016 /*
2017 * positive triggers, no S&H, no burst,
2018 * burst stop, no post trigger,
2019 * no about trigger, trigger stop
2020 */
3063d6de 2021 devpriv->AdControlReg = 0x00;
242467bd
MD
2022 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2023 /*
2024 * bipolar, S.E., use 8254, stop 8354,
2025 * internal trigger, soft trigger,
2026 * disable INT and DMA
2027 */
3063d6de
MD
2028 outl(0, dev->iobase + PCI9118_BURST);
2029 outl(1, dev->iobase + PCI9118_SCANMOD);
242467bd
MD
2030 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
2031 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
3063d6de
MD
2032
2033 devpriv->ai_do = 0;
2034 devpriv->usedma = 0;
2035
2036 devpriv->ai_act_scan = 0;
2037 devpriv->ai_act_dmapos = 0;
2038 s->async->cur_chan = 0;
2039 s->async->inttrig = NULL;
2040 devpriv->ai_buf_ptr = 0;
2041 devpriv->ai_neverending = 0;
2042 devpriv->dma_actbuf = 0;
2043
2044 if (!devpriv->IntControlReg)
242467bd
MD
2045 outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00,
2046 devpriv->iobase_a + AMCC_OP_REG_INTCSR);
2047 /* allow INT in AMCC */
3063d6de
MD
2048
2049 return 0;
2050}
2051
2052/*
2053==============================================================================
2054*/
da91b269 2055static int pci9118_reset(struct comedi_device *dev)
3063d6de
MD
2056{
2057 devpriv->IntControlReg = 0;
2058 devpriv->exttrg_users = 0;
2059 inl(dev->iobase + PCI9118_INTCTRL);
242467bd
MD
2060 outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
2061 /* disable interrupts source */
3063d6de 2062 outl(0x30, dev->iobase + PCI9118_CNTCTRL);
0f04c356 2063/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
242467bd 2064 start_pacer(dev, 0, 0, 0); /* stop 8254 counters */
3063d6de 2065 devpriv->AdControlReg = 0;
242467bd
MD
2066 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2067 /*
2068 * bipolar, S.E., use 8254,
2069 * stop 8354, internal trigger,
2070 * soft trigger,
2071 * disable INT and DMA
2072 */
3063d6de
MD
2073 outl(0, dev->iobase + PCI9118_BURST);
2074 outl(1, dev->iobase + PCI9118_SCANMOD);
242467bd 2075 outl(2, dev->iobase + PCI9118_SCANMOD); /* reset scan queue */
3063d6de 2076 devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
242467bd
MD
2077 outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
2078 /*
2079 * positive triggers, no S&H,
2080 * no burst, burst stop,
2081 * no post trigger,
2082 * no about trigger,
2083 * trigger stop
2084 */
3063d6de
MD
2085
2086 devpriv->ao_data[0] = 2047;
2087 devpriv->ao_data[1] = 2047;
242467bd
MD
2088 outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);
2089 /* reset A/D outs to 0V */
3063d6de 2090 outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
242467bd 2091 outl(0, dev->iobase + PCI9118_DO); /* reset digi outs to L */
5f74ea14 2092 udelay(10);
3063d6de 2093 inl(dev->iobase + PCI9118_AD_DATA);
242467bd
MD
2094 outl(0, dev->iobase + PCI9118_DELFIFO); /* flush FIFO */
2095 outl(0, dev->iobase + PCI9118_INTSRC); /* remove INT requests */
2096 inl(dev->iobase + PCI9118_ADSTAT); /* flush A/D status register */
2097 inl(dev->iobase + PCI9118_INTSRC); /* flush INT requests */
3063d6de 2098 devpriv->AdControlReg = 0;
242467bd
MD
2099 outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
2100 /*
2101 * bipolar, S.E., use 8254,
2102 * stop 8354, internal trigger,
2103 * soft trigger,
2104 * disable INT and DMA
2105 */
3063d6de
MD
2106
2107 devpriv->cnt0_users = 0;
2108 devpriv->exttrg_users = 0;
2109
2110 return 0;
2111}
2112
93b6e479
HS
2113static struct pci_dev *pci9118_find_pci(struct comedi_device *dev,
2114 struct comedi_devconfig *it)
2115{
2116 struct pci_dev *pcidev = NULL;
2117 int bus = it->options[0];
2118 int slot = it->options[1];
2119
2120 for_each_pci_dev(pcidev) {
2121 if (pcidev->vendor != PCI_VENDOR_ID_AMCC)
2122 continue;
2123 if (pcidev->device != this_board->device_id)
2124 continue;
2125 if (bus || slot) {
2126 /* requested particular bus/slot */
2127 if (pcidev->bus->number != bus ||
2128 PCI_SLOT(pcidev->devfn) != slot)
2129 continue;
2130 }
2131 /*
2132 * Look for device that isn't in use.
2133 * Enable PCI device and request regions.
2134 */
2135 if (comedi_pci_enable(pcidev, "adl_pci9118"))
2136 continue;
2137 printk(KERN_ERR ", b:s:f=%d:%d:%d, io=0x%4lx, 0x%4lx",
2138 pcidev->bus->number,
2139 PCI_SLOT(pcidev->devfn),
2140 PCI_FUNC(pcidev->devfn),
2141 (unsigned long)pci_resource_start(pcidev, 2),
2142 (unsigned long)pci_resource_start(pcidev, 0));
2143 return pcidev;
2144 }
2145 printk(KERN_ERR
2146 "comedi%d: no supported board found! (req. bus/slot : %d/%d)\n",
2147 dev->minor, bus, slot);
2148 return NULL;
2149}
2150
0a85b6f0
MT
2151static int pci9118_attach(struct comedi_device *dev,
2152 struct comedi_devconfig *it)
3063d6de 2153{
34c43922 2154 struct comedi_subdevice *s;
3063d6de
MD
2155 int ret, pages, i;
2156 unsigned short master;
2157 unsigned int irq;
3063d6de
MD
2158 u16 u16w;
2159
0a85b6f0 2160 printk("comedi%d: adl_pci9118: board=%s", dev->minor, this_board->name);
3063d6de 2161
beb50909 2162 if (it->options[3] & 1)
242467bd 2163 master = 0; /* user don't want use bus master */
beb50909 2164 else
3063d6de 2165 master = 1;
3063d6de 2166
c3744138
BP
2167 ret = alloc_private(dev, sizeof(struct pci9118_private));
2168 if (ret < 0) {
5f74ea14 2169 printk(" - Allocation failed!\n");
3063d6de
MD
2170 return -ENOMEM;
2171 }
2172
93b6e479
HS
2173 devpriv->pcidev = pci9118_find_pci(dev, it);
2174 if (!devpriv->pcidev)
3063d6de 2175 return -EIO;
3063d6de 2176
a41aec1b 2177 if (master)
93b6e479 2178 pci_set_master(devpriv->pcidev);
a41aec1b 2179
93b6e479
HS
2180 irq = devpriv->pcidev->irq;
2181 devpriv->iobase_a = pci_resource_start(devpriv->pcidev, 0);
2182 dev->iobase = pci_resource_start(devpriv->pcidev, 2);
3063d6de 2183
3063d6de
MD
2184 dev->board_name = this_board->name;
2185
3063d6de
MD
2186 pci9118_reset(dev);
2187
2188 if (it->options[3] & 2)
242467bd 2189 irq = 0; /* user don't want use IRQ */
3063d6de 2190 if (irq > 0) {
5f74ea14 2191 if (request_irq(irq, interrupt_pci9118, IRQF_SHARED,
3063d6de 2192 "ADLink PCI-9118", dev)) {
5f74ea14 2193 printk(", unable to allocate IRQ %d, DISABLING IT",
0a85b6f0 2194 irq);
3063d6de
MD
2195 irq = 0; /* Can't use IRQ */
2196 } else {
5f74ea14 2197 printk(", irq=%u", irq);
3063d6de
MD
2198 }
2199 } else {
5f74ea14 2200 printk(", IRQ disabled");
3063d6de
MD
2201 }
2202
2203 dev->irq = irq;
2204
242467bd 2205 if (master) { /* alloc DMA buffers */
3063d6de
MD
2206 devpriv->dma_doublebuf = 0;
2207 for (i = 0; i < 2; i++) {
c3744138
BP
2208 for (pages = 4; pages >= 0; pages--) {
2209 devpriv->dmabuf_virt[i] =
0a85b6f0
MT
2210 (short *)__get_free_pages(GFP_KERNEL,
2211 pages);
c3744138 2212 if (devpriv->dmabuf_virt[i])
3063d6de 2213 break;
c3744138 2214 }
3063d6de
MD
2215 if (devpriv->dmabuf_virt[i]) {
2216 devpriv->dmabuf_pages[i] = pages;
2217 devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
2218 devpriv->dmabuf_samples[i] =
0a85b6f0 2219 devpriv->dmabuf_size[i] >> 1;
3063d6de 2220 devpriv->dmabuf_hw[i] =
0a85b6f0
MT
2221 virt_to_bus((void *)
2222 devpriv->dmabuf_virt[i]);
3063d6de
MD
2223 }
2224 }
2225 if (!devpriv->dmabuf_virt[0]) {
5f74ea14 2226 printk(", Can't allocate DMA buffer, DMA disabled!");
3063d6de
MD
2227 master = 0;
2228 }
2229
2230 if (devpriv->dmabuf_virt[1])
2231 devpriv->dma_doublebuf = 1;
2232
2233 }
2234
c3744138
BP
2235 devpriv->master = master;
2236 if (devpriv->master)
5f74ea14 2237 printk(", bus master");
c3744138 2238 else
5f74ea14 2239 printk(", no bus master");
3063d6de
MD
2240
2241 devpriv->usemux = 0;
2242 if (it->options[2] > 0) {
2243 devpriv->usemux = it->options[2];
2244 if (devpriv->usemux > 256)
242467bd 2245 devpriv->usemux = 256; /* max 256 channels! */
3063d6de
MD
2246 if (it->options[4] > 0)
2247 if (devpriv->usemux > 128) {
242467bd
MD
2248 devpriv->usemux = 128;
2249 /* max 128 channels with softare S&H! */
3063d6de 2250 }
5f74ea14 2251 printk(", ext. mux %d channels", devpriv->usemux);
3063d6de
MD
2252 }
2253
2254 devpriv->softsshdelay = it->options[4];
242467bd
MD
2255 if (devpriv->softsshdelay < 0) {
2256 /* select sample&hold signal polarity */
3063d6de
MD
2257 devpriv->softsshdelay = -devpriv->softsshdelay;
2258 devpriv->softsshsample = 0x80;
2259 devpriv->softsshhold = 0x00;
2260 } else {
2261 devpriv->softsshsample = 0x00;
2262 devpriv->softsshhold = 0x80;
2263 }
2264
5f74ea14 2265 printk(".\n");
3063d6de
MD
2266
2267 pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
242467bd
MD
2268 pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);
2269 /* Enable parity check for parity error */
3063d6de 2270
2f0b9d08 2271 ret = comedi_alloc_subdevices(dev, 4);
8b6c5694 2272 if (ret)
3063d6de
MD
2273 return ret;
2274
2275 s = dev->subdevices + 0;
2276 dev->read_subdev = s;
2277 s->type = COMEDI_SUBD_AI;
2278 s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
a41aec1b 2279 if (devpriv->usemux)
3063d6de 2280 s->n_chan = devpriv->usemux;
a41aec1b 2281 else
3063d6de 2282 s->n_chan = this_board->n_aichan;
a41aec1b 2283
3063d6de
MD
2284 s->maxdata = this_board->ai_maxdata;
2285 s->len_chanlist = this_board->n_aichanlist;
2286 s->range_table = this_board->rangelist_ai;
2287 s->cancel = pci9118_ai_cancel;
2288 s->insn_read = pci9118_insn_read_ai;
2289 if (dev->irq) {
2290 s->subdev_flags |= SDF_CMD_READ;
2291 s->do_cmdtest = pci9118_ai_cmdtest;
2292 s->do_cmd = pci9118_ai_cmd;
2293 s->munge = pci9118_ai_munge;
2294 }
2295
2296 s = dev->subdevices + 1;
2297 s->type = COMEDI_SUBD_AO;
2298 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2299 s->n_chan = this_board->n_aochan;
2300 s->maxdata = this_board->ao_maxdata;
2301 s->len_chanlist = this_board->n_aochan;
2302 s->range_table = this_board->rangelist_ao;
2303 s->insn_write = pci9118_insn_write_ao;
2304 s->insn_read = pci9118_insn_read_ao;
2305
2306 s = dev->subdevices + 2;
2307 s->type = COMEDI_SUBD_DI;
2308 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2309 s->n_chan = 4;
2310 s->maxdata = 1;
2311 s->len_chanlist = 4;
2312 s->range_table = &range_digital;
2313 s->io_bits = 0; /* all bits input */
2314 s->insn_bits = pci9118_insn_bits_di;
2315
2316 s = dev->subdevices + 3;
2317 s->type = COMEDI_SUBD_DO;
2318 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2319 s->n_chan = 4;
2320 s->maxdata = 1;
2321 s->len_chanlist = 4;
2322 s->range_table = &range_digital;
2323 s->io_bits = 0xf; /* all bits output */
2324 s->insn_bits = pci9118_insn_bits_do;
2325
2326 devpriv->valid = 1;
242467bd
MD
2327 devpriv->i8254_osc_base = 250; /* 250ns=4MHz */
2328 devpriv->ai_maskharderr = 0x10a;
2329 /* default measure crash condition */
2330 if (it->options[5]) /* disable some requested */
3063d6de
MD
2331 devpriv->ai_maskharderr &= ~it->options[5];
2332
2333 switch (this_board->ai_maxdata) {
2334 case 0xffff:
2335 devpriv->ai16bits = 1;
2336 break;
2337 default:
2338 devpriv->ai16bits = 0;
2339 break;
2340 }
2341 return 0;
2342}
2343
484ecc95 2344static void pci9118_detach(struct comedi_device *dev)
3063d6de
MD
2345{
2346 if (dev->private) {
2347 if (devpriv->valid)
2348 pci9118_reset(dev);
2349 if (dev->irq)
5f74ea14 2350 free_irq(dev->irq, dev);
3063d6de 2351 if (devpriv->pcidev) {
a41aec1b 2352 if (dev->iobase)
3063d6de 2353 comedi_pci_disable(devpriv->pcidev);
a41aec1b 2354
3063d6de
MD
2355 pci_dev_put(devpriv->pcidev);
2356 }
2357 if (devpriv->dmabuf_virt[0])
2358 free_pages((unsigned long)devpriv->dmabuf_virt[0],
0a85b6f0 2359 devpriv->dmabuf_pages[0]);
3063d6de
MD
2360 if (devpriv->dmabuf_virt[1])
2361 free_pages((unsigned long)devpriv->dmabuf_virt[1],
0a85b6f0 2362 devpriv->dmabuf_pages[1]);
3063d6de 2363 }
3063d6de
MD
2364}
2365
618fc38f
HS
2366static const struct boardtype boardtypes[] = {
2367 {
2368 .name = "pci9118dg",
2369 .vendor_id = PCI_VENDOR_ID_AMCC,
2370 .device_id = 0x80d9,
2371 .iorange_amcc = AMCC_OP_REG_SIZE,
2372 .iorange_9118 = IORANGE_9118,
2373 .n_aichan = 16,
2374 .n_aichand = 8,
2375 .mux_aichan = 256,
2376 .n_aichanlist = PCI9118_CHANLEN,
2377 .n_aochan = 2,
2378 .ai_maxdata = 0x0fff,
2379 .ao_maxdata = 0x0fff,
2380 .rangelist_ai = &range_pci9118dg_hr,
2381 .rangelist_ao = &range_bipolar10,
2382 .ai_ns_min = 3000,
2383 .ai_pacer_min = 12,
2384 .half_fifo_size = 512,
2385 }, {
2386 .name = "pci9118hg",
2387 .vendor_id = PCI_VENDOR_ID_AMCC,
2388 .device_id = 0x80d9,
2389 .iorange_amcc = AMCC_OP_REG_SIZE,
2390 .iorange_9118 = IORANGE_9118,
2391 .n_aichan = 16,
2392 .n_aichand = 8,
2393 .mux_aichan = 256,
2394 .n_aichanlist = PCI9118_CHANLEN,
2395 .n_aochan = 2,
2396 .ai_maxdata = 0x0fff,
2397 .ao_maxdata = 0x0fff,
2398 .rangelist_ai = &range_pci9118hg,
2399 .rangelist_ao = &range_bipolar10,
2400 .ai_ns_min = 3000,
2401 .ai_pacer_min = 12,
2402 .half_fifo_size = 512,
2403 }, {
2404 .name = "pci9118hr",
2405 .vendor_id = PCI_VENDOR_ID_AMCC,
2406 .device_id = 0x80d9,
2407 .iorange_amcc = AMCC_OP_REG_SIZE,
2408 .iorange_9118 = IORANGE_9118,
2409 .n_aichan = 16,
2410 .n_aichand = 8,
2411 .mux_aichan = 256,
2412 .n_aichanlist = PCI9118_CHANLEN,
2413 .n_aochan = 2,
2414 .ai_maxdata = 0xffff,
2415 .ao_maxdata = 0x0fff,
2416 .rangelist_ai = &range_pci9118dg_hr,
2417 .rangelist_ao = &range_bipolar10,
2418 .ai_ns_min = 10000,
2419 .ai_pacer_min = 40,
2420 .half_fifo_size = 512,
2421 },
2422};
2423
2424static struct comedi_driver adl_pci9118_driver = {
2425 .driver_name = "adl_pci9118",
2426 .module = THIS_MODULE,
2427 .attach = pci9118_attach,
2428 .detach = pci9118_detach,
2429 .num_names = ARRAY_SIZE(boardtypes),
2430 .board_name = &boardtypes[0].name,
2431 .offset = sizeof(struct boardtype),
2432};
2433
2434static int __devinit adl_pci9118_pci_probe(struct pci_dev *dev,
2435 const struct pci_device_id *ent)
2436{
2437 return comedi_pci_auto_config(dev, &adl_pci9118_driver);
2438}
2439
2440static void __devexit adl_pci9118_pci_remove(struct pci_dev *dev)
2441{
2442 comedi_pci_auto_unconfig(dev);
2443}
2444
2445static DEFINE_PCI_DEVICE_TABLE(adl_pci9118_pci_table) = {
2446 { PCI_DEVICE(PCI_VENDOR_ID_AMCC, 0x80d9) },
2447 { 0 }
2448};
2449MODULE_DEVICE_TABLE(pci, adl_pci9118_pci_table);
2450
2451static struct pci_driver adl_pci9118_pci_driver = {
2452 .name = "adl_pci9118",
2453 .id_table = adl_pci9118_pci_table,
2454 .probe = adl_pci9118_pci_probe,
2455 .remove = __devexit_p(adl_pci9118_pci_remove),
2456};
2457module_comedi_pci_driver(adl_pci9118_driver, adl_pci9118_pci_driver);
90f703d3
AT
2458
2459MODULE_AUTHOR("Comedi http://www.comedi.org");
2460MODULE_DESCRIPTION("Comedi low-level driver");
2461MODULE_LICENSE("GPL");