adl_pci9118.c revision 68c3dbff9fc9f25872408d0e95980d41733d48d0
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	DPRINTK("adl_pci9118 EDBG: END: pci9118_ai_cmd()\n");
1483	return ret;
1484}
1485
1486/*
1487==============================================================================
1488*/
1489static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
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)
1508		differencial = 1;	/*  all input must be diff */
1509	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1510		bipolar = 1;	/*  all input must be bipolar */
1511	if (n_chan > 1)
1512		for (i = 1; i < n_chan; i++) {	/*  check S.E/diff */
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*/
1540static int setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
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)
1555		differencial = 1;	/*  all input must be diff */
1556	if (CR_RANGE(chanlist[0]) < PCI9118_BIPOLAR_RANGES)
1557		bipolar = 1;	/*  all input must be bipolar */
1558
1559	/*  All is ok, so we can setup channel/range list */
1560
1561	if (!bipolar) {
1562		devpriv->AdControlReg |= AdControl_UniP;	/*  set unibipolar */
1563	} else {
1564		devpriv->AdControlReg &= ((~AdControl_UniP) & 0xff);	/*  enable bipolar */
1565	}
1566
1567	if (differencial) {
1568		devpriv->AdControlReg |= AdControl_Diff;	/*  enable diff inputs */
1569	} else {
1570		devpriv->AdControlReg &= ((~AdControl_Diff) & 0xff);	/*  set single ended inputs */
1571	}
1572
1573	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  setup mode */
1574
1575	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  gods know why this sequence! */
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
1585	if (frontadd) {		/*  insert channels for S&H */
1586		ssh = devpriv->softsshsample;
1587		DPRINTK("FA: %04x: ", ssh);
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 */
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);
1600	for (i = 0; i < n_chan; i++) {	/*  store range list to card */
1601		scanquad = CR_CHAN(chanlist[i]);	/*  get channel number; */
1602#ifdef PCI9118_PARANOIDCHECK
1603		devpriv->chanlist[i ^ usedma] = (scanquad & 0xf) << rot;
1604#endif
1605		gain = CR_RANGE(chanlist[i]);	/*  get gain number */
1606		scanquad |= ((gain & 0x03) << 8);
1607		outl(scanquad | ssh, dev->iobase + PCI9118_GAIN);
1608		DPRINTK("%02x ", scanquad | ssh);
1609	}
1610	DPRINTK("\n ");
1611
1612	if (backadd) {		/*  insert channels for fit onto 32bit DMA */
1613		DPRINTK("BA: %04x: ", ssh);
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 */
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
1624	devpriv->chanlist[n_chan ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
1625	if (useeos) {
1626		for (i = 1; i < n_chan; i++) {	/*  store range list to card */
1627			devpriv->chanlist[(n_chan + i) ^ usedma] =
1628				(CR_CHAN(chanlist[i]) & 0xf) << rot;
1629		}
1630		devpriv->chanlist[(2 * n_chan) ^ usedma] = devpriv->chanlist[0 ^ usedma];	/*  for 32bit oerations */
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
1643	outl(0, dev->iobase + PCI9118_SCANMOD);	/*  close scan queue */
1644/* comedi_udelay(100);                               important delay, or first sample will be cripled */
1645
1646	DPRINTK("adl_pci9118 EDBG: END: setup_channel_list()\n");
1647	return 1;		/*  we can serve this with scan logic */
1648}
1649
1650/*
1651==============================================================================
1652  calculate 8254 divisors if they are used for dual timing
1653*/
1654static void pci9118_calc_divisors(char mode, struct comedi_device *dev,
1655	struct comedi_subdevice *s, unsigned int *tim1, unsigned int *tim2,
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);
1675		*div1 = *tim2 / devpriv->i8254_osc_base;	/*  convert timer (burst) */
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);
1682		*div2 = *tim1 / devpriv->i8254_osc_base;	/*  scan timer */
1683		DPRINTK("4 div1=%u div2=%u timer1=%u timer2=%u\n", *div1, *div2,
1684			*tim1, *tim2);
1685		*div2 = *div2 / *div1;	/*  major timer is c1*c2 */
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
1693		*tim2 = *div1 * devpriv->i8254_osc_base;	/*  real convert timer */
1694
1695		if (usessh & (chnsshfront == 0))	/*  use BSSH signal */
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*/
1713static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
1714	unsigned int divisor2)
1715{
1716	outl(0x74, dev->iobase + PCI9118_CNTCTRL);
1717	outl(0xb4, dev->iobase + PCI9118_CNTCTRL);
1718/* outl(0x30, dev->iobase + PCI9118_CNTCTRL); */
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*/
1732static int pci9118_exttrg_add(struct comedi_device *dev, unsigned char source)
1733{
1734	if (source > 3)
1735		return -1;	/*  incorrect source */
1736	devpriv->exttrg_users |= (1 << source);
1737	devpriv->IntControlReg |= Int_DTrg;
1738	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1739	outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
1740	return 0;
1741}
1742
1743/*
1744==============================================================================
1745*/
1746static int pci9118_exttrg_del(struct comedi_device *dev, unsigned char source)
1747{
1748	if (source > 3)
1749		return -1;	/*  incorrect source */
1750	devpriv->exttrg_users &= ~(1 << source);
1751	if (!devpriv->exttrg_users) {	/*  shutdown ext trg intterrupts */
1752		devpriv->IntControlReg &= ~Int_DTrg;
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 */
1755		outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);
1756	}
1757	return 0;
1758}
1759
1760/*
1761==============================================================================
1762*/
1763static int pci9118_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1764{
1765	if (devpriv->usedma)
1766		outl(inl(devpriv->iobase_a + AMCC_OP_REG_MCSR) & (~EN_A2P_TRANSFERS), devpriv->iobase_a + AMCC_OP_REG_MCSR);	/*  stop DMA */
1767	pci9118_exttrg_del(dev, EXTTRG_AI);
1768	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
1769	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
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 */
1771	devpriv->AdControlReg = 0x00;
1772	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1773	outl(0, dev->iobase + PCI9118_BURST);
1774	outl(1, dev->iobase + PCI9118_SCANMOD);
1775	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
1776	outl(0, dev->iobase + PCI9118_DELFIFO);	/*  flush FIFO */
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)
1790		outl(inl(devpriv->iobase_a + AMCC_OP_REG_INTCSR) | 0x1f00, devpriv->iobase_a + AMCC_OP_REG_INTCSR);	/*  allow INT in AMCC */
1791
1792	return 0;
1793}
1794
1795/*
1796==============================================================================
1797*/
1798static int pci9118_reset(struct comedi_device *dev)
1799{
1800	devpriv->IntControlReg = 0;
1801	devpriv->exttrg_users = 0;
1802	inl(dev->iobase + PCI9118_INTCTRL);
1803	outl(devpriv->IntControlReg, dev->iobase + PCI9118_INTCTRL);	/*  disable interrupts source */
1804	outl(0x30, dev->iobase + PCI9118_CNTCTRL);
1805/* outl(0xb4, dev->iobase + PCI9118_CNTCTRL); */
1806	start_pacer(dev, 0, 0, 0);	/*  stop 8254 counters */
1807	devpriv->AdControlReg = 0;
1808	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1809	outl(0, dev->iobase + PCI9118_BURST);
1810	outl(1, dev->iobase + PCI9118_SCANMOD);
1811	outl(2, dev->iobase + PCI9118_SCANMOD);	/*  reset scan queue */
1812	devpriv->AdFunctionReg = AdFunction_PDTrg | AdFunction_PETrg;
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 */
1814
1815	devpriv->ao_data[0] = 2047;
1816	devpriv->ao_data[1] = 2047;
1817	outl(devpriv->ao_data[0], dev->iobase + PCI9118_DA1);	/*  reset A/D outs to 0V */
1818	outl(devpriv->ao_data[1], dev->iobase + PCI9118_DA2);
1819	outl(0, dev->iobase + PCI9118_DO);	/*  reset digi outs to L */
1820	comedi_udelay(10);
1821	inl(dev->iobase + PCI9118_AD_DATA);
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 */
1826	devpriv->AdControlReg = 0;
1827	outl(devpriv->AdControlReg, dev->iobase + PCI9118_ADCNTRL);	/*  bipolar, S.E., use 8254, stop 8354, internal trigger, soft trigger, disable INT and DMA */
1828
1829	devpriv->cnt0_users = 0;
1830	devpriv->exttrg_users = 0;
1831
1832	return 0;
1833}
1834
1835/*
1836==============================================================================
1837*/
1838static int pci9118_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1839{
1840	struct comedi_subdevice *s;
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) {
1857		master = 0;	/*  user don't want use bus master */
1858	} else {
1859		master = 1;
1860	}
1861
1862	ret = alloc_private(dev, sizeof(struct pci9118_private));
1863	if (ret < 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				devpriv->dmabuf_virt[i] =
1945					(short *) __get_free_pages(GFP_KERNEL,
1946								   pages);
1947				if (devpriv->dmabuf_virt[i])
1948					break;
1949			}
1950			if (devpriv->dmabuf_virt[i]) {
1951				devpriv->dmabuf_pages[i] = pages;
1952				devpriv->dmabuf_size[i] = PAGE_SIZE * pages;
1953				devpriv->dmabuf_samples[i] =
1954					devpriv->dmabuf_size[i] >> 1;
1955				devpriv->dmabuf_hw[i] =
1956					virt_to_bus((void *)devpriv->
1957					dmabuf_virt[i]);
1958			}
1959		}
1960		if (!devpriv->dmabuf_virt[0]) {
1961			rt_printk(", Can't allocate DMA buffer, DMA disabled!");
1962			master = 0;
1963		}
1964
1965		if (devpriv->dmabuf_virt[1])
1966			devpriv->dma_doublebuf = 1;
1967
1968	}
1969
1970	devpriv->master = master;
1971	if (devpriv->master)
1972		rt_printk(", bus master");
1973	else
1974		rt_printk(", no bus master");
1975
1976	devpriv->usemux = 0;
1977	if (it->options[2] > 0) {
1978		devpriv->usemux = it->options[2];
1979		if (devpriv->usemux > 256)
1980			devpriv->usemux = 256;	/*  max 256 channels! */
1981		if (it->options[4] > 0)
1982			if (devpriv->usemux > 128) {
1983				devpriv->usemux = 128;	/*  max 128 channels with softare S&H! */
1984			}
1985		rt_printk(", ext. mux %d channels", devpriv->usemux);
1986	}
1987
1988	devpriv->softsshdelay = it->options[4];
1989	if (devpriv->softsshdelay < 0) {	/*  select sample&hold signal polarity */
1990		devpriv->softsshdelay = -devpriv->softsshdelay;
1991		devpriv->softsshsample = 0x80;
1992		devpriv->softsshhold = 0x00;
1993	} else {
1994		devpriv->softsshsample = 0x00;
1995		devpriv->softsshhold = 0x80;
1996	}
1997
1998	rt_printk(".\n");
1999
2000	pci_read_config_word(devpriv->pcidev, PCI_COMMAND, &u16w);
2001	pci_write_config_word(devpriv->pcidev, PCI_COMMAND, u16w | 64);	/*  Enable parity check for parity error */
2002
2003	ret = alloc_subdevices(dev, 4);
2004	if (ret < 0)
2005		return ret;
2006
2007	s = dev->subdevices + 0;
2008	dev->read_subdev = s;
2009	s->type = COMEDI_SUBD_AI;
2010	s->subdev_flags = SDF_READABLE | SDF_COMMON | SDF_GROUND | SDF_DIFF;
2011	if (devpriv->usemux) {
2012		s->n_chan = devpriv->usemux;
2013	} else {
2014		s->n_chan = this_board->n_aichan;
2015	}
2016	s->maxdata = this_board->ai_maxdata;
2017	s->len_chanlist = this_board->n_aichanlist;
2018	s->range_table = this_board->rangelist_ai;
2019	s->cancel = pci9118_ai_cancel;
2020	s->insn_read = pci9118_insn_read_ai;
2021	if (dev->irq) {
2022		s->subdev_flags |= SDF_CMD_READ;
2023		s->do_cmdtest = pci9118_ai_cmdtest;
2024		s->do_cmd = pci9118_ai_cmd;
2025		s->munge = pci9118_ai_munge;
2026	}
2027
2028	s = dev->subdevices + 1;
2029	s->type = COMEDI_SUBD_AO;
2030	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2031	s->n_chan = this_board->n_aochan;
2032	s->maxdata = this_board->ao_maxdata;
2033	s->len_chanlist = this_board->n_aochan;
2034	s->range_table = this_board->rangelist_ao;
2035	s->insn_write = pci9118_insn_write_ao;
2036	s->insn_read = pci9118_insn_read_ao;
2037
2038	s = dev->subdevices + 2;
2039	s->type = COMEDI_SUBD_DI;
2040	s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_COMMON;
2041	s->n_chan = 4;
2042	s->maxdata = 1;
2043	s->len_chanlist = 4;
2044	s->range_table = &range_digital;
2045	s->io_bits = 0;		/* all bits input */
2046	s->insn_bits = pci9118_insn_bits_di;
2047
2048	s = dev->subdevices + 3;
2049	s->type = COMEDI_SUBD_DO;
2050	s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_COMMON;
2051	s->n_chan = 4;
2052	s->maxdata = 1;
2053	s->len_chanlist = 4;
2054	s->range_table = &range_digital;
2055	s->io_bits = 0xf;	/* all bits output */
2056	s->insn_bits = pci9118_insn_bits_do;
2057
2058	devpriv->valid = 1;
2059	devpriv->i8254_osc_base = 250;	/*  250ns=4MHz */
2060	devpriv->ai_maskharderr = 0x10a;	/*  default measure crash condition */
2061	if (it->options[5])	/*  disable some requested */
2062		devpriv->ai_maskharderr &= ~it->options[5];
2063
2064	switch (this_board->ai_maxdata) {
2065	case 0xffff:
2066		devpriv->ai16bits = 1;
2067		break;
2068	default:
2069		devpriv->ai16bits = 0;
2070		break;
2071	}
2072	return 0;
2073}
2074
2075/*
2076==============================================================================
2077*/
2078static int pci9118_detach(struct comedi_device *dev)
2079{
2080	if (dev->private) {
2081		if (devpriv->valid)
2082			pci9118_reset(dev);
2083		if (dev->irq)
2084			comedi_free_irq(dev->irq, dev);
2085		if (devpriv->pcidev) {
2086			if (dev->iobase) {
2087				comedi_pci_disable(devpriv->pcidev);
2088			}
2089			pci_dev_put(devpriv->pcidev);
2090		}
2091		if (devpriv->dmabuf_virt[0])
2092			free_pages((unsigned long)devpriv->dmabuf_virt[0],
2093				devpriv->dmabuf_pages[0]);
2094		if (devpriv->dmabuf_virt[1])
2095			free_pages((unsigned long)devpriv->dmabuf_virt[1],
2096				devpriv->dmabuf_pages[1]);
2097	}
2098
2099	return 0;
2100}
2101
2102/*
2103==============================================================================
2104*/
2105