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