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