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