pcl818.c revision 0109253dee3d211619876d3345ecc4c312d1b153
1/*
2   comedi/drivers/pcl818.c
3
4   Author:  Michal Dobes <dobes@tesnet.cz>
5
6   hardware driver for Advantech cards:
7    card:   PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718
8    driver: pcl818l,  pcl818h,  pcl818hd,  pcl818hg,  pcl818,  pcl718
9*/
10/*
11Driver: pcl818
12Description: Advantech PCL-818 cards, PCL-718
13Author: Michal Dobes <dobes@tesnet.cz>
14Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
15  PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
16  PCL-718 (pcl718)
17Status: works
18
19All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
20Differences are only at maximal sample speed, range list and FIFO
21support.
22The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
23only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
24PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
25but this code is untested.
26A word or two about DMA. Driver support DMA operations at two ways:
271) DMA uses two buffers and after one is filled then is generated
28   INT and DMA restart with second buffer. With this mode I'm unable run
29   more that 80Ksamples/secs without data dropouts on K6/233.
302) DMA uses one buffer and run in autoinit mode and the data are
31   from DMA buffer moved on the fly with 2kHz interrupts from RTC.
32   This mode is used if the interrupt 8 is available for allocation.
33   If not, then first DMA mode is used. With this I can run at
34   full speed one card (100ksamples/secs) or two cards with
35   60ksamples/secs each (more is problem on account of ISA limitations).
36   To use this mode you must have compiled  kernel with disabled
37   "Enhanced Real Time Clock Support".
38   Maybe you can have problems if you use xntpd or similar.
39   If you've data dropouts with DMA mode 2 then:
40    a) disable IDE DMA
41    b) switch text mode console to fb.
42
43   Options for PCL-818L:
44    [0] - IO Base
45    [1] - IRQ	(0=disable, 2, 3, 4, 5, 6, 7)
46    [2] - DMA	(0=disable, 1, 3)
47    [3] - 0, 10=10MHz clock for 8254
48              1= 1MHz clock for 8254
49    [4] - 0,  5=A/D input  -5V.. +5V
50          1, 10=A/D input -10V..+10V
51    [5] - 0,  5=D/A output 0-5V  (internal reference -5V)
52          1, 10=D/A output 0-10V (internal reference -10V)
53	  2    =D/A output unknow (external reference)
54
55   Options for PCL-818, PCL-818H:
56    [0] - IO Base
57    [1] - IRQ	(0=disable, 2, 3, 4, 5, 6, 7)
58    [2] - DMA	(0=disable, 1, 3)
59    [3] - 0, 10=10MHz clock for 8254
60              1= 1MHz clock for 8254
61    [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
62          1, 10=D/A output 0-10V (internal reference -10V)
63	  2    =D/A output unknow (external reference)
64
65   Options for PCL-818HD, PCL-818HG:
66    [0] - IO Base
67    [1] - IRQ	(0=disable, 2, 3, 4, 5, 6, 7)
68    [2] - DMA/FIFO  (-1=use FIFO, 0=disable both FIFO and DMA,
69                      1=use DMA ch 1, 3=use DMA ch 3)
70    [3] - 0, 10=10MHz clock for 8254
71              1= 1MHz clock for 8254
72    [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
73          1, 10=D/A output 0-10V (internal reference -10V)
74   	  2    =D/A output unknow (external reference)
75
76   Options for PCL-718:
77    [0] - IO Base
78    [1] - IRQ	(0=disable, 2, 3, 4, 5, 6, 7)
79    [2] - DMA	(0=disable, 1, 3)
80    [3] - 0, 10=10MHz clock for 8254
81              1= 1MHz clock for 8254
82    [4] -     0=A/D Range is +/-10V
83	      1=             +/-5V
84	      2=             +/-2.5V
85	      3=             +/-1V
86	      4=             +/-0.5V
87	      5=  	     user defined bipolar
88	      6=	     0-10V
89	      7=	     0-5V
90 	      8=	     0-2V
91	      9=	     0-1V
92	     10=	     user defined unipolar
93    [5] - 0,  5=D/A outputs 0-5V  (internal reference -5V)
94          1, 10=D/A outputs 0-10V (internal reference -10V)
95	      2=D/A outputs unknow (external reference)
96    [6] - 0, 60=max  60kHz A/D sampling
97          1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
98
99*/
100
101#include "../comedidev.h"
102
103#include <linux/ioport.h>
104#include <linux/mc146818rtc.h>
105#include <linux/delay.h>
106#include <asm/dma.h>
107
108#include "8253.h"
109
110/* #define PCL818_MODE13_AO 1 */
111
112/* boards constants */
113
114#define boardPCL818L 0
115#define boardPCL818H 1
116#define boardPCL818HD 2
117#define boardPCL818HG 3
118#define boardPCL818 4
119#define boardPCL718 5
120
121/* IO space len */
122#define PCLx1x_RANGE 16
123/* IO space len if we use FIFO */
124#define PCLx1xFIFO_RANGE 32
125
126/* W: clear INT request */
127#define PCL818_CLRINT 8
128/* R: return status byte */
129#define PCL818_STATUS 8
130/* R: A/D high byte W: A/D range control */
131#define PCL818_RANGE 1
132/* R: next mux scan channel W: mux scan channel & range control pointer */
133#define PCL818_MUX 2
134/* R/W: operation control register */
135#define PCL818_CONTROL 9
136/* W: counter enable */
137#define PCL818_CNTENABLE 10
138
139/* R: low byte of A/D W: soft A/D trigger */
140#define PCL818_AD_LO 0
141/* R: high byte of A/D W: A/D range control */
142#define PCL818_AD_HI 1
143/* W: D/A low&high byte */
144#define PCL818_DA_LO 4
145#define PCL818_DA_HI 5
146/* R: low&high byte of DI */
147#define PCL818_DI_LO 3
148#define PCL818_DI_HI 11
149/* W: low&high byte of DO */
150#define PCL818_DO_LO 3
151#define PCL818_DO_HI 11
152/* W: PCL718 second D/A */
153#define PCL718_DA2_LO 6
154#define PCL718_DA2_HI 7
155/* counters */
156#define PCL818_CTR0 12
157#define PCL818_CTR1 13
158#define PCL818_CTR2 14
159/* W: counter control */
160#define PCL818_CTRCTL 15
161
162/* W: fifo enable/disable */
163#define PCL818_FI_ENABLE 6
164/* W: fifo interrupt clear */
165#define PCL818_FI_INTCLR 20
166/* W: fifo interrupt clear */
167#define PCL818_FI_FLUSH 25
168/* R: fifo status */
169#define PCL818_FI_STATUS 25
170/* R: one record from FIFO */
171#define PCL818_FI_DATALO 23
172#define PCL818_FI_DATAHI 23
173
174/* type of interrupt handler */
175#define INT_TYPE_AI1_INT 1
176#define INT_TYPE_AI1_DMA 2
177#define INT_TYPE_AI1_FIFO 3
178#define INT_TYPE_AI3_INT 4
179#define INT_TYPE_AI3_DMA 5
180#define INT_TYPE_AI3_FIFO 6
181#ifdef PCL818_MODE13_AO
182#define INT_TYPE_AO1_INT 7
183#define INT_TYPE_AO3_INT 8
184#endif
185
186#ifdef unused
187/* RTC stuff... */
188#define INT_TYPE_AI1_DMA_RTC 9
189#define INT_TYPE_AI3_DMA_RTC 10
190
191#define RTC_IRQ 	8
192#define RTC_IO_EXTENT	0x10
193#endif
194
195#define MAGIC_DMA_WORD 0x5a5a
196
197static const struct comedi_lrange range_pcl818h_ai = { 9, {
198			BIP_RANGE(5),
199			BIP_RANGE(2.5),
200			BIP_RANGE(1.25),
201			BIP_RANGE(0.625),
202			UNI_RANGE(10),
203			UNI_RANGE(5),
204			UNI_RANGE(2.5),
205			UNI_RANGE(1.25),
206			BIP_RANGE(10),
207	}
208};
209
210static const struct comedi_lrange range_pcl818hg_ai = { 10, {
211			BIP_RANGE(5),
212			BIP_RANGE(0.5),
213			BIP_RANGE(0.05),
214			BIP_RANGE(0.005),
215			UNI_RANGE(10),
216			UNI_RANGE(1),
217			UNI_RANGE(0.1),
218			UNI_RANGE(0.01),
219			BIP_RANGE(10),
220			BIP_RANGE(1),
221			BIP_RANGE(0.1),
222			BIP_RANGE(0.01),
223	}
224};
225
226static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
227			BIP_RANGE(5),
228			BIP_RANGE(2.5),
229			BIP_RANGE(1.25),
230			BIP_RANGE(0.625),
231	}
232};
233
234static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
235			BIP_RANGE(10),
236			BIP_RANGE(5),
237			BIP_RANGE(2.5),
238			BIP_RANGE(1.25),
239	}
240};
241
242static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
243static const struct comedi_lrange range718_bipolar0_5 = { 1, {BIP_RANGE(0.5),} };
244static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
245static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
246
247static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it);
248static int pcl818_detach(struct comedi_device * dev);
249
250#ifdef unused
251static int RTC_lock = 0;	/* RTC lock */
252static int RTC_timer_lock = 0;	/* RTC int lock */
253#endif
254
255struct pcl818_board {
256
257	const char *name;	/*  driver name */
258	int n_ranges;		/*  len of range list */
259	int n_aichan_se;	/*  num of A/D chans in single ended  mode */
260	int n_aichan_diff;	/*  num of A/D chans in diferencial mode */
261	unsigned int ns_min;	/*  minimal alllowed delay between samples (in ns) */
262	int n_aochan;		/*  num of D/A chans */
263	int n_dichan;		/*  num of DI chans */
264	int n_dochan;		/*  num of DO chans */
265	const struct comedi_lrange *ai_range_type;	/*  default A/D rangelist */
266	const struct comedi_lrange *ao_range_type;	/*  default D/A rangelist */
267	unsigned int io_range;	/*  len of IO space */
268	unsigned int IRQbits;	/*  allowed interrupts */
269	unsigned int DMAbits;	/*  allowed DMA chans */
270	int ai_maxdata;		/*  maxdata for A/D */
271	int ao_maxdata;		/*  maxdata for D/A */
272	unsigned char fifo;	/*  1=board has FIFO */
273	int is_818;
274};
275
276
277static const struct pcl818_board boardtypes[] = {
278	{"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
279			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
280		0x0a, 0xfff, 0xfff, 0, 1},
281	{"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
282			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
283		0x0a, 0xfff, 0xfff, 0, 1},
284	{"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
285			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
286		0x0a, 0xfff, 0xfff, 1, 1},
287	{"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
288			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
289		0x0a, 0xfff, 0xfff, 1, 1},
290	{"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
291			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
292		0x0a, 0xfff, 0xfff, 0, 1},
293	{"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
294			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
295		0x0a, 0xfff, 0xfff, 0, 0},
296	/* pcm3718 */
297	{"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
298			&range_unipolar5, PCLx1x_RANGE, 0x00fc,
299		0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
300};
301
302#define n_boardtypes (sizeof(boardtypes)/sizeof(struct pcl818_board))
303
304static struct comedi_driver driver_pcl818 = {
305      driver_name:"pcl818",
306      module:THIS_MODULE,
307      attach:pcl818_attach,
308      detach:pcl818_detach,
309      board_name:&boardtypes[0].name,
310      num_names:n_boardtypes,
311      offset:sizeof(struct pcl818_board),
312};
313
314COMEDI_INITCLEANUP(driver_pcl818);
315
316struct pcl818_private {
317
318	unsigned int dma;	/*  used DMA, 0=don't use DMA */
319	int dma_rtc;		/*  1=RTC used with DMA, 0=no RTC alloc */
320	unsigned int io_range;
321#ifdef unused
322	unsigned long rtc_iobase;	/*  RTC port region */
323	unsigned int rtc_iosize;
324	unsigned int rtc_irq;
325	struct timer_list rtc_irq_timer;	/*  timer for RTC sanity check */
326	unsigned long rtc_freq;	/*  RTC int freq */
327	int rtc_irq_blocked;	/*  1=we now do AI with DMA&RTC */
328#endif
329	unsigned long dmabuf[2];	/*  pointers to begin of DMA buffers */
330	unsigned int dmapages[2];	/*  len of DMA buffers in PAGE_SIZEs */
331	unsigned int hwdmaptr[2];	/*  hardware address of DMA buffers */
332	unsigned int hwdmasize[2];	/*  len of DMA buffers in Bytes */
333	unsigned int dmasamplsize;	/*  size in samples hwdmasize[0]/2 */
334	unsigned int last_top_dma;	/*  DMA pointer in last RTC int */
335	int next_dma_buf;	/*  which DMA buffer will be used next round */
336	long dma_runs_to_end;	/*  how many we must permorm DMA transfer to end of record */
337	unsigned long last_dma_run;	/*  how many bytes we must transfer on last DMA page */
338	unsigned char neverending_ai;	/*  if=1, then we do neverending record (you must use cancel()) */
339	unsigned int ns_min;	/*  manimal alllowed delay between samples (in us) for actual card */
340	int i8253_osc_base;	/*  1/frequency of on board oscilator in ns */
341	int irq_free;		/*  1=have allocated IRQ */
342	int irq_blocked;	/*  1=IRQ now uses any subdev */
343	int irq_was_now_closed;	/*  when IRQ finish, there's stored int818_mode for last interrupt */
344	int ai_mode;		/*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
345	struct comedi_subdevice *last_int_sub;	/*  ptr to subdevice which now finish */
346	int ai_act_scan;	/*  how many scans we finished */
347	int ai_act_chan;	/*  actual position in actual scan */
348	unsigned int act_chanlist[16];	/*  MUX setting for actual AI operations */
349	unsigned int act_chanlist_len;	/*  how long is actual MUX list */
350	unsigned int act_chanlist_pos;	/*  actual position in MUX list */
351	unsigned int ai_scans;	/*  len of scanlist */
352	unsigned int ai_n_chan;	/*  how many channels is measured */
353	unsigned int *ai_chanlist;	/*  actaul chanlist */
354	unsigned int ai_flags;	/*  flaglist */
355	unsigned int ai_data_len;	/*  len of data buffer */
356	short *ai_data;	/*  data buffer */
357	unsigned int ai_timer1;	/*  timers */
358	unsigned int ai_timer2;
359	struct comedi_subdevice *sub_ai;	/*  ptr to AI subdevice */
360	unsigned char usefifo;	/*  1=use fifo */
361	unsigned int ao_readback[2];
362};
363
364
365static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,	/*  used for gain list programming */
366	0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
367};
368
369#define devpriv ((struct pcl818_private *)dev->private)
370#define this_board ((const struct pcl818_board *)dev->board_ptr)
371
372/*
373==============================================================================
374*/
375static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
376	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen);
377static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
378	unsigned int *chanlist, unsigned int n_chan);
379
380static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
381static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
382	unsigned int divisor2);
383
384#ifdef unused
385static int set_rtc_irq_bit(unsigned char bit);
386static void rtc_dropped_irq(unsigned long data);
387static int rtc_setfreq_irq(int freq);
388#endif
389
390/*
391==============================================================================
392   ANALOG INPUT MODE0, 818 cards, slow version
393*/
394static int pcl818_ai_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
395	struct comedi_insn * insn, unsigned int * data)
396{
397	int n;
398	int timeout;
399
400	/* software trigger, DMA and INT off */
401	outb(0, dev->iobase + PCL818_CONTROL);
402
403	/* select channel */
404	outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
405
406	/* select gain */
407	outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
408
409	for (n = 0; n < insn->n; n++) {
410
411		/* clear INT (conversion end) flag */
412		outb(0, dev->iobase + PCL818_CLRINT);
413
414		/* start conversion */
415		outb(0, dev->iobase + PCL818_AD_LO);
416
417		timeout = 100;
418		while (timeout--) {
419			if (inb(dev->iobase + PCL818_STATUS) & 0x10)
420				goto conv_finish;
421			comedi_udelay(1);
422		}
423		comedi_error(dev, "A/D insn timeout");
424		/* clear INT (conversion end) flag */
425		outb(0, dev->iobase + PCL818_CLRINT);
426		return -EIO;
427
428	      conv_finish:
429		data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
430			(inb(dev->iobase + PCL818_AD_LO) >> 4));
431	}
432
433	return n;
434}
435
436/*
437==============================================================================
438   ANALOG OUTPUT MODE0, 818 cards
439   only one sample per call is supported
440*/
441static int pcl818_ao_insn_read(struct comedi_device * dev, struct comedi_subdevice * s,
442	struct comedi_insn * insn, unsigned int * data)
443{
444	int n;
445	int chan = CR_CHAN(insn->chanspec);
446
447	for (n = 0; n < insn->n; n++) {
448		data[n] = devpriv->ao_readback[chan];
449	}
450
451	return n;
452}
453
454static int pcl818_ao_insn_write(struct comedi_device * dev, struct comedi_subdevice * s,
455	struct comedi_insn * insn, unsigned int * data)
456{
457	int n;
458	int chan = CR_CHAN(insn->chanspec);
459
460	for (n = 0; n < insn->n; n++) {
461		devpriv->ao_readback[chan] = data[n];
462		outb((data[n] & 0x000f) << 4, dev->iobase +
463			(chan) ? PCL718_DA2_LO : PCL818_DA_LO);
464		outb((data[n] & 0x0ff0) >> 4, dev->iobase +
465			(chan) ? PCL718_DA2_HI : PCL818_DA_HI);
466	}
467
468	return n;
469}
470
471/*
472==============================================================================
473   DIGITAL INPUT MODE0, 818 cards
474
475   only one sample per call is supported
476*/
477static int pcl818_di_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
478	struct comedi_insn * insn, unsigned int * data)
479{
480	if (insn->n != 2)
481		return -EINVAL;
482
483	data[1] = inb(dev->iobase + PCL818_DI_LO) |
484		(inb(dev->iobase + PCL818_DI_HI) << 8);
485
486	return 2;
487}
488
489/*
490==============================================================================
491   DIGITAL OUTPUT MODE0, 818 cards
492
493   only one sample per call is supported
494*/
495static int pcl818_do_insn_bits(struct comedi_device * dev, struct comedi_subdevice * s,
496	struct comedi_insn * insn, unsigned int * data)
497{
498	if (insn->n != 2)
499		return -EINVAL;
500
501	s->state &= ~data[0];
502	s->state |= (data[0] & data[1]);
503
504	outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
505	outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
506
507	data[1] = s->state;
508
509	return 2;
510}
511
512/*
513==============================================================================
514   analog input interrupt mode 1 & 3, 818 cards
515   one sample per interrupt version
516*/
517static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
518{
519	struct comedi_device *dev = d;
520	struct comedi_subdevice *s = dev->subdevices + 0;
521	int low;
522	int timeout = 50;	/* wait max 50us */
523
524	while (timeout--) {
525		if (inb(dev->iobase + PCL818_STATUS) & 0x10)
526			goto conv_finish;
527		comedi_udelay(1);
528	}
529	outb(0, dev->iobase + PCL818_STATUS);	/* clear INT request */
530	comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
531	pcl818_ai_cancel(dev, s);
532	s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
533	comedi_event(dev, s);
534	return IRQ_HANDLED;
535
536      conv_finish:
537	low = inb(dev->iobase + PCL818_AD_LO);
538	comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));	/*  get one sample */
539	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
540
541	if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
542		rt_printk
543			("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
544			(low & 0xf),
545			devpriv->act_chanlist[devpriv->act_chanlist_pos]);
546		pcl818_ai_cancel(dev, s);
547		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
548		comedi_event(dev, s);
549		return IRQ_HANDLED;
550	}
551	if (s->async->cur_chan == 0) {
552		/*  rt_printk("E"); */
553		devpriv->ai_act_scan--;
554	}
555
556	if (!devpriv->neverending_ai) {
557		if (devpriv->ai_act_scan == 0) {	/* all data sampled */
558			pcl818_ai_cancel(dev, s);
559			s->async->events |= COMEDI_CB_EOA;
560		}
561	}
562	comedi_event(dev, s);
563	return IRQ_HANDLED;
564}
565
566/*
567==============================================================================
568   analog input dma mode 1 & 3, 818 cards
569*/
570static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
571{
572	struct comedi_device *dev = d;
573	struct comedi_subdevice *s = dev->subdevices + 0;
574	int i, len, bufptr;
575	unsigned long flags;
576	short *ptr;
577
578	disable_dma(devpriv->dma);
579	devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
580	if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {	/*  switch dma bufs */
581		set_dma_mode(devpriv->dma, DMA_MODE_READ);
582		flags = claim_dma_lock();
583		set_dma_addr(devpriv->dma,
584			devpriv->hwdmaptr[devpriv->next_dma_buf]);
585		if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
586			set_dma_count(devpriv->dma,
587				devpriv->hwdmasize[devpriv->next_dma_buf]);
588		} else {
589			set_dma_count(devpriv->dma, devpriv->last_dma_run);
590		}
591		release_dma_lock(flags);
592		enable_dma(devpriv->dma);
593	}
594	rt_printk("comedi: A/D mode1/3 IRQ \n");
595
596	devpriv->dma_runs_to_end--;
597	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
598	ptr = (short *) devpriv->dmabuf[1 - devpriv->next_dma_buf];
599
600	len = devpriv->hwdmasize[0] >> 1;
601	bufptr = 0;
602
603	for (i = 0; i < len; i++) {
604		if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
605			rt_printk
606				("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
607				(ptr[bufptr] & 0xf),
608				devpriv->act_chanlist[devpriv->
609					act_chanlist_pos],
610				devpriv->act_chanlist_pos);
611			pcl818_ai_cancel(dev, s);
612			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
613			comedi_event(dev, s);
614			return IRQ_HANDLED;
615		}
616
617		comedi_buf_put(s->async, ptr[bufptr++] >> 4);	/*  get one sample */
618
619		devpriv->act_chanlist_pos++;
620		if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len) {
621			devpriv->ai_act_scan--;
622			devpriv->act_chanlist_pos = 0;
623		}
624
625		if (!devpriv->neverending_ai)
626			if (devpriv->ai_act_scan == 0) {	/* all data sampled */
627				pcl818_ai_cancel(dev, s);
628				s->async->events |= COMEDI_CB_EOA;
629				comedi_event(dev, s);
630				/*  printk("done int ai13 dma\n"); */
631				return IRQ_HANDLED;
632			}
633	}
634
635	if (len > 0)
636		comedi_event(dev, s);
637	return IRQ_HANDLED;
638}
639
640#ifdef unused
641/*
642==============================================================================
643   analog input dma mode 1 & 3 over RTC, 818 cards
644*/
645static irqreturn_t interrupt_pcl818_ai_mode13_dma_rtc(int irq, void *d)
646{
647	struct comedi_device *dev = d;
648	struct comedi_subdevice *s = dev->subdevices + 0;
649	unsigned long tmp;
650	unsigned int top1, top2, i, bufptr;
651	long ofs_dats;
652	short *dmabuf = (short *) devpriv->dmabuf[0];
653
654	/* outb(2,0x378); */
655	switch (devpriv->ai_mode) {
656	case INT_TYPE_AI1_DMA_RTC:
657	case INT_TYPE_AI3_DMA_RTC:
658		tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);
659		mod_timer(&devpriv->rtc_irq_timer,
660			jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
661
662		for (i = 0; i < 10; i++) {
663			top1 = get_dma_residue(devpriv->dma);
664			top2 = get_dma_residue(devpriv->dma);
665			if (top1 == top2)
666				break;
667		}
668
669		if (top1 != top2)
670			return IRQ_HANDLED;
671		top1 = devpriv->hwdmasize[0] - top1;	/*  where is now DMA in buffer */
672		top1 >>= 1;
673		ofs_dats = top1 - devpriv->last_top_dma;	/*  new samples from last call */
674		if (ofs_dats < 0)
675			ofs_dats = (devpriv->dmasamplsize) + ofs_dats;
676		if (!ofs_dats)
677			return IRQ_HANDLED;	/*  exit=no new samples from last call */
678		/*  obsluz data */
679		i = devpriv->last_top_dma - 1;
680		i &= (devpriv->dmasamplsize - 1);
681
682		if (dmabuf[i] != MAGIC_DMA_WORD) {	/*  DMA overflow! */
683			comedi_error(dev, "A/D mode1/3 DMA buffer overflow!");
684			/* rt_printk("I %d dmabuf[i] %d %d\n",i,dmabuf[i],devpriv->dmasamplsize); */
685			pcl818_ai_cancel(dev, s);
686			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
687			comedi_event(dev, s);
688			return IRQ_HANDLED;
689		}
690		/* rt_printk("r %ld ",ofs_dats); */
691
692		bufptr = devpriv->last_top_dma;
693
694		for (i = 0; i < ofs_dats; i++) {
695			if ((dmabuf[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
696				rt_printk
697					("comedi: A/D mode1/3 DMA - channel dropout %d!=%d !\n",
698					(dmabuf[bufptr] & 0xf),
699					devpriv->act_chanlist[devpriv->
700						act_chanlist_pos]);
701				pcl818_ai_cancel(dev, s);
702				s->async->events |=
703					COMEDI_CB_EOA | COMEDI_CB_ERROR;
704				comedi_event(dev, s);
705				return IRQ_HANDLED;
706			}
707
708			comedi_buf_put(s->async, dmabuf[bufptr++] >> 4);	/*  get one sample */
709			bufptr &= (devpriv->dmasamplsize - 1);
710
711			if (s->async->cur_chan == 0) {
712				devpriv->ai_act_scan--;
713			}
714
715			if (!devpriv->neverending_ai)
716				if (devpriv->ai_act_scan == 0) {	/* all data sampled */
717					pcl818_ai_cancel(dev, s);
718					s->async->events |= COMEDI_CB_EOA;
719					comedi_event(dev, s);
720					/* printk("done int ai13 dma\n"); */
721					return IRQ_HANDLED;
722				}
723		}
724
725		devpriv->last_top_dma = bufptr;
726		bufptr--;
727		bufptr &= (devpriv->dmasamplsize - 1);
728		dmabuf[bufptr] = MAGIC_DMA_WORD;
729		comedi_event(dev, s);
730		/* outb(0,0x378); */
731		return IRQ_HANDLED;
732	}
733
734	/* outb(0,0x378); */
735	return IRQ_HANDLED;
736}
737#endif
738
739/*
740==============================================================================
741   analog input interrupt mode 1 & 3, 818HD/HG cards
742*/
743static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
744{
745	struct comedi_device *dev = d;
746	struct comedi_subdevice *s = dev->subdevices + 0;
747	int i, len, lo;
748
749	outb(0, dev->iobase + PCL818_FI_INTCLR);	/*  clear fifo int request */
750
751	lo = inb(dev->iobase + PCL818_FI_STATUS);
752
753	if (lo & 4) {
754		comedi_error(dev, "A/D mode1/3 FIFO overflow!");
755		pcl818_ai_cancel(dev, s);
756		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
757		comedi_event(dev, s);
758		return IRQ_HANDLED;
759	}
760
761	if (lo & 1) {
762		comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
763		pcl818_ai_cancel(dev, s);
764		s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
765		comedi_event(dev, s);
766		return IRQ_HANDLED;
767	}
768
769	if (lo & 2) {
770		len = 512;
771	} else {
772		len = 0;
773	}
774
775	for (i = 0; i < len; i++) {
776		lo = inb(dev->iobase + PCL818_FI_DATALO);
777		if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {	/*  dropout! */
778			rt_printk
779				("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
780				(lo & 0xf),
781				devpriv->act_chanlist[devpriv->
782					act_chanlist_pos]);
783			pcl818_ai_cancel(dev, s);
784			s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
785			comedi_event(dev, s);
786			return IRQ_HANDLED;
787		}
788
789		comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));	/*  get one sample */
790
791		if (s->async->cur_chan == 0) {
792			devpriv->ai_act_scan--;
793		}
794
795		if (!devpriv->neverending_ai)
796			if (devpriv->ai_act_scan == 0) {	/* all data sampled */
797				pcl818_ai_cancel(dev, s);
798				s->async->events |= COMEDI_CB_EOA;
799				comedi_event(dev, s);
800				return IRQ_HANDLED;
801			}
802	}
803
804	if (len > 0)
805		comedi_event(dev, s);
806	return IRQ_HANDLED;
807}
808
809/*
810==============================================================================
811    INT procedure
812*/
813static irqreturn_t interrupt_pcl818(int irq, void *d PT_REGS_ARG)
814{
815	struct comedi_device *dev = d;
816
817	if (!dev->attached) {
818		comedi_error(dev, "premature interrupt");
819		return IRQ_HANDLED;
820	}
821	/* rt_printk("I\n"); */
822
823	switch (devpriv->ai_mode) {
824	case INT_TYPE_AI1_DMA:
825	case INT_TYPE_AI3_DMA:
826		return interrupt_pcl818_ai_mode13_dma(irq, d);
827	case INT_TYPE_AI1_INT:
828	case INT_TYPE_AI3_INT:
829		return interrupt_pcl818_ai_mode13_int(irq, d);
830	case INT_TYPE_AI1_FIFO:
831	case INT_TYPE_AI3_FIFO:
832		return interrupt_pcl818_ai_mode13_fifo(irq, d);
833#ifdef PCL818_MODE13_AO
834	case INT_TYPE_AO1_INT:
835	case INT_TYPE_AO3_INT:
836		return interrupt_pcl818_ao_mode13_int(irq, d);
837#endif
838	default:
839		break;
840	}
841
842	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
843
844	if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
845		|| (!devpriv->ai_mode)) {
846		if (devpriv->irq_was_now_closed) {
847			if (devpriv->neverending_ai &&
848				(devpriv->ai_mode == INT_TYPE_AI1_DMA
849					|| devpriv->ai_mode ==
850					INT_TYPE_AI3_DMA)) {
851				/* we had neverending ai but ai_cancel() has been called
852				   the cleanup from ai_cancel() has been delayed until know
853				   because the card doesn't seem to like being reprogrammed
854				   while a DMA transfer is in progress
855				 */
856				struct comedi_subdevice *s = dev->subdevices + 0;
857				devpriv->ai_mode = devpriv->irq_was_now_closed;
858				devpriv->irq_was_now_closed = 0;
859				devpriv->neverending_ai = 0;
860				pcl818_ai_cancel(dev, s);
861			}
862			devpriv->irq_was_now_closed = 0;
863			return IRQ_HANDLED;
864		}
865		comedi_error(dev, "bad IRQ!");
866		return IRQ_NONE;
867	}
868
869	comedi_error(dev, "IRQ from unknow source!");
870	return IRQ_NONE;
871}
872
873/*
874==============================================================================
875   ANALOG INPUT MODE 1 or 3 DMA , 818 cards
876*/
877static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
878	struct comedi_subdevice * s)
879{
880	unsigned int flags;
881	unsigned int bytes;
882
883	rt_printk("mode13dma_int, mode: %d\n", mode);
884	disable_dma(devpriv->dma);	/*  disable dma */
885	bytes = devpriv->hwdmasize[0];
886	if (!devpriv->neverending_ai) {
887		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	/*  how many */
888		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	/*  how many DMA pages we must fiil */
889		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	/* on last dma transfer must be moved */
890		devpriv->dma_runs_to_end--;
891		if (devpriv->dma_runs_to_end >= 0)
892			bytes = devpriv->hwdmasize[0];
893	}
894
895	devpriv->next_dma_buf = 0;
896	set_dma_mode(devpriv->dma, DMA_MODE_READ);
897	flags = claim_dma_lock();
898	clear_dma_ff(devpriv->dma);
899	set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
900	set_dma_count(devpriv->dma, bytes);
901	release_dma_lock(flags);
902	enable_dma(devpriv->dma);
903
904	if (mode == 1) {
905		devpriv->ai_mode = INT_TYPE_AI1_DMA;
906		outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ+DMA */
907	} else {
908		devpriv->ai_mode = INT_TYPE_AI3_DMA;
909		outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ+DMA */
910	};
911}
912
913#ifdef unused
914/*
915==============================================================================
916   ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
917*/
918static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
919	struct comedi_subdevice * s)
920{
921	unsigned int flags;
922	short *pole;
923
924	set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
925	flags = claim_dma_lock();
926	clear_dma_ff(devpriv->dma);
927	set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
928	set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
929	release_dma_lock(flags);
930	enable_dma(devpriv->dma);
931	devpriv->last_top_dma = 0;	/* devpriv->hwdmasize[0]; */
932	pole = (short *) devpriv->dmabuf[0];
933	devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
934	pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
935#ifdef unused
936	devpriv->rtc_freq = rtc_setfreq_irq(2048);
937	devpriv->rtc_irq_timer.expires =
938		jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
939	devpriv->rtc_irq_timer.data = (unsigned long)dev;
940	devpriv->rtc_irq_timer.function = rtc_dropped_irq;
941
942	add_timer(&devpriv->rtc_irq_timer);
943#endif
944
945	if (mode == 1) {
946		devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
947		outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+DMA */
948	} else {
949		devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
950		outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+DMA */
951	};
952}
953#endif
954
955/*
956==============================================================================
957   ANALOG INPUT MODE 1 or 3, 818 cards
958*/
959static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
960	struct comedi_subdevice * s)
961{
962	struct comedi_cmd *cmd = &s->async->cmd;
963	int divisor1, divisor2;
964	unsigned int seglen;
965
966	rt_printk("pcl818_ai_cmd_mode()\n");
967	if ((!dev->irq) && (!devpriv->dma_rtc)) {
968		comedi_error(dev, "IRQ not defined!");
969		return -EINVAL;
970	}
971
972	if (devpriv->irq_blocked)
973		return -EBUSY;
974
975	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
976
977	seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
978		devpriv->ai_n_chan);
979	if (seglen < 1)
980		return -EINVAL;
981	setup_channel_list(dev, s, devpriv->ai_chanlist,
982		devpriv->ai_n_chan, seglen);
983
984	comedi_udelay(1);
985
986	devpriv->ai_act_scan = devpriv->ai_scans;
987	devpriv->ai_act_chan = 0;
988	devpriv->irq_blocked = 1;
989	devpriv->irq_was_now_closed = 0;
990	devpriv->neverending_ai = 0;
991	devpriv->act_chanlist_pos = 0;
992	devpriv->dma_runs_to_end = 0;
993
994	if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
995		devpriv->neverending_ai = 1;	/* well, user want neverending */
996
997	if (mode == 1) {
998		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
999			&divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST);
1000		if (divisor1 == 1) {	/* PCL718/818 crash if any divisor is set to 1 */
1001			divisor1 = 2;
1002			divisor2 /= 2;
1003		}
1004		if (divisor2 == 1) {
1005			divisor2 = 2;
1006			divisor1 /= 2;
1007		}
1008	}
1009
1010	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
1011
1012	switch (devpriv->dma) {
1013	case 1:		/*  DMA */
1014	case 3:
1015		if (devpriv->dma_rtc == 0) {
1016			pcl818_ai_mode13dma_int(mode, dev, s);
1017		}
1018#ifdef unused
1019		else {
1020			pcl818_ai_mode13dma_rtc(mode, dev, s);
1021		}
1022#else
1023		else {
1024			return -EINVAL;
1025		}
1026#endif
1027		break;
1028	case 0:		/*  IRQ */
1029		/*  rt_printk("IRQ\n"); */
1030		if (mode == 1) {
1031			devpriv->ai_mode = INT_TYPE_AI1_INT;
1032			outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ */
1033		} else {
1034			devpriv->ai_mode = INT_TYPE_AI3_INT;
1035			outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ */
1036		};
1037		break;
1038	case -1:		/*  FIFO */
1039		outb(1, dev->iobase + PCL818_FI_ENABLE);	/*  enable FIFO */
1040		if (mode == 1) {
1041			devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1042			outb(0x03, dev->iobase + PCL818_CONTROL);	/* Pacer */
1043		} else {
1044			devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1045			outb(0x02, dev->iobase + PCL818_CONTROL);
1046		};		/* Ext trig */
1047		break;
1048	}
1049
1050	start_pacer(dev, mode, divisor1, divisor2);
1051
1052#ifdef unused
1053	switch (devpriv->ai_mode) {
1054	case INT_TYPE_AI1_DMA_RTC:
1055	case INT_TYPE_AI3_DMA_RTC:
1056		set_rtc_irq_bit(1);	/* start RTC */
1057		break;
1058	}
1059#endif
1060	rt_printk("pcl818_ai_cmd_mode() end\n");
1061	return 0;
1062}
1063
1064#ifdef unused
1065/*
1066==============================================================================
1067   ANALOG OUTPUT MODE 1 or 3, 818 cards
1068*/
1069#ifdef PCL818_MODE13_AO
1070static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s,
1071	comedi_trig * it)
1072{
1073	int divisor1, divisor2;
1074
1075	if (!dev->irq) {
1076		comedi_error(dev, "IRQ not defined!");
1077		return -EINVAL;
1078	}
1079
1080	if (devpriv->irq_blocked)
1081		return -EBUSY;
1082
1083	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
1084
1085	devpriv->int13_act_scan = it->n;
1086	devpriv->int13_act_chan = 0;
1087	devpriv->irq_blocked = 1;
1088	devpriv->irq_was_now_closed = 0;
1089	devpriv->neverending_ai = 0;
1090	devpriv->act_chanlist_pos = 0;
1091
1092	if (mode == 1) {
1093		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1094			&divisor2, &it->trigvar, TRIG_ROUND_NEAREST);
1095		if (divisor1 == 1) {	/* PCL818 crash if any divisor is set to 1 */
1096			divisor1 = 2;
1097			divisor2 /= 2;
1098		}
1099		if (divisor2 == 1) {
1100			divisor2 = 2;
1101			divisor1 /= 2;
1102		}
1103	}
1104
1105	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
1106	if (mode == 1) {
1107		devpriv->int818_mode = INT_TYPE_AO1_INT;
1108		outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ */
1109	} else {
1110		devpriv->int818_mode = INT_TYPE_AO3_INT;
1111		outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ */
1112	};
1113
1114	start_pacer(dev, mode, divisor1, divisor2);
1115
1116	return 0;
1117}
1118
1119/*
1120==============================================================================
1121   ANALOG OUTPUT MODE 1, 818 cards
1122*/
1123static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s,
1124	comedi_trig * it)
1125{
1126	return pcl818_ao_mode13(1, dev, s, it);
1127}
1128
1129/*
1130==============================================================================
1131   ANALOG OUTPUT MODE 3, 818 cards
1132*/
1133static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s,
1134	comedi_trig * it)
1135{
1136	return pcl818_ao_mode13(3, dev, s, it);
1137}
1138#endif
1139#endif
1140
1141/*
1142==============================================================================
1143 Start/stop pacer onboard pacer
1144*/
1145static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
1146	unsigned int divisor2)
1147{
1148	outb(0xb4, dev->iobase + PCL818_CTRCTL);
1149	outb(0x74, dev->iobase + PCL818_CTRCTL);
1150	comedi_udelay(1);
1151
1152	if (mode == 1) {
1153		outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1154		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1155		outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1156		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1157	}
1158}
1159
1160/*
1161==============================================================================
1162 Check if channel list from user is builded correctly
1163 If it's ok, then program scan/gain logic
1164*/
1165static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1166	unsigned int *chanlist, unsigned int n_chan)
1167{
1168	unsigned int chansegment[16];
1169	unsigned int i, nowmustbechan, seglen, segpos;
1170
1171	/* correct channel and range number check itself comedi/range.c */
1172	if (n_chan < 1) {
1173		comedi_error(dev, "range/channel list is empty!");
1174		return 0;
1175	}
1176
1177	if (n_chan > 1) {
1178		/*  first channel is everytime ok */
1179		chansegment[0] = chanlist[0];
1180		/*  build part of chanlist */
1181		for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1182
1183			/* rt_printk("%d. %d * %d\n",i,
1184			 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1185
1186			/* we detect loop, this must by finish */
1187
1188			if (chanlist[0] == chanlist[i])
1189				break;
1190			nowmustbechan =
1191				(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1192			if (nowmustbechan != CR_CHAN(chanlist[i])) {	/*  channel list isn't continous :-( */
1193				rt_printk
1194					("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1195					dev->minor, i, CR_CHAN(chanlist[i]),
1196					nowmustbechan, CR_CHAN(chanlist[0]));
1197				return 0;
1198			}
1199			/*  well, this is next correct channel in list */
1200			chansegment[i] = chanlist[i];
1201		}
1202
1203		/*  check whole chanlist */
1204		for (i = 0, segpos = 0; i < n_chan; i++) {
1205			/* rt_printk("%d %d=%d %d\n",CR_CHAN(chansegment[i%seglen]),CR_RANGE(chansegment[i%seglen]),CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i])); */
1206			if (chanlist[i] != chansegment[i % seglen]) {
1207				rt_printk
1208					("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1209					dev->minor, i, CR_CHAN(chansegment[i]),
1210					CR_RANGE(chansegment[i]),
1211					CR_AREF(chansegment[i]),
1212					CR_CHAN(chanlist[i % seglen]),
1213					CR_RANGE(chanlist[i % seglen]),
1214					CR_AREF(chansegment[i % seglen]));
1215				return 0;	/*  chan/gain list is strange */
1216			}
1217		}
1218	} else {
1219		seglen = 1;
1220	}
1221	rt_printk("check_channel_list: seglen %d\n", seglen);
1222	return seglen;
1223}
1224
1225static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1226	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
1227{
1228	int i;
1229
1230	devpriv->act_chanlist_len = seglen;
1231	devpriv->act_chanlist_pos = 0;
1232
1233	for (i = 0; i < seglen; i++) {	/*  store range list to card */
1234		devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1235		outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);	/* select channel */
1236		outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);	/* select gain */
1237	}
1238
1239	comedi_udelay(1);
1240
1241	/* select channel interval to scan */
1242	outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1243				1] << 4), dev->iobase + PCL818_MUX);
1244}
1245
1246/*
1247==============================================================================
1248 Check if board is switched to SE (1) or DIFF(0) mode
1249*/
1250static int check_single_ended(unsigned int port)
1251{
1252	if (inb(port + PCL818_STATUS) & 0x20) {
1253		return 1;
1254	} else {
1255		return 0;
1256	}
1257}
1258
1259/*
1260==============================================================================
1261*/
1262static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1263	struct comedi_cmd * cmd)
1264{
1265	int err = 0;
1266	int tmp, divisor1, divisor2;
1267
1268	/* step 1: make sure trigger sources are trivially valid */
1269
1270	tmp = cmd->start_src;
1271	cmd->start_src &= TRIG_NOW;
1272	if (!cmd->start_src || tmp != cmd->start_src)
1273		err++;
1274
1275	tmp = cmd->scan_begin_src;
1276	cmd->scan_begin_src &= TRIG_FOLLOW;
1277	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1278		err++;
1279
1280	tmp = cmd->convert_src;
1281	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1282	if (!cmd->convert_src || tmp != cmd->convert_src)
1283		err++;
1284
1285	tmp = cmd->scan_end_src;
1286	cmd->scan_end_src &= TRIG_COUNT;
1287	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1288		err++;
1289
1290	tmp = cmd->stop_src;
1291	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1292	if (!cmd->stop_src || tmp != cmd->stop_src)
1293		err++;
1294
1295	if (err) {
1296		return 1;
1297	}
1298
1299	/* step 2: make sure trigger sources are unique and mutually compatible */
1300
1301	if (cmd->start_src != TRIG_NOW) {
1302		cmd->start_src = TRIG_NOW;
1303		err++;
1304	}
1305	if (cmd->scan_begin_src != TRIG_FOLLOW) {
1306		cmd->scan_begin_src = TRIG_FOLLOW;
1307		err++;
1308	}
1309	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1310		err++;
1311
1312	if (cmd->scan_end_src != TRIG_COUNT) {
1313		cmd->scan_end_src = TRIG_COUNT;
1314		err++;
1315	}
1316
1317	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1318		err++;
1319
1320	if (err) {
1321		return 2;
1322	}
1323
1324	/* step 3: make sure arguments are trivially compatible */
1325
1326	if (cmd->start_arg != 0) {
1327		cmd->start_arg = 0;
1328		err++;
1329	}
1330
1331	if (cmd->scan_begin_arg != 0) {
1332		cmd->scan_begin_arg = 0;
1333		err++;
1334	}
1335
1336	if (cmd->convert_src == TRIG_TIMER) {
1337		if (cmd->convert_arg < this_board->ns_min) {
1338			cmd->convert_arg = this_board->ns_min;
1339			err++;
1340		}
1341	} else {		/* TRIG_EXT */
1342		if (cmd->convert_arg != 0) {
1343			cmd->convert_arg = 0;
1344			err++;
1345		}
1346	}
1347
1348	if (!cmd->chanlist_len) {
1349		cmd->chanlist_len = 1;
1350		err++;
1351	}
1352	if (cmd->chanlist_len > s->n_chan) {
1353		cmd->chanlist_len = s->n_chan;
1354		err++;
1355	}
1356	if (cmd->scan_end_arg != cmd->chanlist_len) {
1357		cmd->scan_end_arg = cmd->chanlist_len;
1358		err++;
1359	}
1360	if (cmd->stop_src == TRIG_COUNT) {
1361		if (!cmd->stop_arg) {
1362			cmd->stop_arg = 1;
1363			err++;
1364		}
1365	} else {		/* TRIG_NONE */
1366		if (cmd->stop_arg != 0) {
1367			cmd->stop_arg = 0;
1368			err++;
1369		}
1370	}
1371
1372	if (err) {
1373		return 3;
1374	}
1375
1376	/* step 4: fix up any arguments */
1377
1378	if (cmd->convert_src == TRIG_TIMER) {
1379		tmp = cmd->convert_arg;
1380		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1381			&divisor2, &cmd->convert_arg,
1382			cmd->flags & TRIG_ROUND_MASK);
1383		if (cmd->convert_arg < this_board->ns_min)
1384			cmd->convert_arg = this_board->ns_min;
1385		if (tmp != cmd->convert_arg)
1386			err++;
1387	}
1388
1389	if (err) {
1390		return 4;
1391	}
1392
1393	/* step 5: complain about special chanlist considerations */
1394
1395	if (cmd->chanlist) {
1396		if (!check_channel_list(dev, s, cmd->chanlist,
1397				cmd->chanlist_len))
1398			return 5;	/*  incorrect channels list */
1399	}
1400
1401	return 0;
1402}
1403
1404/*
1405==============================================================================
1406*/
1407static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
1408{
1409	struct comedi_cmd *cmd = &s->async->cmd;
1410	int retval;
1411
1412	rt_printk("pcl818_ai_cmd()\n");
1413	devpriv->ai_n_chan = cmd->chanlist_len;
1414	devpriv->ai_chanlist = cmd->chanlist;
1415	devpriv->ai_flags = cmd->flags;
1416	devpriv->ai_data_len = s->async->prealloc_bufsz;
1417	devpriv->ai_data = s->async->prealloc_buf;
1418	devpriv->ai_timer1 = 0;
1419	devpriv->ai_timer2 = 0;
1420
1421	if (cmd->stop_src == TRIG_COUNT) {
1422		devpriv->ai_scans = cmd->stop_arg;
1423	} else {
1424		devpriv->ai_scans = 0;
1425	}
1426
1427	if (cmd->scan_begin_src == TRIG_FOLLOW) {	/*  mode 1, 3 */
1428		if (cmd->convert_src == TRIG_TIMER) {	/*  mode 1 */
1429			devpriv->ai_timer1 = cmd->convert_arg;
1430			retval = pcl818_ai_cmd_mode(1, dev, s);
1431			rt_printk("pcl818_ai_cmd() end\n");
1432			return retval;
1433		}
1434		if (cmd->convert_src == TRIG_EXT) {	/*  mode 3 */
1435			return pcl818_ai_cmd_mode(3, dev, s);
1436		}
1437	}
1438
1439	return -1;
1440}
1441
1442/*
1443==============================================================================
1444 cancel any mode 1-4 AI
1445*/
1446static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1447{
1448	if (devpriv->irq_blocked > 0) {
1449		rt_printk("pcl818_ai_cancel()\n");
1450		devpriv->irq_was_now_closed = devpriv->ai_mode;
1451		devpriv->ai_mode = 0;
1452
1453		switch (devpriv->irq_was_now_closed) {
1454#ifdef unused
1455		case INT_TYPE_AI1_DMA_RTC:
1456		case INT_TYPE_AI3_DMA_RTC:
1457			set_rtc_irq_bit(0);	/*  stop RTC */
1458			del_timer(&devpriv->rtc_irq_timer);
1459#endif
1460		case INT_TYPE_AI1_DMA:
1461		case INT_TYPE_AI3_DMA:
1462			if (devpriv->neverending_ai) {
1463				/* wait for running dma transfer to end, do cleanup in interrupt */
1464				goto end;
1465			}
1466			disable_dma(devpriv->dma);
1467		case INT_TYPE_AI1_INT:
1468		case INT_TYPE_AI3_INT:
1469		case INT_TYPE_AI1_FIFO:
1470		case INT_TYPE_AI3_FIFO:
1471#ifdef PCL818_MODE13_AO
1472		case INT_TYPE_AO1_INT:
1473		case INT_TYPE_AO3_INT:
1474#endif
1475			outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1476			comedi_udelay(1);
1477			start_pacer(dev, -1, 0, 0);
1478			outb(0, dev->iobase + PCL818_AD_LO);
1479			inb(dev->iobase + PCL818_AD_LO);
1480			inb(dev->iobase + PCL818_AD_HI);
1481			outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
1482			outb(0, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1483			if (devpriv->usefifo) {	/*  FIFO shutdown */
1484				outb(0, dev->iobase + PCL818_FI_INTCLR);
1485				outb(0, dev->iobase + PCL818_FI_FLUSH);
1486				outb(0, dev->iobase + PCL818_FI_ENABLE);
1487			}
1488			devpriv->irq_blocked = 0;
1489			devpriv->last_int_sub = s;
1490			devpriv->neverending_ai = 0;
1491			break;
1492		}
1493	}
1494
1495      end:
1496	rt_printk("pcl818_ai_cancel() end\n");
1497	return 0;
1498}
1499
1500/*
1501==============================================================================
1502 chech for PCL818
1503*/
1504static int pcl818_check(unsigned long iobase)
1505{
1506	outb(0x00, iobase + PCL818_MUX);
1507	comedi_udelay(1);
1508	if (inb(iobase + PCL818_MUX) != 0x00)
1509		return 1;	/* there isn't card */
1510	outb(0x55, iobase + PCL818_MUX);
1511	comedi_udelay(1);
1512	if (inb(iobase + PCL818_MUX) != 0x55)
1513		return 1;	/* there isn't card */
1514	outb(0x00, iobase + PCL818_MUX);
1515	comedi_udelay(1);
1516	outb(0x18, iobase + PCL818_CONTROL);
1517	comedi_udelay(1);
1518	if (inb(iobase + PCL818_CONTROL) != 0x18)
1519		return 1;	/* there isn't card */
1520	return 0;		/*  ok, card exist */
1521}
1522
1523/*
1524==============================================================================
1525 reset whole PCL-818 cards
1526*/
1527static void pcl818_reset(struct comedi_device * dev)
1528{
1529	if (devpriv->usefifo) {	/*  FIFO shutdown */
1530		outb(0, dev->iobase + PCL818_FI_INTCLR);
1531		outb(0, dev->iobase + PCL818_FI_FLUSH);
1532		outb(0, dev->iobase + PCL818_FI_ENABLE);
1533	}
1534	outb(0, dev->iobase + PCL818_DA_LO);	/*  DAC=0V */
1535	outb(0, dev->iobase + PCL818_DA_HI);
1536	comedi_udelay(1);
1537	outb(0, dev->iobase + PCL818_DO_HI);	/*  DO=$0000 */
1538	outb(0, dev->iobase + PCL818_DO_LO);
1539	comedi_udelay(1);
1540	outb(0, dev->iobase + PCL818_CONTROL);
1541	outb(0, dev->iobase + PCL818_CNTENABLE);
1542	outb(0, dev->iobase + PCL818_MUX);
1543	outb(0, dev->iobase + PCL818_CLRINT);
1544	outb(0xb0, dev->iobase + PCL818_CTRCTL);	/* Stop pacer */
1545	outb(0x70, dev->iobase + PCL818_CTRCTL);
1546	outb(0x30, dev->iobase + PCL818_CTRCTL);
1547	if (this_board->is_818) {
1548		outb(0, dev->iobase + PCL818_RANGE);
1549	} else {
1550		outb(0, dev->iobase + PCL718_DA2_LO);
1551		outb(0, dev->iobase + PCL718_DA2_HI);
1552	}
1553}
1554
1555#ifdef unused
1556/*
1557==============================================================================
1558  Enable(1)/disable(0) periodic interrupts from RTC
1559*/
1560static int set_rtc_irq_bit(unsigned char bit)
1561{
1562	unsigned char val;
1563	unsigned long flags;
1564
1565	if (bit == 1) {
1566		RTC_timer_lock++;
1567		if (RTC_timer_lock > 1)
1568			return 0;
1569	} else {
1570		RTC_timer_lock--;
1571		if (RTC_timer_lock < 0)
1572			RTC_timer_lock = 0;
1573		if (RTC_timer_lock > 0)
1574			return 0;
1575	}
1576
1577	save_flags(flags);
1578	cli();
1579	val = CMOS_READ(RTC_CONTROL);
1580	if (bit) {
1581		val |= RTC_PIE;
1582	} else {
1583		val &= ~RTC_PIE;
1584	}
1585	CMOS_WRITE(val, RTC_CONTROL);
1586	CMOS_READ(RTC_INTR_FLAGS);
1587	restore_flags(flags);
1588	return 0;
1589}
1590
1591/*
1592==============================================================================
1593  Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1594*/
1595static void rtc_dropped_irq(unsigned long data)
1596{
1597	struct comedi_device *dev = (void *)data;
1598	unsigned long flags, tmp;
1599
1600	switch (devpriv->int818_mode) {
1601	case INT_TYPE_AI1_DMA_RTC:
1602	case INT_TYPE_AI3_DMA_RTC:
1603		mod_timer(&devpriv->rtc_irq_timer,
1604			jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1605		save_flags(flags);
1606		cli();
1607		tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);	/* restart */
1608		restore_flags(flags);
1609		break;
1610	};
1611}
1612
1613/*
1614==============================================================================
1615  Set frequency of interrupts from RTC
1616*/
1617static int rtc_setfreq_irq(int freq)
1618{
1619	int tmp = 0;
1620	int rtc_freq;
1621	unsigned char val;
1622	unsigned long flags;
1623
1624	if (freq < 2)
1625		freq = 2;
1626	if (freq > 8192)
1627		freq = 8192;
1628
1629	while (freq > (1 << tmp))
1630		tmp++;
1631
1632	rtc_freq = 1 << tmp;
1633
1634	save_flags(flags);
1635	cli();
1636	val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1637	val |= (16 - tmp);
1638	CMOS_WRITE(val, RTC_FREQ_SELECT);
1639	restore_flags(flags);
1640	return rtc_freq;
1641}
1642#endif
1643
1644/*
1645==============================================================================
1646  Free any resources that we have claimed
1647*/
1648static void free_resources(struct comedi_device * dev)
1649{
1650	/* rt_printk("free_resource()\n"); */
1651	if (dev->private) {
1652		pcl818_ai_cancel(dev, devpriv->sub_ai);
1653		pcl818_reset(dev);
1654		if (devpriv->dma)
1655			free_dma(devpriv->dma);
1656		if (devpriv->dmabuf[0])
1657			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1658		if (devpriv->dmabuf[1])
1659			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1660#ifdef unused
1661		if (devpriv->rtc_irq)
1662			comedi_free_irq(devpriv->rtc_irq, dev);
1663		if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1664			if (devpriv->rtc_iobase)
1665				release_region(devpriv->rtc_iobase,
1666					devpriv->rtc_iosize);
1667		}
1668		if (devpriv->dma_rtc)
1669			RTC_lock--;
1670#endif
1671	}
1672
1673	if (dev->irq)
1674		free_irq(dev->irq, dev);
1675	if (dev->iobase)
1676		release_region(dev->iobase, devpriv->io_range);
1677	/* rt_printk("free_resource() end\n"); */
1678}
1679
1680/*
1681==============================================================================
1682
1683   Initialization
1684
1685*/
1686static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1687{
1688	int ret;
1689	unsigned long iobase;
1690	unsigned int irq, dma;
1691	unsigned long pages;
1692	struct comedi_subdevice *s;
1693
1694	if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
1695		return ret;	/* Can't alloc mem */
1696
1697	/* claim our I/O space */
1698	iobase = it->options[0];
1699	printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1700		dev->minor, this_board->name, iobase);
1701	devpriv->io_range = this_board->io_range;
1702	if ((this_board->fifo) && (it->options[2] == -1)) {	/*  we've board with FIFO and we want to use FIFO */
1703		devpriv->io_range = PCLx1xFIFO_RANGE;
1704		devpriv->usefifo = 1;
1705	}
1706	if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1707		rt_printk("I/O port conflict\n");
1708		return -EIO;
1709	}
1710
1711	dev->iobase = iobase;
1712
1713	if (pcl818_check(iobase)) {
1714		rt_printk(", I can't detect board. FAIL!\n");
1715		return -EIO;
1716	}
1717
1718	/* set up some name stuff */
1719	dev->board_name = this_board->name;
1720	/* grab our IRQ */
1721	irq = 0;
1722	if (this_board->IRQbits != 0) {	/* board support IRQ */
1723		irq = it->options[1];
1724		if (irq) {	/* we want to use IRQ */
1725			if (((1 << irq) & this_board->IRQbits) == 0) {
1726				rt_printk
1727					(", IRQ %u is out of allowed range, DISABLING IT",
1728					irq);
1729				irq = 0;	/* Bad IRQ */
1730			} else {
1731				if (comedi_request_irq(irq, interrupt_pcl818, 0,
1732						"pcl818", dev)) {
1733					rt_printk
1734						(", unable to allocate IRQ %u, DISABLING IT",
1735						irq);
1736					irq = 0;	/* Can't use IRQ */
1737				} else {
1738					rt_printk(", irq=%u", irq);
1739				}
1740			}
1741		}
1742	}
1743
1744	dev->irq = irq;
1745	if (irq) {
1746		devpriv->irq_free = 1;
1747	} /* 1=we have allocated irq */
1748	else {
1749		devpriv->irq_free = 0;
1750	}
1751	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
1752	devpriv->ai_mode = 0;	/* mode of irq */
1753
1754#ifdef unused
1755	/* grab RTC for DMA operations */
1756	devpriv->dma_rtc = 0;
1757	if (it->options[2] > 0) {	/*  we want to use DMA */
1758		if (RTC_lock == 0) {
1759			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1760					"pcl818 (RTC)"))
1761				goto no_rtc;
1762		}
1763		devpriv->rtc_iobase = RTC_PORT(0);
1764		devpriv->rtc_iosize = RTC_IO_EXTENT;
1765		RTC_lock++;
1766		if (!comedi_request_irq(RTC_IRQ,
1767				interrupt_pcl818_ai_mode13_dma_rtc, 0,
1768				"pcl818 DMA (RTC)", dev)) {
1769			devpriv->dma_rtc = 1;
1770			devpriv->rtc_irq = RTC_IRQ;
1771			rt_printk(", dma_irq=%u", devpriv->rtc_irq);
1772		} else {
1773			RTC_lock--;
1774			if (RTC_lock == 0) {
1775				if (devpriv->rtc_iobase)
1776					release_region(devpriv->rtc_iobase,
1777						devpriv->rtc_iosize);
1778			}
1779			devpriv->rtc_iobase = 0;
1780			devpriv->rtc_iosize = 0;
1781		}
1782	}
1783
1784      no_rtc:
1785#endif
1786	/* grab our DMA */
1787	dma = 0;
1788	devpriv->dma = dma;
1789	if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1790		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
1791	if (this_board->DMAbits != 0) {	/* board support DMA */
1792		dma = it->options[2];
1793		if (dma < 1)
1794			goto no_dma;	/* DMA disabled */
1795		if (((1 << dma) & this_board->DMAbits) == 0) {
1796			rt_printk(", DMA is out of allowed range, FAIL!\n");
1797			return -EINVAL;	/* Bad DMA */
1798		}
1799		ret = request_dma(dma, "pcl818");
1800		if (ret) {
1801			rt_printk(", unable to allocate DMA %u, FAIL!\n", dma);
1802			return -EBUSY;	/* DMA isn't free */
1803		}
1804		devpriv->dma = dma;
1805		rt_printk(", dma=%u", dma);
1806		pages = 2;	/* we need 16KB */
1807		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1808		if (!devpriv->dmabuf[0]) {
1809			rt_printk(", unable to allocate DMA buffer, FAIL!\n");
1810			/* maybe experiment with try_to_free_pages() will help .... */
1811			return -EBUSY;	/* no buffer :-( */
1812		}
1813		devpriv->dmapages[0] = pages;
1814		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1815		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1816		/* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1817		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
1818			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1819			if (!devpriv->dmabuf[1]) {
1820				rt_printk
1821					(", unable to allocate DMA buffer, FAIL!\n");
1822				return -EBUSY;
1823			}
1824			devpriv->dmapages[1] = pages;
1825			devpriv->hwdmaptr[1] =
1826				virt_to_bus((void *)devpriv->dmabuf[1]);
1827			devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1828		}
1829	}
1830
1831      no_dma:
1832
1833	if ((ret = alloc_subdevices(dev, 4)) < 0)
1834		return ret;
1835
1836	s = dev->subdevices + 0;
1837	if (!this_board->n_aichan_se) {
1838		s->type = COMEDI_SUBD_UNUSED;
1839	} else {
1840		s->type = COMEDI_SUBD_AI;
1841		devpriv->sub_ai = s;
1842		s->subdev_flags = SDF_READABLE;
1843		if (check_single_ended(dev->iobase)) {
1844			s->n_chan = this_board->n_aichan_se;
1845			s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1846			printk(", %dchans S.E. DAC", s->n_chan);
1847		} else {
1848			s->n_chan = this_board->n_aichan_diff;
1849			s->subdev_flags |= SDF_DIFF;
1850			printk(", %dchans DIFF DAC", s->n_chan);
1851		}
1852		s->maxdata = this_board->ai_maxdata;
1853		s->len_chanlist = s->n_chan;
1854		s->range_table = this_board->ai_range_type;
1855		s->cancel = pcl818_ai_cancel;
1856		s->insn_read = pcl818_ai_insn_read;
1857		if ((irq) || (devpriv->dma_rtc)) {
1858			dev->read_subdev = s;
1859			s->subdev_flags |= SDF_CMD_READ;
1860			s->do_cmdtest = ai_cmdtest;
1861			s->do_cmd = ai_cmd;
1862		}
1863		if (this_board->is_818) {
1864			if ((it->options[4] == 1) || (it->options[4] == 10))
1865				s->range_table = &range_pcl818l_h_ai;	/*  secondary range list jumper selectable */
1866		} else {
1867			switch (it->options[4]) {
1868			case 0:
1869				s->range_table = &range_bipolar10;
1870				break;
1871			case 1:
1872				s->range_table = &range_bipolar5;
1873				break;
1874			case 2:
1875				s->range_table = &range_bipolar2_5;
1876				break;
1877			case 3:
1878				s->range_table = &range718_bipolar1;
1879				break;
1880			case 4:
1881				s->range_table = &range718_bipolar0_5;
1882				break;
1883			case 6:
1884				s->range_table = &range_unipolar10;
1885				break;
1886			case 7:
1887				s->range_table = &range_unipolar5;
1888				break;
1889			case 8:
1890				s->range_table = &range718_unipolar2;
1891				break;
1892			case 9:
1893				s->range_table = &range718_unipolar1;
1894				break;
1895			default:
1896				s->range_table = &range_unknown;
1897				break;
1898			}
1899		}
1900	}
1901
1902	s = dev->subdevices + 1;
1903	if (!this_board->n_aochan) {
1904		s->type = COMEDI_SUBD_UNUSED;
1905	} else {
1906		s->type = COMEDI_SUBD_AO;
1907		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1908		s->n_chan = this_board->n_aochan;
1909		s->maxdata = this_board->ao_maxdata;
1910		s->len_chanlist = this_board->n_aochan;
1911		s->range_table = this_board->ao_range_type;
1912		s->insn_read = pcl818_ao_insn_read;
1913		s->insn_write = pcl818_ao_insn_write;
1914#ifdef unused
1915#ifdef PCL818_MODE13_AO
1916		if (irq) {
1917			s->trig[1] = pcl818_ao_mode1;
1918			s->trig[3] = pcl818_ao_mode3;
1919		}
1920#endif
1921#endif
1922		if (this_board->is_818) {
1923			if ((it->options[4] == 1) || (it->options[4] == 10))
1924				s->range_table = &range_unipolar10;
1925			if (it->options[4] == 2)
1926				s->range_table = &range_unknown;
1927		} else {
1928			if ((it->options[5] == 1) || (it->options[5] == 10))
1929				s->range_table = &range_unipolar10;
1930			if (it->options[5] == 2)
1931				s->range_table = &range_unknown;
1932		}
1933	}
1934
1935	s = dev->subdevices + 2;
1936	if (!this_board->n_dichan) {
1937		s->type = COMEDI_SUBD_UNUSED;
1938	} else {
1939		s->type = COMEDI_SUBD_DI;
1940		s->subdev_flags = SDF_READABLE;
1941		s->n_chan = this_board->n_dichan;
1942		s->maxdata = 1;
1943		s->len_chanlist = this_board->n_dichan;
1944		s->range_table = &range_digital;
1945		s->insn_bits = pcl818_di_insn_bits;
1946	}
1947
1948	s = dev->subdevices + 3;
1949	if (!this_board->n_dochan) {
1950		s->type = COMEDI_SUBD_UNUSED;
1951	} else {
1952		s->type = COMEDI_SUBD_DO;
1953		s->subdev_flags = SDF_WRITABLE;
1954		s->n_chan = this_board->n_dochan;
1955		s->maxdata = 1;
1956		s->len_chanlist = this_board->n_dochan;
1957		s->range_table = &range_digital;
1958		s->insn_bits = pcl818_do_insn_bits;
1959	}
1960
1961	/* select 1/10MHz oscilator */
1962	if ((it->options[3] == 0) || (it->options[3] == 10)) {
1963		devpriv->i8253_osc_base = 100;
1964	} else {
1965		devpriv->i8253_osc_base = 1000;
1966	}
1967
1968	/* max sampling speed */
1969	devpriv->ns_min = this_board->ns_min;
1970
1971	if (!this_board->is_818) {
1972		if ((it->options[6] == 1) || (it->options[6] == 100))
1973			devpriv->ns_min = 10000;	/* extended PCL718 to 100kHz DAC */
1974	}
1975
1976	pcl818_reset(dev);
1977
1978	rt_printk("\n");
1979
1980	return 0;
1981}
1982
1983/*
1984==============================================================================
1985  Removes device
1986 */
1987static int pcl818_detach(struct comedi_device * dev)
1988{
1989	/*   rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
1990	free_resources(dev);
1991	return 0;
1992}
1993