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