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