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