pcl818.c revision 087ea31bdabb0395f83223c153a0557136461a85
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			// rt_printk("%d. %d %d\n",i,CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));
1183			// we detect loop, this must by finish
1184			if (chanlist[0] == chanlist[i])
1185				break;
1186			nowmustbechan =
1187				(CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1188			if (nowmustbechan != CR_CHAN(chanlist[i])) {	// channel list isn't continous :-(
1189				rt_printk
1190					("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1191					dev->minor, i, CR_CHAN(chanlist[i]),
1192					nowmustbechan, CR_CHAN(chanlist[0]));
1193				return 0;
1194			}
1195			// well, this is next correct channel in list
1196			chansegment[i] = chanlist[i];
1197		}
1198
1199		// check whole chanlist
1200		for (i = 0, segpos = 0; i < n_chan; i++) {
1201			//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]));
1202			if (chanlist[i] != chansegment[i % seglen]) {
1203				rt_printk
1204					("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1205					dev->minor, i, CR_CHAN(chansegment[i]),
1206					CR_RANGE(chansegment[i]),
1207					CR_AREF(chansegment[i]),
1208					CR_CHAN(chanlist[i % seglen]),
1209					CR_RANGE(chanlist[i % seglen]),
1210					CR_AREF(chansegment[i % seglen]));
1211				return 0;	// chan/gain list is strange
1212			}
1213		}
1214	} else {
1215		seglen = 1;
1216	}
1217	rt_printk("check_channel_list: seglen %d\n", seglen);
1218	return seglen;
1219}
1220
1221static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1222	unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
1223{
1224	int i;
1225
1226	devpriv->act_chanlist_len = seglen;
1227	devpriv->act_chanlist_pos = 0;
1228
1229	for (i = 0; i < seglen; i++) {	// store range list to card
1230		devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1231		outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);	/* select channel */
1232		outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);	/* select gain */
1233	}
1234
1235	comedi_udelay(1);
1236
1237	/* select channel interval to scan */
1238	outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1239				1] << 4), dev->iobase + PCL818_MUX);
1240}
1241
1242/*
1243==============================================================================
1244 Check if board is switched to SE (1) or DIFF(0) mode
1245*/
1246static int check_single_ended(unsigned int port)
1247{
1248	if (inb(port + PCL818_STATUS) & 0x20) {
1249		return 1;
1250	} else {
1251		return 0;
1252	}
1253}
1254
1255/*
1256==============================================================================
1257*/
1258static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1259	struct comedi_cmd * cmd)
1260{
1261	int err = 0;
1262	int tmp, divisor1, divisor2;
1263
1264	/* step 1: make sure trigger sources are trivially valid */
1265
1266	tmp = cmd->start_src;
1267	cmd->start_src &= TRIG_NOW;
1268	if (!cmd->start_src || tmp != cmd->start_src)
1269		err++;
1270
1271	tmp = cmd->scan_begin_src;
1272	cmd->scan_begin_src &= TRIG_FOLLOW;
1273	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1274		err++;
1275
1276	tmp = cmd->convert_src;
1277	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1278	if (!cmd->convert_src || tmp != cmd->convert_src)
1279		err++;
1280
1281	tmp = cmd->scan_end_src;
1282	cmd->scan_end_src &= TRIG_COUNT;
1283	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1284		err++;
1285
1286	tmp = cmd->stop_src;
1287	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1288	if (!cmd->stop_src || tmp != cmd->stop_src)
1289		err++;
1290
1291	if (err) {
1292		return 1;
1293	}
1294
1295	/* step 2: make sure trigger sources are unique and mutually compatible */
1296
1297	if (cmd->start_src != TRIG_NOW) {
1298		cmd->start_src = TRIG_NOW;
1299		err++;
1300	}
1301	if (cmd->scan_begin_src != TRIG_FOLLOW) {
1302		cmd->scan_begin_src = TRIG_FOLLOW;
1303		err++;
1304	}
1305	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1306		err++;
1307
1308	if (cmd->scan_end_src != TRIG_COUNT) {
1309		cmd->scan_end_src = TRIG_COUNT;
1310		err++;
1311	}
1312
1313	if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1314		err++;
1315
1316	if (err) {
1317		return 2;
1318	}
1319
1320	/* step 3: make sure arguments are trivially compatible */
1321
1322	if (cmd->start_arg != 0) {
1323		cmd->start_arg = 0;
1324		err++;
1325	}
1326
1327	if (cmd->scan_begin_arg != 0) {
1328		cmd->scan_begin_arg = 0;
1329		err++;
1330	}
1331
1332	if (cmd->convert_src == TRIG_TIMER) {
1333		if (cmd->convert_arg < this_board->ns_min) {
1334			cmd->convert_arg = this_board->ns_min;
1335			err++;
1336		}
1337	} else {		/* TRIG_EXT */
1338		if (cmd->convert_arg != 0) {
1339			cmd->convert_arg = 0;
1340			err++;
1341		}
1342	}
1343
1344	if (!cmd->chanlist_len) {
1345		cmd->chanlist_len = 1;
1346		err++;
1347	}
1348	if (cmd->chanlist_len > s->n_chan) {
1349		cmd->chanlist_len = s->n_chan;
1350		err++;
1351	}
1352	if (cmd->scan_end_arg != cmd->chanlist_len) {
1353		cmd->scan_end_arg = cmd->chanlist_len;
1354		err++;
1355	}
1356	if (cmd->stop_src == TRIG_COUNT) {
1357		if (!cmd->stop_arg) {
1358			cmd->stop_arg = 1;
1359			err++;
1360		}
1361	} else {		/* TRIG_NONE */
1362		if (cmd->stop_arg != 0) {
1363			cmd->stop_arg = 0;
1364			err++;
1365		}
1366	}
1367
1368	if (err) {
1369		return 3;
1370	}
1371
1372	/* step 4: fix up any arguments */
1373
1374	if (cmd->convert_src == TRIG_TIMER) {
1375		tmp = cmd->convert_arg;
1376		i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1377			&divisor2, &cmd->convert_arg,
1378			cmd->flags & TRIG_ROUND_MASK);
1379		if (cmd->convert_arg < this_board->ns_min)
1380			cmd->convert_arg = this_board->ns_min;
1381		if (tmp != cmd->convert_arg)
1382			err++;
1383	}
1384
1385	if (err) {
1386		return 4;
1387	}
1388
1389	/* step 5: complain about special chanlist considerations */
1390
1391	if (cmd->chanlist) {
1392		if (!check_channel_list(dev, s, cmd->chanlist,
1393				cmd->chanlist_len))
1394			return 5;	// incorrect channels list
1395	}
1396
1397	return 0;
1398}
1399
1400/*
1401==============================================================================
1402*/
1403static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
1404{
1405	struct comedi_cmd *cmd = &s->async->cmd;
1406	int retval;
1407
1408	rt_printk("pcl818_ai_cmd()\n");
1409	devpriv->ai_n_chan = cmd->chanlist_len;
1410	devpriv->ai_chanlist = cmd->chanlist;
1411	devpriv->ai_flags = cmd->flags;
1412	devpriv->ai_data_len = s->async->prealloc_bufsz;
1413	devpriv->ai_data = s->async->prealloc_buf;
1414	devpriv->ai_timer1 = 0;
1415	devpriv->ai_timer2 = 0;
1416
1417	if (cmd->stop_src == TRIG_COUNT) {
1418		devpriv->ai_scans = cmd->stop_arg;
1419	} else {
1420		devpriv->ai_scans = 0;
1421	}
1422
1423	if (cmd->scan_begin_src == TRIG_FOLLOW) {	// mode 1, 3
1424		if (cmd->convert_src == TRIG_TIMER) {	// mode 1
1425			devpriv->ai_timer1 = cmd->convert_arg;
1426			retval = pcl818_ai_cmd_mode(1, dev, s);
1427			rt_printk("pcl818_ai_cmd() end\n");
1428			return retval;
1429		}
1430		if (cmd->convert_src == TRIG_EXT) {	// mode 3
1431			return pcl818_ai_cmd_mode(3, dev, s);
1432		}
1433	}
1434
1435	return -1;
1436}
1437
1438/*
1439==============================================================================
1440 cancel any mode 1-4 AI
1441*/
1442static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1443{
1444	if (devpriv->irq_blocked > 0) {
1445		rt_printk("pcl818_ai_cancel()\n");
1446		devpriv->irq_was_now_closed = devpriv->ai_mode;
1447		devpriv->ai_mode = 0;
1448
1449		switch (devpriv->irq_was_now_closed) {
1450#ifdef unused
1451		case INT_TYPE_AI1_DMA_RTC:
1452		case INT_TYPE_AI3_DMA_RTC:
1453			set_rtc_irq_bit(0);	// stop RTC
1454			del_timer(&devpriv->rtc_irq_timer);
1455#endif
1456		case INT_TYPE_AI1_DMA:
1457		case INT_TYPE_AI3_DMA:
1458			if (devpriv->neverending_ai) {
1459				/* wait for running dma transfer to end, do cleanup in interrupt */
1460				goto end;
1461			}
1462			disable_dma(devpriv->dma);
1463		case INT_TYPE_AI1_INT:
1464		case INT_TYPE_AI3_INT:
1465		case INT_TYPE_AI1_FIFO:
1466		case INT_TYPE_AI3_FIFO:
1467#ifdef PCL818_MODE13_AO
1468		case INT_TYPE_AO1_INT:
1469		case INT_TYPE_AO3_INT:
1470#endif
1471			outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1472			comedi_udelay(1);
1473			start_pacer(dev, -1, 0, 0);
1474			outb(0, dev->iobase + PCL818_AD_LO);
1475			inb(dev->iobase + PCL818_AD_LO);
1476			inb(dev->iobase + PCL818_AD_HI);
1477			outb(0, dev->iobase + PCL818_CLRINT);	/* clear INT request */
1478			outb(0, dev->iobase + PCL818_CONTROL);	/* Stop A/D */
1479			if (devpriv->usefifo) {	// FIFO shutdown
1480				outb(0, dev->iobase + PCL818_FI_INTCLR);
1481				outb(0, dev->iobase + PCL818_FI_FLUSH);
1482				outb(0, dev->iobase + PCL818_FI_ENABLE);
1483			}
1484			devpriv->irq_blocked = 0;
1485			devpriv->last_int_sub = s;
1486			devpriv->neverending_ai = 0;
1487			break;
1488		}
1489	}
1490
1491      end:
1492	rt_printk("pcl818_ai_cancel() end\n");
1493	return 0;
1494}
1495
1496/*
1497==============================================================================
1498 chech for PCL818
1499*/
1500static int pcl818_check(unsigned long iobase)
1501{
1502	outb(0x00, iobase + PCL818_MUX);
1503	comedi_udelay(1);
1504	if (inb(iobase + PCL818_MUX) != 0x00)
1505		return 1;	//there isn't card
1506	outb(0x55, iobase + PCL818_MUX);
1507	comedi_udelay(1);
1508	if (inb(iobase + PCL818_MUX) != 0x55)
1509		return 1;	//there isn't card
1510	outb(0x00, iobase + PCL818_MUX);
1511	comedi_udelay(1);
1512	outb(0x18, iobase + PCL818_CONTROL);
1513	comedi_udelay(1);
1514	if (inb(iobase + PCL818_CONTROL) != 0x18)
1515		return 1;	//there isn't card
1516	return 0;		// ok, card exist
1517}
1518
1519/*
1520==============================================================================
1521 reset whole PCL-818 cards
1522*/
1523static void pcl818_reset(struct comedi_device * dev)
1524{
1525	if (devpriv->usefifo) {	// FIFO shutdown
1526		outb(0, dev->iobase + PCL818_FI_INTCLR);
1527		outb(0, dev->iobase + PCL818_FI_FLUSH);
1528		outb(0, dev->iobase + PCL818_FI_ENABLE);
1529	}
1530	outb(0, dev->iobase + PCL818_DA_LO);	// DAC=0V
1531	outb(0, dev->iobase + PCL818_DA_HI);
1532	comedi_udelay(1);
1533	outb(0, dev->iobase + PCL818_DO_HI);	// DO=$0000
1534	outb(0, dev->iobase + PCL818_DO_LO);
1535	comedi_udelay(1);
1536	outb(0, dev->iobase + PCL818_CONTROL);
1537	outb(0, dev->iobase + PCL818_CNTENABLE);
1538	outb(0, dev->iobase + PCL818_MUX);
1539	outb(0, dev->iobase + PCL818_CLRINT);
1540	outb(0xb0, dev->iobase + PCL818_CTRCTL);	/* Stop pacer */
1541	outb(0x70, dev->iobase + PCL818_CTRCTL);
1542	outb(0x30, dev->iobase + PCL818_CTRCTL);
1543	if (this_board->is_818) {
1544		outb(0, dev->iobase + PCL818_RANGE);
1545	} else {
1546		outb(0, dev->iobase + PCL718_DA2_LO);
1547		outb(0, dev->iobase + PCL718_DA2_HI);
1548	}
1549}
1550
1551#ifdef unused
1552/*
1553==============================================================================
1554  Enable(1)/disable(0) periodic interrupts from RTC
1555*/
1556static int set_rtc_irq_bit(unsigned char bit)
1557{
1558	unsigned char val;
1559	unsigned long flags;
1560
1561	if (bit == 1) {
1562		RTC_timer_lock++;
1563		if (RTC_timer_lock > 1)
1564			return 0;
1565	} else {
1566		RTC_timer_lock--;
1567		if (RTC_timer_lock < 0)
1568			RTC_timer_lock = 0;
1569		if (RTC_timer_lock > 0)
1570			return 0;
1571	}
1572
1573	save_flags(flags);
1574	cli();
1575	val = CMOS_READ(RTC_CONTROL);
1576	if (bit) {
1577		val |= RTC_PIE;
1578	} else {
1579		val &= ~RTC_PIE;
1580	}
1581	CMOS_WRITE(val, RTC_CONTROL);
1582	CMOS_READ(RTC_INTR_FLAGS);
1583	restore_flags(flags);
1584	return 0;
1585}
1586
1587/*
1588==============================================================================
1589  Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1590*/
1591static void rtc_dropped_irq(unsigned long data)
1592{
1593	struct comedi_device *dev = (void *)data;
1594	unsigned long flags, tmp;
1595
1596	switch (devpriv->int818_mode) {
1597	case INT_TYPE_AI1_DMA_RTC:
1598	case INT_TYPE_AI3_DMA_RTC:
1599		mod_timer(&devpriv->rtc_irq_timer,
1600			jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1601		save_flags(flags);
1602		cli();
1603		tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);	/* restart */
1604		restore_flags(flags);
1605		break;
1606	};
1607}
1608
1609/*
1610==============================================================================
1611  Set frequency of interrupts from RTC
1612*/
1613static int rtc_setfreq_irq(int freq)
1614{
1615	int tmp = 0;
1616	int rtc_freq;
1617	unsigned char val;
1618	unsigned long flags;
1619
1620	if (freq < 2)
1621		freq = 2;
1622	if (freq > 8192)
1623		freq = 8192;
1624
1625	while (freq > (1 << tmp))
1626		tmp++;
1627
1628	rtc_freq = 1 << tmp;
1629
1630	save_flags(flags);
1631	cli();
1632	val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1633	val |= (16 - tmp);
1634	CMOS_WRITE(val, RTC_FREQ_SELECT);
1635	restore_flags(flags);
1636	return rtc_freq;
1637}
1638#endif
1639
1640/*
1641==============================================================================
1642  Free any resources that we have claimed
1643*/
1644static void free_resources(struct comedi_device * dev)
1645{
1646	//rt_printk("free_resource()\n");
1647	if (dev->private) {
1648		pcl818_ai_cancel(dev, devpriv->sub_ai);
1649		pcl818_reset(dev);
1650		if (devpriv->dma)
1651			free_dma(devpriv->dma);
1652		if (devpriv->dmabuf[0])
1653			free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1654		if (devpriv->dmabuf[1])
1655			free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1656#ifdef unused
1657		if (devpriv->rtc_irq)
1658			comedi_free_irq(devpriv->rtc_irq, dev);
1659		if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1660			if (devpriv->rtc_iobase)
1661				release_region(devpriv->rtc_iobase,
1662					devpriv->rtc_iosize);
1663		}
1664		if (devpriv->dma_rtc)
1665			RTC_lock--;
1666#endif
1667	}
1668
1669	if (dev->irq)
1670		free_irq(dev->irq, dev);
1671	if (dev->iobase)
1672		release_region(dev->iobase, devpriv->io_range);
1673	//rt_printk("free_resource() end\n");
1674}
1675
1676/*
1677==============================================================================
1678
1679   Initialization
1680
1681*/
1682static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1683{
1684	int ret;
1685	unsigned long iobase;
1686	unsigned int irq, dma;
1687	unsigned long pages;
1688	struct comedi_subdevice *s;
1689
1690	if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
1691		return ret;	/* Can't alloc mem */
1692
1693	/* claim our I/O space */
1694	iobase = it->options[0];
1695	printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1696		dev->minor, this_board->name, iobase);
1697	devpriv->io_range = this_board->io_range;
1698	if ((this_board->fifo) && (it->options[2] == -1)) {	// we've board with FIFO and we want to use FIFO
1699		devpriv->io_range = PCLx1xFIFO_RANGE;
1700		devpriv->usefifo = 1;
1701	}
1702	if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1703		rt_printk("I/O port conflict\n");
1704		return -EIO;
1705	}
1706
1707	dev->iobase = iobase;
1708
1709	if (pcl818_check(iobase)) {
1710		rt_printk(", I can't detect board. FAIL!\n");
1711		return -EIO;
1712	}
1713
1714	/* set up some name stuff */
1715	dev->board_name = this_board->name;
1716	/* grab our IRQ */
1717	irq = 0;
1718	if (this_board->IRQbits != 0) {	/* board support IRQ */
1719		irq = it->options[1];
1720		if (irq) {	/* we want to use IRQ */
1721			if (((1 << irq) & this_board->IRQbits) == 0) {
1722				rt_printk
1723					(", IRQ %u is out of allowed range, DISABLING IT",
1724					irq);
1725				irq = 0;	/* Bad IRQ */
1726			} else {
1727				if (comedi_request_irq(irq, interrupt_pcl818, 0,
1728						"pcl818", dev)) {
1729					rt_printk
1730						(", unable to allocate IRQ %u, DISABLING IT",
1731						irq);
1732					irq = 0;	/* Can't use IRQ */
1733				} else {
1734					rt_printk(", irq=%u", irq);
1735				}
1736			}
1737		}
1738	}
1739
1740	dev->irq = irq;
1741	if (irq) {
1742		devpriv->irq_free = 1;
1743	} /* 1=we have allocated irq */
1744	else {
1745		devpriv->irq_free = 0;
1746	}
1747	devpriv->irq_blocked = 0;	/* number of subdevice which use IRQ */
1748	devpriv->ai_mode = 0;	/* mode of irq */
1749
1750#ifdef unused
1751	/* grab RTC for DMA operations */
1752	devpriv->dma_rtc = 0;
1753	if (it->options[2] > 0) {	// we want to use DMA
1754		if (RTC_lock == 0) {
1755			if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1756					"pcl818 (RTC)"))
1757				goto no_rtc;
1758		}
1759		devpriv->rtc_iobase = RTC_PORT(0);
1760		devpriv->rtc_iosize = RTC_IO_EXTENT;
1761		RTC_lock++;
1762		if (!comedi_request_irq(RTC_IRQ,
1763				interrupt_pcl818_ai_mode13_dma_rtc, 0,
1764				"pcl818 DMA (RTC)", dev)) {
1765			devpriv->dma_rtc = 1;
1766			devpriv->rtc_irq = RTC_IRQ;
1767			rt_printk(", dma_irq=%u", devpriv->rtc_irq);
1768		} else {
1769			RTC_lock--;
1770			if (RTC_lock == 0) {
1771				if (devpriv->rtc_iobase)
1772					release_region(devpriv->rtc_iobase,
1773						devpriv->rtc_iosize);
1774			}
1775			devpriv->rtc_iobase = 0;
1776			devpriv->rtc_iosize = 0;
1777		}
1778	}
1779
1780      no_rtc:
1781#endif
1782	/* grab our DMA */
1783	dma = 0;
1784	devpriv->dma = dma;
1785	if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1786		goto no_dma;	/* if we haven't IRQ, we can't use DMA */
1787	if (this_board->DMAbits != 0) {	/* board support DMA */
1788		dma = it->options[2];
1789		if (dma < 1)
1790			goto no_dma;	/* DMA disabled */
1791		if (((1 << dma) & this_board->DMAbits) == 0) {
1792			rt_printk(", DMA is out of allowed range, FAIL!\n");
1793			return -EINVAL;	/* Bad DMA */
1794		}
1795		ret = request_dma(dma, "pcl818");
1796		if (ret) {
1797			rt_printk(", unable to allocate DMA %u, FAIL!\n", dma);
1798			return -EBUSY;	/* DMA isn't free */
1799		}
1800		devpriv->dma = dma;
1801		rt_printk(", dma=%u", dma);
1802		pages = 2;	/* we need 16KB */
1803		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1804		if (!devpriv->dmabuf[0]) {
1805			rt_printk(", unable to allocate DMA buffer, FAIL!\n");
1806			/* maybe experiment with try_to_free_pages() will help .... */
1807			return -EBUSY;	/* no buffer :-( */
1808		}
1809		devpriv->dmapages[0] = pages;
1810		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1811		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1812		//rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE);
1813		if (devpriv->dma_rtc == 0) {	// we must do duble buff :-(
1814			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1815			if (!devpriv->dmabuf[1]) {
1816				rt_printk
1817					(", unable to allocate DMA buffer, FAIL!\n");
1818				return -EBUSY;
1819			}
1820			devpriv->dmapages[1] = pages;
1821			devpriv->hwdmaptr[1] =
1822				virt_to_bus((void *)devpriv->dmabuf[1]);
1823			devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1824		}
1825	}
1826
1827      no_dma:
1828
1829	if ((ret = alloc_subdevices(dev, 4)) < 0)
1830		return ret;
1831
1832	s = dev->subdevices + 0;
1833	if (!this_board->n_aichan_se) {
1834		s->type = COMEDI_SUBD_UNUSED;
1835	} else {
1836		s->type = COMEDI_SUBD_AI;
1837		devpriv->sub_ai = s;
1838		s->subdev_flags = SDF_READABLE;
1839		if (check_single_ended(dev->iobase)) {
1840			s->n_chan = this_board->n_aichan_se;
1841			s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1842			printk(", %dchans S.E. DAC", s->n_chan);
1843		} else {
1844			s->n_chan = this_board->n_aichan_diff;
1845			s->subdev_flags |= SDF_DIFF;
1846			printk(", %dchans DIFF DAC", s->n_chan);
1847		}
1848		s->maxdata = this_board->ai_maxdata;
1849		s->len_chanlist = s->n_chan;
1850		s->range_table = this_board->ai_range_type;
1851		s->cancel = pcl818_ai_cancel;
1852		s->insn_read = pcl818_ai_insn_read;
1853		if ((irq) || (devpriv->dma_rtc)) {
1854			dev->read_subdev = s;
1855			s->subdev_flags |= SDF_CMD_READ;
1856			s->do_cmdtest = ai_cmdtest;
1857			s->do_cmd = ai_cmd;
1858		}
1859		if (this_board->is_818) {
1860			if ((it->options[4] == 1) || (it->options[4] == 10))
1861				s->range_table = &range_pcl818l_h_ai;	// secondary range list jumper selectable
1862		} else {
1863			switch (it->options[4]) {
1864			case 0:
1865				s->range_table = &range_bipolar10;
1866				break;
1867			case 1:
1868				s->range_table = &range_bipolar5;
1869				break;
1870			case 2:
1871				s->range_table = &range_bipolar2_5;
1872				break;
1873			case 3:
1874				s->range_table = &range718_bipolar1;
1875				break;
1876			case 4:
1877				s->range_table = &range718_bipolar0_5;
1878				break;
1879			case 6:
1880				s->range_table = &range_unipolar10;
1881				break;
1882			case 7:
1883				s->range_table = &range_unipolar5;
1884				break;
1885			case 8:
1886				s->range_table = &range718_unipolar2;
1887				break;
1888			case 9:
1889				s->range_table = &range718_unipolar1;
1890				break;
1891			default:
1892				s->range_table = &range_unknown;
1893				break;
1894			}
1895		}
1896	}
1897
1898	s = dev->subdevices + 1;
1899	if (!this_board->n_aochan) {
1900		s->type = COMEDI_SUBD_UNUSED;
1901	} else {
1902		s->type = COMEDI_SUBD_AO;
1903		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1904		s->n_chan = this_board->n_aochan;
1905		s->maxdata = this_board->ao_maxdata;
1906		s->len_chanlist = this_board->n_aochan;
1907		s->range_table = this_board->ao_range_type;
1908		s->insn_read = pcl818_ao_insn_read;
1909		s->insn_write = pcl818_ao_insn_write;
1910#ifdef unused
1911#ifdef PCL818_MODE13_AO
1912		if (irq) {
1913			s->trig[1] = pcl818_ao_mode1;
1914			s->trig[3] = pcl818_ao_mode3;
1915		}
1916#endif
1917#endif
1918		if (this_board->is_818) {
1919			if ((it->options[4] == 1) || (it->options[4] == 10))
1920				s->range_table = &range_unipolar10;
1921			if (it->options[4] == 2)
1922				s->range_table = &range_unknown;
1923		} else {
1924			if ((it->options[5] == 1) || (it->options[5] == 10))
1925				s->range_table = &range_unipolar10;
1926			if (it->options[5] == 2)
1927				s->range_table = &range_unknown;
1928		}
1929	}
1930
1931	s = dev->subdevices + 2;
1932	if (!this_board->n_dichan) {
1933		s->type = COMEDI_SUBD_UNUSED;
1934	} else {
1935		s->type = COMEDI_SUBD_DI;
1936		s->subdev_flags = SDF_READABLE;
1937		s->n_chan = this_board->n_dichan;
1938		s->maxdata = 1;
1939		s->len_chanlist = this_board->n_dichan;
1940		s->range_table = &range_digital;
1941		s->insn_bits = pcl818_di_insn_bits;
1942	}
1943
1944	s = dev->subdevices + 3;
1945	if (!this_board->n_dochan) {
1946		s->type = COMEDI_SUBD_UNUSED;
1947	} else {
1948		s->type = COMEDI_SUBD_DO;
1949		s->subdev_flags = SDF_WRITABLE;
1950		s->n_chan = this_board->n_dochan;
1951		s->maxdata = 1;
1952		s->len_chanlist = this_board->n_dochan;
1953		s->range_table = &range_digital;
1954		s->insn_bits = pcl818_do_insn_bits;
1955	}
1956
1957	/* select 1/10MHz oscilator */
1958	if ((it->options[3] == 0) || (it->options[3] == 10)) {
1959		devpriv->i8253_osc_base = 100;
1960	} else {
1961		devpriv->i8253_osc_base = 1000;
1962	}
1963
1964	/* max sampling speed */
1965	devpriv->ns_min = this_board->ns_min;
1966
1967	if (!this_board->is_818) {
1968		if ((it->options[6] == 1) || (it->options[6] == 100))
1969			devpriv->ns_min = 10000;	/* extended PCL718 to 100kHz DAC */
1970	}
1971
1972	pcl818_reset(dev);
1973
1974	rt_printk("\n");
1975
1976	return 0;
1977}
1978
1979/*
1980==============================================================================
1981  Removes device
1982 */
1983static int pcl818_detach(struct comedi_device * dev)
1984{
1985	//  rt_printk("comedi%d: pcl818: remove\n", dev->minor);
1986	free_resources(dev);
1987	return 0;
1988}
1989