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