pcl818.c revision c3744138715045adb316284ee7a1e608f0278f6c
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)
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	if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
824		if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
825						devpriv->ai_act_scan > 0)) &&
826				(devpriv->ai_mode == INT_TYPE_AI1_DMA ||
827				 devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
828			/* The cleanup from ai_cancel() has been delayed
829			   until now because the card doesn't seem to like
830			   being reprogrammed while a DMA transfer is in
831			   progress.
832			 */
833			struct comedi_subdevice *s = dev->subdevices + 0;
834			devpriv->ai_act_scan = 0;
835			devpriv->neverending_ai = 0;
836			pcl818_ai_cancel(dev, s);
837		}
838
839		outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
840
841		return IRQ_HANDLED;
842	}
843
844	switch (devpriv->ai_mode) {
845	case INT_TYPE_AI1_DMA:
846	case INT_TYPE_AI3_DMA:
847		return interrupt_pcl818_ai_mode13_dma(irq, d);
848	case INT_TYPE_AI1_INT:
849	case INT_TYPE_AI3_INT:
850		return interrupt_pcl818_ai_mode13_int(irq, d);
851	case INT_TYPE_AI1_FIFO:
852	case INT_TYPE_AI3_FIFO:
853		return interrupt_pcl818_ai_mode13_fifo(irq, d);
854#ifdef PCL818_MODE13_AO
855	case INT_TYPE_AO1_INT:
856	case INT_TYPE_AO3_INT:
857		return interrupt_pcl818_ao_mode13_int(irq, d);
858#endif
859	default:
860		break;
861	}
862
863	outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
864
865	if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
866		|| (!devpriv->ai_mode)) {
867		comedi_error(dev, "bad IRQ!");
868		return IRQ_NONE;
869	}
870
871	comedi_error(dev, "IRQ from unknow source!");
872	return IRQ_NONE;
873}
874
875/*
876==============================================================================
877   ANALOG INPUT MODE 1 or 3 DMA , 818 cards
878*/
879static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
880	struct comedi_subdevice *s)
881{
882	unsigned int flags;
883	unsigned int bytes;
884
885	rt_printk("mode13dma_int, mode: %d\n", mode);
886	disable_dma(devpriv->dma);	/*  disable dma */
887	bytes = devpriv->hwdmasize[0];
888	if (!devpriv->neverending_ai) {
889		bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short);	/*  how many */
890		devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];	/*  how many DMA pages we must fiil */
891		devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];	/* on last dma transfer must be moved */
892		devpriv->dma_runs_to_end--;
893		if (devpriv->dma_runs_to_end >= 0)
894			bytes = devpriv->hwdmasize[0];
895	}
896
897	devpriv->next_dma_buf = 0;
898	set_dma_mode(devpriv->dma, DMA_MODE_READ);
899	flags = claim_dma_lock();
900	clear_dma_ff(devpriv->dma);
901	set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
902	set_dma_count(devpriv->dma, bytes);
903	release_dma_lock(flags);
904	enable_dma(devpriv->dma);
905
906	if (mode == 1) {
907		devpriv->ai_mode = INT_TYPE_AI1_DMA;
908		outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ+DMA */
909	} else {
910		devpriv->ai_mode = INT_TYPE_AI3_DMA;
911		outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ+DMA */
912	};
913}
914
915#ifdef unused
916/*
917==============================================================================
918   ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
919*/
920static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device *dev,
921	struct comedi_subdevice *s)
922{
923	unsigned int flags;
924	short *pole;
925
926	set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
927	flags = claim_dma_lock();
928	clear_dma_ff(devpriv->dma);
929	set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
930	set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
931	release_dma_lock(flags);
932	enable_dma(devpriv->dma);
933	devpriv->last_top_dma = 0;	/* devpriv->hwdmasize[0]; */
934	pole = (short *) devpriv->dmabuf[0];
935	devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
936	pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
937#ifdef unused
938	devpriv->rtc_freq = rtc_setfreq_irq(2048);
939	devpriv->rtc_irq_timer.expires =
940		jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
941	devpriv->rtc_irq_timer.data = (unsigned long)dev;
942	devpriv->rtc_irq_timer.function = rtc_dropped_irq;
943
944	add_timer(&devpriv->rtc_irq_timer);
945#endif
946
947	if (mode == 1) {
948		devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
949		outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+DMA */
950	} else {
951		devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
952		outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+DMA */
953	};
954}
955#endif
956
957/*
958==============================================================================
959   ANALOG INPUT MODE 1 or 3, 818 cards
960*/
961static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
962	struct comedi_subdevice *s)
963{
964	struct comedi_cmd *cmd = &s->async->cmd;
965	int divisor1, divisor2;
966	unsigned int seglen;
967
968	rt_printk("pcl818_ai_cmd_mode()\n");
969	if ((!dev->irq) && (!devpriv->dma_rtc)) {
970		comedi_error(dev, "IRQ not defined!");
971		return -EINVAL;
972	}
973
974	if (devpriv->irq_blocked)
975		return -EBUSY;
976
977	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
978
979	seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
980		devpriv->ai_n_chan);
981	if (seglen < 1)
982		return -EINVAL;
983	setup_channel_list(dev, s, devpriv->ai_chanlist,
984		devpriv->ai_n_chan, seglen);
985
986	comedi_udelay(1);
987
988	devpriv->ai_act_scan = devpriv->ai_scans;
989	devpriv->ai_act_chan = 0;
990	devpriv->irq_blocked = 1;
991	devpriv->irq_was_now_closed = 0;
992	devpriv->neverending_ai = 0;
993	devpriv->act_chanlist_pos = 0;
994	devpriv->dma_runs_to_end = 0;
995
996	if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
997		devpriv->neverending_ai = 1;	/* well, user want neverending */
998
999	if (mode == 1) {
1000		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1001			&divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST);
1002		if (divisor1 == 1) {	/* PCL718/818 crash if any divisor is set to 1 */
1003			divisor1 = 2;
1004			divisor2 /= 2;
1005		}
1006		if (divisor2 == 1) {
1007			divisor2 = 2;
1008			divisor1 /= 2;
1009		}
1010	}
1011
1012	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
1013
1014	switch (devpriv->dma) {
1015	case 1:		/*  DMA */
1016	case 3:
1017		if (devpriv->dma_rtc == 0) {
1018			pcl818_ai_mode13dma_int(mode, dev, s);
1019		}
1020#ifdef unused
1021		else {
1022			pcl818_ai_mode13dma_rtc(mode, dev, s);
1023		}
1024#else
1025		else {
1026			return -EINVAL;
1027		}
1028#endif
1029		break;
1030	case 0:
1031		if (!devpriv->usefifo) {
1032			/* IRQ */
1033			/* rt_printk("IRQ\n"); */
1034			if (mode == 1) {
1035				devpriv->ai_mode = INT_TYPE_AI1_INT;
1036				/* Pacer+IRQ */
1037				outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1038			} else {
1039				devpriv->ai_mode = INT_TYPE_AI3_INT;
1040				/* Ext trig+IRQ */
1041				outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1042			}
1043		} else {
1044			/* FIFO */
1045			/* enable FIFO */
1046			outb(1, dev->iobase + PCL818_FI_ENABLE);
1047			if (mode == 1) {
1048				devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1049				/* Pacer */
1050				outb(0x03, dev->iobase + PCL818_CONTROL);
1051			} else {
1052				devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1053				outb(0x02, dev->iobase + PCL818_CONTROL);
1054			}
1055		}
1056	}
1057
1058	start_pacer(dev, mode, divisor1, divisor2);
1059
1060#ifdef unused
1061	switch (devpriv->ai_mode) {
1062	case INT_TYPE_AI1_DMA_RTC:
1063	case INT_TYPE_AI3_DMA_RTC:
1064		set_rtc_irq_bit(1);	/* start RTC */
1065		break;
1066	}
1067#endif
1068	rt_printk("pcl818_ai_cmd_mode() end\n");
1069	return 0;
1070}
1071
1072#ifdef unused
1073/*
1074==============================================================================
1075   ANALOG OUTPUT MODE 1 or 3, 818 cards
1076*/
1077#ifdef PCL818_MODE13_AO
1078static int pcl818_ao_mode13(int mode, struct comedi_device *dev, struct comedi_subdevice *s,
1079	comedi_trig *it)
1080{
1081	int divisor1, divisor2;
1082
1083	if (!dev->irq) {
1084		comedi_error(dev, "IRQ not defined!");
1085		return -EINVAL;
1086	}
1087
1088	if (devpriv->irq_blocked)
1089		return -EBUSY;
1090
1091	start_pacer(dev, -1, 0, 0);	/*  stop pacer */
1092
1093	devpriv->int13_act_scan = it->n;
1094	devpriv->int13_act_chan = 0;
1095	devpriv->irq_blocked = 1;
1096	devpriv->irq_was_now_closed = 0;
1097	devpriv->neverending_ai = 0;
1098	devpriv->act_chanlist_pos = 0;
1099
1100	if (mode == 1) {
1101		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1102			&divisor2, &it->trigvar, TRIG_ROUND_NEAREST);
1103		if (divisor1 == 1) {	/* PCL818 crash if any divisor is set to 1 */
1104			divisor1 = 2;
1105			divisor2 /= 2;
1106		}
1107		if (divisor2 == 1) {
1108			divisor2 = 2;
1109			divisor1 /= 2;
1110		}
1111	}
1112
1113	outb(0, dev->iobase + PCL818_CNTENABLE);	/* enable pacer */
1114	if (mode == 1) {
1115		devpriv->int818_mode = INT_TYPE_AO1_INT;
1116		outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Pacer+IRQ */
1117	} else {
1118		devpriv->int818_mode = INT_TYPE_AO3_INT;
1119		outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);	/* Ext trig+IRQ */
1120	};
1121
1122	start_pacer(dev, mode, divisor1, divisor2);
1123
1124	return 0;
1125}
1126
1127/*
1128==============================================================================
1129   ANALOG OUTPUT MODE 1, 818 cards
1130*/
1131static int pcl818_ao_mode1(struct comedi_device *dev, struct comedi_subdevice *s,
1132	comedi_trig *it)
1133{
1134	return pcl818_ao_mode13(1, dev, s, it);
1135}
1136
1137/*
1138==============================================================================
1139   ANALOG OUTPUT MODE 3, 818 cards
1140*/
1141static int pcl818_ao_mode3(struct comedi_device *dev, struct comedi_subdevice *s,
1142	comedi_trig *it)
1143{
1144	return pcl818_ao_mode13(3, dev, s, it);
1145}
1146#endif
1147#endif
1148
1149/*
1150==============================================================================
1151 Start/stop pacer onboard pacer
1152*/
1153static void start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
1154	unsigned int divisor2)
1155{
1156	outb(0xb4, dev->iobase + PCL818_CTRCTL);
1157	outb(0x74, dev->iobase + PCL818_CTRCTL);
1158	comedi_udelay(1);
1159
1160	if (mode == 1) {
1161		outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1162		outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1163		outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1164		outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1165	}
1166}
1167
1168/*
1169==============================================================================
1170 Check if channel list from user is builded correctly
1171 If it's ok, then program scan/gain logic
1172*/
1173static int check_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
1174	unsigned int *chanlist, unsigned int n_chan)
1175{
1176	unsigned int chansegment[16];
1177	unsigned int i, nowmustbechan, seglen, segpos;
1178
1179	/* correct channel and range number check itself comedi/range.c */
1180	if (n_chan < 1) {
1181		comedi_error(dev, "range/channel list is empty!");
1182		return 0;
1183	}
1184
1185	if (n_chan > 1) {
1186		/*  first channel is everytime ok */
1187		chansegment[0] = chanlist[0];
1188		/*  build part of chanlist */
1189		for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1190
1191			/* rt_printk("%d. %d * %d\n",i,
1192			 * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1193
1194			/* we detect loop, this must by finish */
1195
1196			if (chanlist[0] == chanlist[i])
1197				break;
1198			nowmustbechan =
1199				(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1200			if (nowmustbechan != CR_CHAN(chanlist[i])) {	/*  channel list isn't continous :-( */
1201				rt_printk
1202					("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1203					dev->minor, i, CR_CHAN(chanlist[i]),
1204					nowmustbechan, CR_CHAN(chanlist[0]));
1205				return 0;
1206			}
1207			/*  well, this is next correct channel in list */
1208			chansegment[i] = chanlist[i];
1209		}
1210
1211		/*  check whole chanlist */
1212		for (i = 0, segpos = 0; i < n_chan; i++) {
1213			/* 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])); */
1214			if (chanlist[i] != chansegment[i % seglen]) {
1215				rt_printk
1216					("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1217					dev->minor, i, CR_CHAN(chansegment[i]),
1218					CR_RANGE(chansegment[i]),
1219					CR_AREF(chansegment[i]),
1220					CR_CHAN(chanlist[i % seglen]),
1221					CR_RANGE(chanlist[i % seglen]),
1222					CR_AREF(chansegment[i % seglen]));
1223				return 0;	/*  chan/gain list is strange */
1224			}
1225		}
1226	} else {
1227		seglen = 1;
1228	}
1229	rt_printk("check_channel_list: seglen %d\n", seglen);
1230	return seglen;
1231}
1232
1233static void setup_channel_list(struct comedi_device *dev, struct comedi_subdevice *s,
1234	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
1235{
1236	int i;
1237
1238	devpriv->act_chanlist_len = seglen;
1239	devpriv->act_chanlist_pos = 0;
1240
1241	for (i = 0; i < seglen; i++) {	/*  store range list to card */
1242		devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1243		outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);	/* select channel */
1244		outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);	/* select gain */
1245	}
1246
1247	comedi_udelay(1);
1248
1249	/* select channel interval to scan */
1250	outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1251				1] << 4), dev->iobase + PCL818_MUX);
1252}
1253
1254/*
1255==============================================================================
1256 Check if board is switched to SE (1) or DIFF(0) mode
1257*/
1258static int check_single_ended(unsigned int port)
1259{
1260	if (inb(port + PCL818_STATUS) & 0x20) {
1261		return 1;
1262	} else {
1263		return 0;
1264	}
1265}
1266
1267/*
1268==============================================================================
1269*/
1270static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1271	struct comedi_cmd *cmd)
1272{
1273	int err = 0;
1274	int tmp, divisor1, divisor2;
1275
1276	/* step 1: make sure trigger sources are trivially valid */
1277
1278	tmp = cmd->start_src;
1279	cmd->start_src &= TRIG_NOW;
1280	if (!cmd->start_src || tmp != cmd->start_src)
1281		err++;
1282
1283	tmp = cmd->scan_begin_src;
1284	cmd->scan_begin_src &= TRIG_FOLLOW;
1285	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1286		err++;
1287
1288	tmp = cmd->convert_src;
1289	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1290	if (!cmd->convert_src || tmp != cmd->convert_src)
1291		err++;
1292
1293	tmp = cmd->scan_end_src;
1294	cmd->scan_end_src &= TRIG_COUNT;
1295	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1296		err++;
1297
1298	tmp = cmd->stop_src;
1299	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1300	if (!cmd->stop_src || tmp != cmd->stop_src)
1301		err++;
1302
1303	if (err) {
1304		return 1;
1305	}
1306
1307	/* step 2: make sure trigger sources are unique and mutually compatible */
1308
1309	if (cmd->start_src != TRIG_NOW) {
1310		cmd->start_src = TRIG_NOW;
1311		err++;
1312	}
1313	if (cmd->scan_begin_src != TRIG_FOLLOW) {
1314		cmd->scan_begin_src = TRIG_FOLLOW;
1315		err++;
1316	}
1317	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1318		err++;
1319
1320	if (cmd->scan_end_src != TRIG_COUNT) {
1321		cmd->scan_end_src = TRIG_COUNT;
1322		err++;
1323	}
1324
1325	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1326		err++;
1327
1328	if (err) {
1329		return 2;
1330	}
1331
1332	/* step 3: make sure arguments are trivially compatible */
1333
1334	if (cmd->start_arg != 0) {
1335		cmd->start_arg = 0;
1336		err++;
1337	}
1338
1339	if (cmd->scan_begin_arg != 0) {
1340		cmd->scan_begin_arg = 0;
1341		err++;
1342	}
1343
1344	if (cmd->convert_src == TRIG_TIMER) {
1345		if (cmd->convert_arg < this_board->ns_min) {
1346			cmd->convert_arg = this_board->ns_min;
1347			err++;
1348		}
1349	} else {		/* TRIG_EXT */
1350		if (cmd->convert_arg != 0) {
1351			cmd->convert_arg = 0;
1352			err++;
1353		}
1354	}
1355
1356	if (!cmd->chanlist_len) {
1357		cmd->chanlist_len = 1;
1358		err++;
1359	}
1360	if (cmd->chanlist_len > s->n_chan) {
1361		cmd->chanlist_len = s->n_chan;
1362		err++;
1363	}
1364	if (cmd->scan_end_arg != cmd->chanlist_len) {
1365		cmd->scan_end_arg = cmd->chanlist_len;
1366		err++;
1367	}
1368	if (cmd->stop_src == TRIG_COUNT) {
1369		if (!cmd->stop_arg) {
1370			cmd->stop_arg = 1;
1371			err++;
1372		}
1373	} else {		/* TRIG_NONE */
1374		if (cmd->stop_arg != 0) {
1375			cmd->stop_arg = 0;
1376			err++;
1377		}
1378	}
1379
1380	if (err) {
1381		return 3;
1382	}
1383
1384	/* step 4: fix up any arguments */
1385
1386	if (cmd->convert_src == TRIG_TIMER) {
1387		tmp = cmd->convert_arg;
1388		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1389			&divisor2, &cmd->convert_arg,
1390			cmd->flags & TRIG_ROUND_MASK);
1391		if (cmd->convert_arg < this_board->ns_min)
1392			cmd->convert_arg = this_board->ns_min;
1393		if (tmp != cmd->convert_arg)
1394			err++;
1395	}
1396
1397	if (err) {
1398		return 4;
1399	}
1400
1401	/* step 5: complain about special chanlist considerations */
1402
1403	if (cmd->chanlist) {
1404		if (!check_channel_list(dev, s, cmd->chanlist,
1405				cmd->chanlist_len))
1406			return 5;	/*  incorrect channels list */
1407	}
1408
1409	return 0;
1410}
1411
1412/*
1413==============================================================================
1414*/
1415static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1416{
1417	struct comedi_cmd *cmd = &s->async->cmd;
1418	int retval;
1419
1420	rt_printk("pcl818_ai_cmd()\n");
1421	devpriv->ai_n_chan = cmd->chanlist_len;
1422	devpriv->ai_chanlist = cmd->chanlist;
1423	devpriv->ai_flags = cmd->flags;
1424	devpriv->ai_data_len = s->async->prealloc_bufsz;
1425	devpriv->ai_data = s->async->prealloc_buf;
1426	devpriv->ai_timer1 = 0;
1427	devpriv->ai_timer2 = 0;
1428
1429	if (cmd->stop_src == TRIG_COUNT) {
1430		devpriv->ai_scans = cmd->stop_arg;
1431	} else {
1432		devpriv->ai_scans = 0;
1433	}
1434
1435	if (cmd->scan_begin_src == TRIG_FOLLOW) {	/*  mode 1, 3 */
1436		if (cmd->convert_src == TRIG_TIMER) {	/*  mode 1 */
1437			devpriv->ai_timer1 = cmd->convert_arg;
1438			retval = pcl818_ai_cmd_mode(1, dev, s);
1439			rt_printk("pcl818_ai_cmd() end\n");
1440			return retval;
1441		}
1442		if (cmd->convert_src == TRIG_EXT) {	/*  mode 3 */
1443			return pcl818_ai_cmd_mode(3, dev, s);
1444		}
1445	}
1446
1447	return -1;
1448}
1449
1450/*
1451==============================================================================
1452 cancel any mode 1-4 AI
1453*/
1454static int pcl818_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1455{
1456	if (devpriv->irq_blocked > 0) {
1457		rt_printk("pcl818_ai_cancel()\n");
1458		devpriv->irq_was_now_closed = 1;
1459
1460		switch (devpriv->ai_mode) {
1461#ifdef unused
1462		case INT_TYPE_AI1_DMA_RTC:
1463		case INT_TYPE_AI3_DMA_RTC:
1464			set_rtc_irq_bit(0);	/*  stop RTC */
1465			del_timer(&devpriv->rtc_irq_timer);
1466#endif
1467		case INT_TYPE_AI1_DMA:
1468		case INT_TYPE_AI3_DMA:
1469			if (devpriv->neverending_ai ||
1470					(!devpriv->neverending_ai &&
1471					 devpriv->ai_act_scan > 0)) {
1472				/* wait for running dma transfer to end, do cleanup in interrupt */
1473				goto end;
1474			}
1475			disable_dma(devpriv->dma);
1476		case INT_TYPE_AI1_INT:
1477		case INT_TYPE_AI3_INT:
1478		case INT_TYPE_AI1_FIFO:
1479		case INT_TYPE_AI3_FIFO:
1480#ifdef PCL818_MODE13_AO
1481		case INT_TYPE_AO1_INT:
1482		case INT_TYPE_AO3_INT:
1483#endif
1484			outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1485			comedi_udelay(1);
1486			start_pacer(dev, -1, 0, 0);
1487			outb(0, dev->iobase + PCL818_AD_LO);
1488			inb(dev->iobase + PCL818_AD_LO);
1489			inb(dev->iobase + PCL818_AD_HI);
1490			outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
1491			outb(0, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1492			if (devpriv->usefifo) {	/*  FIFO shutdown */
1493				outb(0, dev->iobase + PCL818_FI_INTCLR);
1494				outb(0, dev->iobase + PCL818_FI_FLUSH);
1495				outb(0, dev->iobase + PCL818_FI_ENABLE);
1496			}
1497			devpriv->irq_blocked = 0;
1498			devpriv->last_int_sub = s;
1499			devpriv->neverending_ai = 0;
1500			devpriv->ai_mode = 0;
1501			devpriv->irq_was_now_closed = 0;
1502			break;
1503		}
1504	}
1505
1506      end:
1507	rt_printk("pcl818_ai_cancel() end\n");
1508	return 0;
1509}
1510
1511/*
1512==============================================================================
1513 chech for PCL818
1514*/
1515static int pcl818_check(unsigned long iobase)
1516{
1517	outb(0x00, iobase + PCL818_MUX);
1518	comedi_udelay(1);
1519	if (inb(iobase + PCL818_MUX) != 0x00)
1520		return 1;	/* there isn't card */
1521	outb(0x55, iobase + PCL818_MUX);
1522	comedi_udelay(1);
1523	if (inb(iobase + PCL818_MUX) != 0x55)
1524		return 1;	/* there isn't card */
1525	outb(0x00, iobase + PCL818_MUX);
1526	comedi_udelay(1);
1527	outb(0x18, iobase + PCL818_CONTROL);
1528	comedi_udelay(1);
1529	if (inb(iobase + PCL818_CONTROL) != 0x18)
1530		return 1;	/* there isn't card */
1531	return 0;		/*  ok, card exist */
1532}
1533
1534/*
1535==============================================================================
1536 reset whole PCL-818 cards
1537*/
1538static void pcl818_reset(struct comedi_device *dev)
1539{
1540	if (devpriv->usefifo) {	/*  FIFO shutdown */
1541		outb(0, dev->iobase + PCL818_FI_INTCLR);
1542		outb(0, dev->iobase + PCL818_FI_FLUSH);
1543		outb(0, dev->iobase + PCL818_FI_ENABLE);
1544	}
1545	outb(0, dev->iobase + PCL818_DA_LO);	/*  DAC=0V */
1546	outb(0, dev->iobase + PCL818_DA_HI);
1547	comedi_udelay(1);
1548	outb(0, dev->iobase + PCL818_DO_HI);	/*  DO=$0000 */
1549	outb(0, dev->iobase + PCL818_DO_LO);
1550	comedi_udelay(1);
1551	outb(0, dev->iobase + PCL818_CONTROL);
1552	outb(0, dev->iobase + PCL818_CNTENABLE);
1553	outb(0, dev->iobase + PCL818_MUX);
1554	outb(0, dev->iobase + PCL818_CLRINT);
1555	outb(0xb0, dev->iobase + PCL818_CTRCTL);	/* Stop pacer */
1556	outb(0x70, dev->iobase + PCL818_CTRCTL);
1557	outb(0x30, dev->iobase + PCL818_CTRCTL);
1558	if (this_board->is_818) {
1559		outb(0, dev->iobase + PCL818_RANGE);
1560	} else {
1561		outb(0, dev->iobase + PCL718_DA2_LO);
1562		outb(0, dev->iobase + PCL718_DA2_HI);
1563	}
1564}
1565
1566#ifdef unused
1567/*
1568==============================================================================
1569  Enable(1)/disable(0) periodic interrupts from RTC
1570*/
1571static int set_rtc_irq_bit(unsigned char bit)
1572{
1573	unsigned char val;
1574	unsigned long flags;
1575
1576	if (bit == 1) {
1577		RTC_timer_lock++;
1578		if (RTC_timer_lock > 1)
1579			return 0;
1580	} else {
1581		RTC_timer_lock--;
1582		if (RTC_timer_lock < 0)
1583			RTC_timer_lock = 0;
1584		if (RTC_timer_lock > 0)
1585			return 0;
1586	}
1587
1588	save_flags(flags);
1589	cli();
1590	val = CMOS_READ(RTC_CONTROL);
1591	if (bit) {
1592		val |= RTC_PIE;
1593	} else {
1594		val &= ~RTC_PIE;
1595	}
1596	CMOS_WRITE(val, RTC_CONTROL);
1597	CMOS_READ(RTC_INTR_FLAGS);
1598	restore_flags(flags);
1599	return 0;
1600}
1601
1602/*
1603==============================================================================
1604  Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1605*/
1606static void rtc_dropped_irq(unsigned long data)
1607{
1608	struct comedi_device *dev = (void *)data;
1609	unsigned long flags, tmp;
1610
1611	switch (devpriv->int818_mode) {
1612	case INT_TYPE_AI1_DMA_RTC:
1613	case INT_TYPE_AI3_DMA_RTC:
1614		mod_timer(&devpriv->rtc_irq_timer,
1615			jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1616		save_flags(flags);
1617		cli();
1618		tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);	/* restart */
1619		restore_flags(flags);
1620		break;
1621	};
1622}
1623
1624/*
1625==============================================================================
1626  Set frequency of interrupts from RTC
1627*/
1628static int rtc_setfreq_irq(int freq)
1629{
1630	int tmp = 0;
1631	int rtc_freq;
1632	unsigned char val;
1633	unsigned long flags;
1634
1635	if (freq < 2)
1636		freq = 2;
1637	if (freq > 8192)
1638		freq = 8192;
1639
1640	while (freq > (1 << tmp))
1641		tmp++;
1642
1643	rtc_freq = 1 << tmp;
1644
1645	save_flags(flags);
1646	cli();
1647	val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1648	val |= (16 - tmp);
1649	CMOS_WRITE(val, RTC_FREQ_SELECT);
1650	restore_flags(flags);
1651	return rtc_freq;
1652}
1653#endif
1654
1655/*
1656==============================================================================
1657  Free any resources that we have claimed
1658*/
1659static void free_resources(struct comedi_device *dev)
1660{
1661	/* rt_printk("free_resource()\n"); */
1662	if (dev->private) {
1663		pcl818_ai_cancel(dev, devpriv->sub_ai);
1664		pcl818_reset(dev);
1665		if (devpriv->dma)
1666			free_dma(devpriv->dma);
1667		if (devpriv->dmabuf[0])
1668			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1669		if (devpriv->dmabuf[1])
1670			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1671#ifdef unused
1672		if (devpriv->rtc_irq)
1673			comedi_free_irq(devpriv->rtc_irq, dev);
1674		if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1675			if (devpriv->rtc_iobase)
1676				release_region(devpriv->rtc_iobase,
1677					devpriv->rtc_iosize);
1678		}
1679		if (devpriv->dma_rtc)
1680			RTC_lock--;
1681#endif
1682	}
1683
1684	if (dev->irq)
1685		free_irq(dev->irq, dev);
1686	if (dev->iobase)
1687		release_region(dev->iobase, devpriv->io_range);
1688	/* rt_printk("free_resource() end\n"); */
1689}
1690
1691/*
1692==============================================================================
1693
1694   Initialization
1695
1696*/
1697static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1698{
1699	int ret;
1700	unsigned long iobase;
1701	unsigned int irq;
1702	int dma;
1703	unsigned long pages;
1704	struct comedi_subdevice *s;
1705
1706	ret = alloc_private(dev, sizeof(struct pcl818_private));
1707	if (ret < 0)
1708		return ret;	/* Can't alloc mem */
1709
1710	/* claim our I/O space */
1711	iobase = it->options[0];
1712	printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1713		dev->minor, this_board->name, iobase);
1714	devpriv->io_range = this_board->io_range;
1715	if ((this_board->fifo) && (it->options[2] == -1)) {	/*  we've board with FIFO and we want to use FIFO */
1716		devpriv->io_range = PCLx1xFIFO_RANGE;
1717		devpriv->usefifo = 1;
1718	}
1719	if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1720		rt_printk("I/O port conflict\n");
1721		return -EIO;
1722	}
1723
1724	dev->iobase = iobase;
1725
1726	if (pcl818_check(iobase)) {
1727		rt_printk(", I can't detect board. FAIL!\n");
1728		return -EIO;
1729	}
1730
1731	/* set up some name stuff */
1732	dev->board_name = this_board->name;
1733	/* grab our IRQ */
1734	irq = 0;
1735	if (this_board->IRQbits != 0) {	/* board support IRQ */
1736		irq = it->options[1];
1737		if (irq) {	/* we want to use IRQ */
1738			if (((1 << irq) & this_board->IRQbits) == 0) {
1739				rt_printk
1740					(", IRQ %u is out of allowed range, DISABLING IT",
1741					irq);
1742				irq = 0;	/* Bad IRQ */
1743			} else {
1744				if (comedi_request_irq(irq, interrupt_pcl818, 0,
1745						"pcl818", dev)) {
1746					rt_printk
1747						(", unable to allocate IRQ %u, DISABLING IT",
1748						irq);
1749					irq = 0;	/* Can't use IRQ */
1750				} else {
1751					rt_printk(", irq=%u", irq);
1752				}
1753			}
1754		}
1755	}
1756
1757	dev->irq = irq;
1758	if (irq) {
1759		devpriv->irq_free = 1;
1760	} /* 1=we have allocated irq */
1761	else {
1762		devpriv->irq_free = 0;
1763	}
1764	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
1765	devpriv->ai_mode = 0;	/* mode of irq */
1766
1767#ifdef unused
1768	/* grab RTC for DMA operations */
1769	devpriv->dma_rtc = 0;
1770	if (it->options[2] > 0) {	/*  we want to use DMA */
1771		if (RTC_lock == 0) {
1772			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1773					"pcl818 (RTC)"))
1774				goto no_rtc;
1775		}
1776		devpriv->rtc_iobase = RTC_PORT(0);
1777		devpriv->rtc_iosize = RTC_IO_EXTENT;
1778		RTC_lock++;
1779		if (!comedi_request_irq(RTC_IRQ,
1780				interrupt_pcl818_ai_mode13_dma_rtc, 0,
1781				"pcl818 DMA (RTC)", dev)) {
1782			devpriv->dma_rtc = 1;
1783			devpriv->rtc_irq = RTC_IRQ;
1784			rt_printk(", dma_irq=%u", devpriv->rtc_irq);
1785		} else {
1786			RTC_lock--;
1787			if (RTC_lock == 0) {
1788				if (devpriv->rtc_iobase)
1789					release_region(devpriv->rtc_iobase,
1790						devpriv->rtc_iosize);
1791			}
1792			devpriv->rtc_iobase = 0;
1793			devpriv->rtc_iosize = 0;
1794		}
1795	}
1796
1797      no_rtc:
1798#endif
1799	/* grab our DMA */
1800	dma = 0;
1801	devpriv->dma = dma;
1802	if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1803		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
1804	if (this_board->DMAbits != 0) {	/* board support DMA */
1805		dma = it->options[2];
1806		if (dma < 1)
1807			goto no_dma;	/* DMA disabled */
1808		if (((1 << dma) & this_board->DMAbits) == 0) {
1809			rt_printk(", DMA is out of allowed range, FAIL!\n");
1810			return -EINVAL;	/* Bad DMA */
1811		}
1812		ret = request_dma(dma, "pcl818");
1813		if (ret) {
1814			rt_printk(", unable to allocate DMA %u, FAIL!\n", dma);
1815			return -EBUSY;	/* DMA isn't free */
1816		}
1817		devpriv->dma = dma;
1818		rt_printk(", dma=%u", dma);
1819		pages = 2;	/* we need 16KB */
1820		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1821		if (!devpriv->dmabuf[0]) {
1822			rt_printk(", unable to allocate DMA buffer, FAIL!\n");
1823			/* maybe experiment with try_to_free_pages() will help .... */
1824			return -EBUSY;	/* no buffer :-( */
1825		}
1826		devpriv->dmapages[0] = pages;
1827		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1828		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1829		/* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1830		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
1831			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1832			if (!devpriv->dmabuf[1]) {
1833				rt_printk
1834					(", unable to allocate DMA buffer, FAIL!\n");
1835				return -EBUSY;
1836			}
1837			devpriv->dmapages[1] = pages;
1838			devpriv->hwdmaptr[1] =
1839				virt_to_bus((void *)devpriv->dmabuf[1]);
1840			devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1841		}
1842	}
1843
1844      no_dma:
1845
1846	ret = alloc_subdevices(dev, 4);
1847	if (ret < 0)
1848		return ret;
1849
1850	s = dev->subdevices + 0;
1851	if (!this_board->n_aichan_se) {
1852		s->type = COMEDI_SUBD_UNUSED;
1853	} else {
1854		s->type = COMEDI_SUBD_AI;
1855		devpriv->sub_ai = s;
1856		s->subdev_flags = SDF_READABLE;
1857		if (check_single_ended(dev->iobase)) {
1858			s->n_chan = this_board->n_aichan_se;
1859			s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1860			printk(", %dchans S.E. DAC", s->n_chan);
1861		} else {
1862			s->n_chan = this_board->n_aichan_diff;
1863			s->subdev_flags |= SDF_DIFF;
1864			printk(", %dchans DIFF DAC", s->n_chan);
1865		}
1866		s->maxdata = this_board->ai_maxdata;
1867		s->len_chanlist = s->n_chan;
1868		s->range_table = this_board->ai_range_type;
1869		s->cancel = pcl818_ai_cancel;
1870		s->insn_read = pcl818_ai_insn_read;
1871		if ((irq) || (devpriv->dma_rtc)) {
1872			dev->read_subdev = s;
1873			s->subdev_flags |= SDF_CMD_READ;
1874			s->do_cmdtest = ai_cmdtest;
1875			s->do_cmd = ai_cmd;
1876		}
1877		if (this_board->is_818) {
1878			if ((it->options[4] == 1) || (it->options[4] == 10))
1879				s->range_table = &range_pcl818l_h_ai;	/*  secondary range list jumper selectable */
1880		} else {
1881			switch (it->options[4]) {
1882			case 0:
1883				s->range_table = &range_bipolar10;
1884				break;
1885			case 1:
1886				s->range_table = &range_bipolar5;
1887				break;
1888			case 2:
1889				s->range_table = &range_bipolar2_5;
1890				break;
1891			case 3:
1892				s->range_table = &range718_bipolar1;
1893				break;
1894			case 4:
1895				s->range_table = &range718_bipolar0_5;
1896				break;
1897			case 6:
1898				s->range_table = &range_unipolar10;
1899				break;
1900			case 7:
1901				s->range_table = &range_unipolar5;
1902				break;
1903			case 8:
1904				s->range_table = &range718_unipolar2;
1905				break;
1906			case 9:
1907				s->range_table = &range718_unipolar1;
1908				break;
1909			default:
1910				s->range_table = &range_unknown;
1911				break;
1912			}
1913		}
1914	}
1915
1916	s = dev->subdevices + 1;
1917	if (!this_board->n_aochan) {
1918		s->type = COMEDI_SUBD_UNUSED;
1919	} else {
1920		s->type = COMEDI_SUBD_AO;
1921		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1922		s->n_chan = this_board->n_aochan;
1923		s->maxdata = this_board->ao_maxdata;
1924		s->len_chanlist = this_board->n_aochan;
1925		s->range_table = this_board->ao_range_type;
1926		s->insn_read = pcl818_ao_insn_read;
1927		s->insn_write = pcl818_ao_insn_write;
1928#ifdef unused
1929#ifdef PCL818_MODE13_AO
1930		if (irq) {
1931			s->trig[1] = pcl818_ao_mode1;
1932			s->trig[3] = pcl818_ao_mode3;
1933		}
1934#endif
1935#endif
1936		if (this_board->is_818) {
1937			if ((it->options[4] == 1) || (it->options[4] == 10))
1938				s->range_table = &range_unipolar10;
1939			if (it->options[4] == 2)
1940				s->range_table = &range_unknown;
1941		} else {
1942			if ((it->options[5] == 1) || (it->options[5] == 10))
1943				s->range_table = &range_unipolar10;
1944			if (it->options[5] == 2)
1945				s->range_table = &range_unknown;
1946		}
1947	}
1948
1949	s = dev->subdevices + 2;
1950	if (!this_board->n_dichan) {
1951		s->type = COMEDI_SUBD_UNUSED;
1952	} else {
1953		s->type = COMEDI_SUBD_DI;
1954		s->subdev_flags = SDF_READABLE;
1955		s->n_chan = this_board->n_dichan;
1956		s->maxdata = 1;
1957		s->len_chanlist = this_board->n_dichan;
1958		s->range_table = &range_digital;
1959		s->insn_bits = pcl818_di_insn_bits;
1960	}
1961
1962	s = dev->subdevices + 3;
1963	if (!this_board->n_dochan) {
1964		s->type = COMEDI_SUBD_UNUSED;
1965	} else {
1966		s->type = COMEDI_SUBD_DO;
1967		s->subdev_flags = SDF_WRITABLE;
1968		s->n_chan = this_board->n_dochan;
1969		s->maxdata = 1;
1970		s->len_chanlist = this_board->n_dochan;
1971		s->range_table = &range_digital;
1972		s->insn_bits = pcl818_do_insn_bits;
1973	}
1974
1975	/* select 1/10MHz oscilator */
1976	if ((it->options[3] == 0) || (it->options[3] == 10)) {
1977		devpriv->i8253_osc_base = 100;
1978	} else {
1979		devpriv->i8253_osc_base = 1000;
1980	}
1981
1982	/* max sampling speed */
1983	devpriv->ns_min = this_board->ns_min;
1984
1985	if (!this_board->is_818) {
1986		if ((it->options[6] == 1) || (it->options[6] == 100))
1987			devpriv->ns_min = 10000;	/* extended PCL718 to 100kHz DAC */
1988	}
1989
1990	pcl818_reset(dev);
1991
1992	rt_printk("\n");
1993
1994	return 0;
1995}
1996
1997/*
1998==============================================================================
1999  Removes device
2000 */
2001static int pcl818_detach(struct comedi_device *dev)
2002{
2003	/*   rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
2004	free_resources(dev);
2005	return 0;
2006}
2007