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