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