adl_pci9118.c revision da91b2692e0939b307f9047192d2b9fe07793e7a
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#include <linux/interrupt.h>
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
111/* bits from A/D control register (PCI9118_ADCNTRL) */
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
121/* bits from A/D function register (PCI9118_ADFUNC) */
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
131/* bits from A/D status register (PCI9118_ADSTAT) */
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
142/* bits for interrupt reason and control (PCI9118_INTSRC, PCI9118_INTCTRL) */
143/* 1=interrupt occur, enable source,  0=interrupt not occur, disable source */
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
156static const struct comedi_lrange range_pci9118dg_hr = { 8, {
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
168static const struct comedi_lrange range_pci9118hg = { 8, {
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
182static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it);
183static int pci9118_detach(struct comedi_device *dev);
184
185struct boardtype {
186	const char *name;	/*  board name */
187	int vendor_id;		/*  PCI vendor a device ID of card */
188	int device_id;
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 */
203
204};
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
213static const struct boardtype boardtypes[] = {
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
231#define n_boardtypes (sizeof(boardtypes)/sizeof(struct boardtype))
232
233static struct comedi_driver driver_pci9118 = {
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,
240      offset:sizeof(struct boardtype),
241};
242
243COMEDI_PCI_INITCLEANUP(driver_pci9118, pci9118_pci_table);
244
245struct pci9118_private {
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! */
250#ifdef PCI9118_PARANOIDCHECK
251	unsigned short chanlist[PCI9118_CHANLEN + 1];	/*  list of scaned channel */
252	unsigned char chanlistlen;	/*  number of scanlist */
253#endif
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 */
270	unsigned int ai_timer1;
271	unsigned int ai_timer2;
272	unsigned int ai_flags;
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 */
275	unsigned int ai_data_len;
276	short *ai_data;
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 */
286	unsigned int dmabuf_panic_size[2];
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 */
303};
304
305#define devpriv ((struct pci9118_private *)dev->private)
306#define this_board ((struct boardtype *)dev->board_ptr)
307
308/*
309==============================================================================
310*/
311
312static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
313	int n_chan, unsigned int *chanlist, int frontadd, int backadd);
314static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
315	int n_chan, unsigned int *chanlist, int rot, int frontadd, int backadd,
316	int usedma, char eoshandle);
317static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
318	unsigned int divisor2);
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);
322static int pci9118_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
323static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
324	struct comedi_subdevice *s, unsigned int *tim1, unsigned int *tim2,
325	unsigned int flags, int chans, unsigned int *div1, unsigned int *div2,
326	char usessh, unsigned int chnsshfront);
327
328/*
329==============================================================================
330*/
331static int pci9118_insn_read_ai(struct comedi_device *dev, struct comedi_subdevice *s,
332	struct comedi_insn *insn, unsigned int *data)
333{
334
335	int n, timeout;
336
337	devpriv->AdControlReg = AdControl_Int & 0xff;
338	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
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 */
340
341	if (!setup_channel_list(dev, s, 1, &insn->chanspec, 0, 0, 0, 0, 0))
342		return -EINVAL;
343
344	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
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;
358		outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
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
373	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
374	return n;
375
376}
377
378/*
379==============================================================================
380*/
381static int pci9118_insn_write_ao(struct comedi_device *dev, struct comedi_subdevice *s,
382	struct comedi_insn *insn, unsigned int *data)
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*/
404static int pci9118_insn_read_ao(struct comedi_device *dev, struct comedi_subdevice *s,
405	struct comedi_insn *insn, unsigned int *data)
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*/
419static int pci9118_insn_bits_di(struct comedi_device *dev, struct comedi_subdevice *s,
420	struct comedi_insn *insn, unsigned int *data)
421{
422	data[1] = inl(dev->iobase + PCI9118_DI) & 0xf;
423
424	return 2;
425}
426
427/*
428==============================================================================
429*/
430static int pci9118_insn_bits_do(struct comedi_device *dev, struct comedi_subdevice *s,
431	struct comedi_insn *insn, unsigned int *data)
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*/
446static void interrupt_pci9118_ai_mode4_switch(struct comedi_device *dev)
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
460static unsigned int defragment_dma_buffer(struct comedi_device *dev,
461	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
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*/
484static unsigned int move_block_from_dma(struct comedi_device *dev,
485	struct comedi_subdevice *s, short *dma_buffer, unsigned int num_samples)
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,
496		num_samples * sizeof(short));
497	if (num_bytes < num_samples * sizeof(short))
498		return -1;
499	return 0;
500}
501
502/*
503==============================================================================
504*/
505static char pci9118_decode_error_status(struct comedi_device *dev,
506	struct comedi_subdevice *s, unsigned char m)
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
535static void pci9118_ai_munge(struct comedi_device *dev, struct comedi_subdevice *s,
536	void *data, unsigned int num_bytes, unsigned int start_chan_index)
537{
538	unsigned int i, num_samples = num_bytes / sizeof(short);
539	short *array = data;
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*/
555static void interrupt_pci9118_ai_onesample(struct comedi_device *dev,
556	struct comedi_subdevice *s, unsigned short int_adstat, unsigned int int_amcc,
557	unsigned short int_daq)
558{
559	register short sampl;
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) {
571		if ((sampl & 0x000f) != devpriv->chanlist[s->async->cur_chan]) {	/*  data dropout! */
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*/
602static void interrupt_pci9118_ai_dma(struct comedi_device *dev, struct comedi_subdevice *s,
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)
625/* if (int_adstat & 0x106) */
626		if (pci9118_decode_error_status(dev, s, int_adstat))
627			return;
628
629	samplesinbuf = devpriv->dmabuf_use_size[devpriv->dma_actbuf] >> 1;	/*  number of received real samples */
630/* DPRINTK("dma_actbuf=%d\n",devpriv->dma_actbuf); */
631
632	if (devpriv->dma_doublebuf) {	/*  switch DMA buffers if is used double buffering */
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) {
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); */
647		sampls = m;
648		move_block_from_dma(dev, s,
649			devpriv->dmabuf_virt[devpriv->dma_actbuf],
650			samplesinbuf);
651		m = m - sampls;	/*  m= how many samples was transfered */
652	}
653/* DPRINTK("YYY\n"); */
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
661	if (devpriv->dma_doublebuf) {	/*  switch dma buffers */
662		devpriv->dma_actbuf = 1 - devpriv->dma_actbuf;
663	} else {		/*  restart DMA if is not used double buffering */
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*/
678static irqreturn_t interrupt_pci9118(int irq, void *d)
679{
680	struct comedi_device *dev = d;
681	unsigned int int_daq = 0, int_amcc, int_adstat;
682
683	if (!dev->attached)
684		return IRQ_NONE;	/*  not fully initialized */
685
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 */
688
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); */
690
691	if ((!int_daq) && (!(int_amcc & ANY_S593X_INT)))
692		return IRQ_NONE;	/*  interrupt from other source */
693
694	outl(int_amcc | 0x00ff0000, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  shutdown IRQ reasons in AMCC */
695
696	int_adstat = inw(dev->iobase + PCI9118_ADSTAT) & 0x1ff;	/*  get STATUS register */
697
698	if (devpriv->ai_do) {
699		if (devpriv->ai12_startstop)
700			if ((int_adstat & AdStatus_DTH) && (int_daq & Int_DTrg)) {	/*  start stop of measure */
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))
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 */
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;
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 */
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*/
731static int pci9118_ai_inttrig(struct comedi_device *dev, struct comedi_subdevice *s,
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*/
755static int pci9118_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
756	struct comedi_cmd *cmd)
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;
953/* rt_printk("S1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
954		i8253_cascade_ns_to_timer(devpriv->i8254_osc_base, &divisor1,
955			&divisor2, &cmd->scan_begin_arg,
956			cmd->flags & TRIG_ROUND_MASK);
957/* rt_printk("S2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
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);
969/* rt_printk("s1 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
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);
983/* rt_printk("s2 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
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;
992/* rt_printk("s3 timer1=%u timer2=%u\n",cmd->scan_begin_arg,cmd->convert_arg); */
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))
1005			return 5;	/*  incorrect channels list */
1006
1007	return 0;
1008}
1009
1010/*
1011==============================================================================
1012*/
1013static int Compute_and_setup_dma(struct comedi_device *dev)
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);
1022	/*  isn't output buff smaller that our DMA buff? */
1023	if (dmalen0 > (devpriv->ai_data_len)) {
1024		dmalen0 = devpriv->ai_data_len & ~3L;	/*  allign to 32bit down */
1025	}
1026	if (dmalen1 > (devpriv->ai_data_len)) {
1027		dmalen1 = devpriv->ai_data_len & ~3L;	/*  allign to 32bit down */
1028	}
1029	DPRINTK("2 dmalen0=%d dmalen1=%d \n", dmalen0, dmalen1);
1030
1031	/*  we want wake up every scan? */
1032	if (devpriv->ai_flags & TRIG_WAKE_EOS) {
1033		if (dmalen0 < (devpriv->ai_n_realscanlen << 1)) {
1034			/*  uff, too short DMA buffer, disable EOS support! */
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 {
1041			/*  short first DMA buffer to one scan */
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)) {
1056			/*  uff, too short DMA buffer, disable EOS support! */
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 {
1063			/*  short second DMA buffer to one scan */
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);
1078	/*  transfer without TRIG_WAKE_EOS */
1079	if (!(devpriv->ai_flags & TRIG_WAKE_EOS)) {
1080		/*  if it's possible then allign DMA buffers to length of scan */
1081		i = dmalen0;
1082		dmalen0 =
1083			(dmalen0 / (devpriv->ai_n_realscanlen << 1)) *
1084			(devpriv->ai_n_realscanlen << 1);
1085		dmalen0 &= ~3L;
1086		if (!dmalen0)
1087			dmalen0 = i;	/*  uff. very long scan? */
1088		i = dmalen1;
1089		dmalen1 =
1090			(dmalen1 / (devpriv->ai_n_realscanlen << 1)) *
1091			(devpriv->ai_n_realscanlen << 1);
1092		dmalen1 &= ~3L;
1093		if (!dmalen1)
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 */
1096		if (!devpriv->ai_neverending) {
1097			/*  fits whole measure into one DMA buffer? */
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;
1108			} else {	/*  fits whole measure into two DMA buffer? */
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
1125	/*  these DMA buffer size we'll be used */
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 +
1135			1) * devpriv->ai_n_scanlen * sizeof(short);
1136		devpriv->dmabuf_panic_size[1] =
1137			(this_board->half_fifo_size / devpriv->ai_n_scanlen +
1138			1) * devpriv->ai_n_scanlen * sizeof(short);
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
1147	outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
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);
1150	/*  init DMA transfer */
1151	outl(0x00000000 | AINT_WRITE_COMPL,
1152		devpriv->iobase_a + AMCC_OP_REG_INTCSR);
1153/* outl(0x02000000|AINT_WRITE_COMPL, devpriv->iobase_a+AMCC_OP_REG_INTCSR); */
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);
1158	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | EN_A2P_TRANSFERS, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow bus mastering */
1159
1160	DPRINTK("adl_pci9118 EDBG: END: Compute_and_setup_dma()\n");
1161	return 0;
1162}
1163
1164/*
1165==============================================================================
1166*/
1167static int pci9118_ai_docmd_sampl(struct comedi_device *dev, struct comedi_subdevice *s)
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
1190	devpriv->int_ai_func = interrupt_pci9118_ai_onesample;	/* transfer function */
1191
1192	if (devpriv->ai12_startstop)
1193		pci9118_exttrg_add(dev, EXTTRG_AI);	/*  activate EXT trigger */
1194
1195	if ((devpriv->ai_do == 1) || (devpriv->ai_do == 2))
1196		devpriv->IntControlReg |= Int_Timer;
1197
1198	devpriv->AdControlReg |= AdControl_Int;
1199
1200	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
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*/
1220static int pci9118_ai_docmd_dma(struct comedi_device *dev, struct comedi_subdevice *s)
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) {
1265		pci9118_exttrg_add(dev, EXTTRG_AI);	/*  activate EXT trigger */
1266	}
1267
1268	devpriv->int_ai_func = interrupt_pci9118_ai_dma;	/* transfer function */
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*/
1291static int pci9118_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1292{
1293	struct comedi_cmd *cmd = &s->async->cmd;
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
1311	/*  prepare for start/stop conditions */
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
1338	/*  use sample&hold signal? */
1339	if (cmd->convert_src == TRIG_NOW) {
1340		devpriv->usessh = 1;
1341	}			/*  yes */
1342	else {
1343		devpriv->usessh = 0;
1344	}			/*  no */
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
1350	/*  use additional sample at end of every scan to satisty DMA 32 bit transfer? */
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) {
1362				devpriv->usedma = 0;	/*  use INT transfer if scanlist have only one channel */
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) {
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 */
1372				devpriv->ai_add_back = 1;
1373			}
1374		}
1375	} else {		/*  interrupt transfer don't need any correction */
1376		devpriv->usedma = 0;
1377	}
1378
1379	/*  we need software S&H signal? It add  two samples before every scan as minimum */
1380	if (devpriv->usessh && devpriv->softsshdelay) {
1381		devpriv->ai_add_front = 2;
1382		if ((devpriv->usedma == 1) && (devpriv->ai_add_back == 1)) {	/*  move it to front */
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++;
1391		if (addchans > (devpriv->ai_add_front - 1)) {	/*  uff, still short :-( */
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)
1397					devpriv->ai_add_front++;	/*  round up to 32 bit */
1398		}
1399	}			/*  well, we now know what must be all added */
1400
1401	devpriv->ai_n_realscanlen =	/*  what we must take from card in real to have ai_n_scanlen on output? */
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
1412	/*  check and setup channel list */
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
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 */
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
1439	if ((cmd->scan_begin_src == TRIG_TIMER) && ((cmd->convert_src == TRIG_TIMER) || (cmd->convert_src == TRIG_NOW))) {	/*  double timed action */
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
1461	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
1462
1463	devpriv->AdControlReg = 0;	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable DMA */
1464	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);
1465	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;	/*  positive triggers, no S&H, no burst, burst stop, no post trigger, no about trigger, trigger stop */
1466	outl(devpriv->AdFunctionReg, dev->iobase + PCI9118_ADFUNC);
1467	comedi_udelay(1);
1468	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
1469	inl(dev->iobase + PCI9118_ADSTAT);	/*  flush A/D and INT status register */
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*/
1490static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
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)
1509		differencial = 1;	/*  all input must be diff */
1510	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1511		bipolar = 1;	/*  all input must be bipolar */
1512	if (n_chan > 1)
1513		for (i = 1; i < n_chan; i++) {	/*  check S.E/diff */
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*/
1541static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
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)
1556		differencial = 1;	/*  all input must be diff */
1557	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1558		bipolar = 1;	/*  all input must be bipolar */
1559
1560	/*  All is ok, so we can setup channel/range list */
1561
1562	if (!bipolar) {
1563		devpriv->AdControlReg |= AdControl_UniP;	/*  set unibipolar */
1564	} else {
1565		devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);	/*  enable bipolar */
1566	}
1567
1568	if (differencial) {
1569		devpriv->AdControlReg |= AdControl_Diff;	/*  enable diff inputs */
1570	} else {
1571		devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);	/*  set single ended inputs */
1572	}
1573
1574	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  setup mode */
1575
1576	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  gods know why this sequence! */
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
1586	if (frontadd) {		/*  insert channels for S&H */
1587		ssh = devpriv->softsshsample;
1588		DPRINTK("FA: %04x: ", ssh);
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 */
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);
1601	for (i = 0; i < n_chan; i++) {	/*  store range list to card */
1602		scanquad = CR_CHAN(chanlist[i]);	/*  get channel number; */
1603#ifdef PCI9118_PARANOIDCHECK
1604		devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1605#endif
1606		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
1607		scanquad |= ((gain & 0x03) << 8);
1608		outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1609		DPRINTK("%02x ", scanquad | ssh);
1610	}
1611	DPRINTK("\n ");
1612
1613	if (backadd) {		/*  insert channels for fit onto 32bit DMA */
1614		DPRINTK("BA: %04x: ", ssh);
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 */
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
1625	devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
1626	if (useeos) {
1627		for (i = 1; i < n_chan; i++) {	/*  store range list to card */
1628			devpriv->chanlist[(n_chan + i) ^ usedma] =
1629				(CR_CHAN(chanlist[i]) & 0xf) << rot;
1630		}
1631		devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
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
1644	outl(0, dev->iobase + PCI9118_SCANMOD);	/*  close scan queue */
1645/* comedi_udelay(100);                               important delay, or first sample will be cripled */
1646
1647	DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1648	return 1;		/*  we can serve this with scan logic */
1649}
1650
1651/*
1652==============================================================================
1653  calculate 8254 divisors if they are used for dual timing
1654*/
1655static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1656	struct comedi_subdevice *s, unsigned int *tim1, unsigned int *tim2,
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);
1676		*div1 = *tim2 / devpriv->i8254_osc_base;	/*  convert timer (burst) */
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);
1683		*div2 = *tim1 / devpriv->i8254_osc_base;	/*  scan timer */
1684		DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1685			*tim1, *tim2);
1686		*div2 = *div2 / *div1;	/*  major timer is c1*c2 */
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
1694		*tim2 = *div1 * devpriv->i8254_osc_base;	/*  real convert timer */
1695
1696		if (usessh & (chnsshfront == 0))	/*  use BSSH signal */
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*/
1714static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
1715	unsigned int divisor2)
1716{
1717	outl(0x74, dev->iobase + PCI9118_CNTCTRL);
1718	outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
1719/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
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*/
1733static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
1734{
1735	if (source > 3)
1736		return -1;	/*  incorrect source */
1737	devpriv->exttrg_users |= (1 << source);
1738	devpriv->IntControlReg |= Int_DTrg;
1739	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1740	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
1741	return 0;
1742}
1743
1744/*
1745==============================================================================
1746*/
1747static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
1748{
1749	if (source > 3)
1750		return -1;	/*  incorrect source */
1751	devpriv->exttrg_users &= ~(1 << source);
1752	if (!devpriv->exttrg_users) {	/*  shutdown ext trg intterrupts */
1753		devpriv->IntControlReg &= ~Int_DTrg;
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 */
1756		outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1757	}
1758	return 0;
1759}
1760
1761/*
1762==============================================================================
1763*/
1764static int pci9118_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1765{
1766	if (devpriv->usedma)
1767		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
1768	pci9118_exttrg_del(dev, EXTTRG_AI);
1769	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
1770	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
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 */
1772	devpriv->AdControlReg = 0x00;
1773	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1774	outl(0, dev->iobase + PCI9118_BURST);
1775	outl(1, dev->iobase + PCI9118_SCANMOD);
1776	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
1777	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
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)
1791		outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
1792
1793	return 0;
1794}
1795
1796/*
1797==============================================================================
1798*/
1799static int pci9118_reset(struct comedi_device *dev)
1800{
1801	devpriv->IntControlReg = 0;
1802	devpriv->exttrg_users = 0;
1803	inl(dev->iobase + PCI9118_INTCTRL);
1804	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);	/*  disable interrupts source */
1805	outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1806/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1807	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
1808	devpriv->AdControlReg = 0;
1809	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1810	outl(0, dev->iobase + PCI9118_BURST);
1811	outl(1, dev->iobase + PCI9118_SCANMOD);
1812	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
1813	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
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 */
1815
1816	devpriv->ao_data[0] = 2047;
1817	devpriv->ao_data[1] = 2047;
1818	outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);	/*  reset A/D outs to 0V */
1819	outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1820	outl(0, dev->iobase + PCI9118_DO);	/*  reset digi outs to L */
1821	comedi_udelay(10);
1822	inl(dev->iobase + PCI9118_AD_DATA);
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 */
1827	devpriv->AdControlReg = 0;
1828	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1829
1830	devpriv->cnt0_users = 0;
1831	devpriv->exttrg_users = 0;
1832
1833	return 0;
1834}
1835
1836/*
1837==============================================================================
1838*/
1839static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1840{
1841	struct comedi_subdevice *s;
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) {
1858		master = 0;	/*  user don't want use bus master */
1859	} else {
1860		master = 1;
1861	}
1862
1863	if ((ret = alloc_private(dev, sizeof(struct pci9118_private))) < 0) {
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)
1924		irq = 0;	/*  user don't want use IRQ */
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
1940	if (master) {		/*  alloc DMA buffers */
1941		devpriv->dma_doublebuf = 0;
1942		for (i = 0; i < 2; i++) {
1943			for (pages = 4; pages >= 0; pages--)
1944				if ((devpriv->dmabuf_virt[i] = (short *)
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)
1978			devpriv->usemux = 256;	/*  max 256 channels! */
1979		if (it->options[4] > 0)
1980			if (devpriv->usemux > 128) {
1981				devpriv->usemux = 128;	/*  max 128 channels with softare S&H! */
1982			}
1983		rt_printk(", ext. mux %d channels", devpriv->usemux);
1984	}
1985
1986	devpriv->softsshdelay = it->options[4];
1987	if (devpriv->softsshdelay < 0) {	/*  select sample&hold signal polarity */
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);
1999	pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);	/*  Enable parity check for parity error */
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;
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 */
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*/
2075static int pci9118_detach(struct comedi_device *dev)
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*/
2102