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 /*
11 Driver: pcl818
12 Description: Advantech PCL-818 cards, PCL-718
13 Author: Michal Dobes <dobes@tesnet.cz>
14 Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
15   PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
16   PCL-718 (pcl718)
17 Status: works
18 
19 All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
20 Differences are only at maximal sample speed, range list and FIFO
21 support.
22 The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
23 only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
24 PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
25 but this code is untested.
26 A word or two about DMA. Driver support DMA operations at two ways:
27 1) 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.
30 2) 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 
199 static 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 
212 static 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 
228 static 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 
236 static 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 
244 static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
245 static const struct comedi_lrange range718_bipolar0_5 =
246     { 1, {BIP_RANGE(0.5),} };
247 static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
248 static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
249 
250 static int pcl818_attach(struct comedi_device *dev,
251 			 struct comedi_devconfig *it);
252 static int pcl818_detach(struct comedi_device *dev);
253 
254 #ifdef unused
255 static int RTC_lock;	/* RTC lock */
256 static int RTC_timer_lock;	/* RTC int lock */
257 #endif
258 
259 struct 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 
280 static 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 
307 static 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 
driver_pcl818_init_module(void)317 static int __init driver_pcl818_init_module(void)
318 {
319 	return comedi_driver_register(&driver_pcl818);
320 }
321 
driver_pcl818_cleanup_module(void)322 static void __exit driver_pcl818_cleanup_module(void)
323 {
324 	comedi_driver_unregister(&driver_pcl818);
325 }
326 
327 module_init(driver_pcl818_init_module);
328 module_exit(driver_pcl818_cleanup_module);
329 
330 struct 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 
378 static 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 */
388 static 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);
392 static int check_channel_list(struct comedi_device *dev,
393 			      struct comedi_subdevice *s,
394 			      unsigned int *chanlist, unsigned int n_chan);
395 
396 static int pcl818_ai_cancel(struct comedi_device *dev,
397 			    struct comedi_subdevice *s);
398 static void start_pacer(struct comedi_device *dev, int mode,
399 			unsigned int divisor1, unsigned int divisor2);
400 
401 #ifdef unused
402 static int set_rtc_irq_bit(unsigned char bit);
403 static void rtc_dropped_irq(unsigned long data);
404 static int rtc_setfreq_irq(int freq);
405 #endif
406 
407 /*
408 ==============================================================================
409    ANALOG INPUT MODE0, 818 cards, slow version
410 */
pcl818_ai_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)411 static 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 
446 conv_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 */
pcl818_ao_insn_read(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)459 static 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 
pcl818_ao_insn_write(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)472 static 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 */
pcl818_di_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)496 static 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 */
pcl818_do_insn_bits(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_insn * insn,unsigned int * data)515 static 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 */
interrupt_pcl818_ai_mode13_int(int irq,void * d)538 static 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 
557 conv_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 */
interrupt_pcl818_ai_mode13_dma(int irq,void * d)597 static 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 */
interrupt_pcl818_ai_mode13_dma_rtc(int irq,void * d)676 static 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 */
interrupt_pcl818_ai_mode13_fifo(int irq,void * d)781 static 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 */
interrupt_pcl818(int irq,void * d)855 static 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 */
pcl818_ai_mode13dma_int(int mode,struct comedi_device * dev,struct comedi_subdevice * s)921 static 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 */
pcl818_ai_mode13dma_rtc(int mode,struct comedi_device * dev,struct comedi_subdevice * s)962 static 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 */
pcl818_ai_cmd_mode(int mode,struct comedi_device * dev,struct comedi_subdevice * s)1003 static 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
pcl818_ao_mode13(int mode,struct comedi_device * dev,struct comedi_subdevice * s,comedi_trig * it)1123 static 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 */
pcl818_ao_mode1(struct comedi_device * dev,struct comedi_subdevice * s,comedi_trig * it)1177 static 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 */
pcl818_ao_mode3(struct comedi_device * dev,struct comedi_subdevice * s,comedi_trig * it)1187 static 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 */
start_pacer(struct comedi_device * dev,int mode,unsigned int divisor1,unsigned int divisor2)1199 static 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 */
check_channel_list(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int * chanlist,unsigned int n_chan)1219 static 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 
setup_channel_list(struct comedi_device * dev,struct comedi_subdevice * s,unsigned int * chanlist,unsigned int n_chan,unsigned int seglen)1280 static 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 */
check_single_ended(unsigned int port)1308 static 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 */
ai_cmdtest(struct comedi_device * dev,struct comedi_subdevice * s,struct comedi_cmd * cmd)1318 static 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 */
ai_cmd(struct comedi_device * dev,struct comedi_subdevice * s)1451 static 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 */
pcl818_ai_cancel(struct comedi_device * dev,struct comedi_subdevice * s)1489 static 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 
1542 end:
1543 	dev_dbg(dev->hw_dev, "pcl818_ai_cancel() end\n");
1544 	return 0;
1545 }
1546 
1547 /*
1548 ==============================================================================
1549  chech for PCL818
1550 */
pcl818_check(unsigned long iobase)1551 static 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 */
pcl818_reset(struct comedi_device * dev)1574 static 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 */
set_rtc_irq_bit(unsigned char bit)1607 static 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 */
rtc_dropped_irq(unsigned long data)1642 static 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 */
rtc_setfreq_irq(int freq)1664 static 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 */
free_resources(struct comedi_device * dev)1695 static 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 */
pcl818_attach(struct comedi_device * dev,struct comedi_devconfig * it)1733 static 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 
1832 no_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(KERN_ERR "DMA is out of allowed range, FAIL!\n");
1845 			return -EINVAL;	/* Bad DMA */
1846 		}
1847 		ret = request_dma(dma, "pcl818");
1848 		if (ret)
1849 			return -EBUSY;	/* DMA isn't free */
1850 		devpriv->dma = dma;
1851 		pages = 2;	/* we need 16KB */
1852 		devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1853 		if (!devpriv->dmabuf[0])
1854 			/* maybe experiment with try_to_free_pages() will help .... */
1855 			return -EBUSY;	/* no buffer :-( */
1856 		devpriv->dmapages[0] = pages;
1857 		devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1858 		devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1859 		/* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1860 		if (devpriv->dma_rtc == 0) {	/*  we must do duble buff :-( */
1861 			devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1862 			if (!devpriv->dmabuf[1])
1863 				return -EBUSY;
1864 			devpriv->dmapages[1] = pages;
1865 			devpriv->hwdmaptr[1] =
1866 			    virt_to_bus((void *)devpriv->dmabuf[1]);
1867 			devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1868 		}
1869 	}
1870 
1871 no_dma:
1872 
1873 	ret = alloc_subdevices(dev, 4);
1874 	if (ret < 0)
1875 		return ret;
1876 
1877 	s = dev->subdevices + 0;
1878 	if (!this_board->n_aichan_se) {
1879 		s->type = COMEDI_SUBD_UNUSED;
1880 	} else {
1881 		s->type = COMEDI_SUBD_AI;
1882 		devpriv->sub_ai = s;
1883 		s->subdev_flags = SDF_READABLE;
1884 		if (check_single_ended(dev->iobase)) {
1885 			s->n_chan = this_board->n_aichan_se;
1886 			s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1887 			printk(", %dchans S.E. DAC", s->n_chan);
1888 		} else {
1889 			s->n_chan = this_board->n_aichan_diff;
1890 			s->subdev_flags |= SDF_DIFF;
1891 			printk(", %dchans DIFF DAC", s->n_chan);
1892 		}
1893 		s->maxdata = this_board->ai_maxdata;
1894 		s->len_chanlist = s->n_chan;
1895 		s->range_table = this_board->ai_range_type;
1896 		s->cancel = pcl818_ai_cancel;
1897 		s->insn_read = pcl818_ai_insn_read;
1898 		if ((irq) || (devpriv->dma_rtc)) {
1899 			dev->read_subdev = s;
1900 			s->subdev_flags |= SDF_CMD_READ;
1901 			s->do_cmdtest = ai_cmdtest;
1902 			s->do_cmd = ai_cmd;
1903 		}
1904 		if (this_board->is_818) {
1905 			if ((it->options[4] == 1) || (it->options[4] == 10))
1906 				s->range_table = &range_pcl818l_h_ai;	/*  secondary range list jumper selectable */
1907 		} else {
1908 			switch (it->options[4]) {
1909 			case 0:
1910 				s->range_table = &range_bipolar10;
1911 				break;
1912 			case 1:
1913 				s->range_table = &range_bipolar5;
1914 				break;
1915 			case 2:
1916 				s->range_table = &range_bipolar2_5;
1917 				break;
1918 			case 3:
1919 				s->range_table = &range718_bipolar1;
1920 				break;
1921 			case 4:
1922 				s->range_table = &range718_bipolar0_5;
1923 				break;
1924 			case 6:
1925 				s->range_table = &range_unipolar10;
1926 				break;
1927 			case 7:
1928 				s->range_table = &range_unipolar5;
1929 				break;
1930 			case 8:
1931 				s->range_table = &range718_unipolar2;
1932 				break;
1933 			case 9:
1934 				s->range_table = &range718_unipolar1;
1935 				break;
1936 			default:
1937 				s->range_table = &range_unknown;
1938 				break;
1939 			}
1940 		}
1941 	}
1942 
1943 	s = dev->subdevices + 1;
1944 	if (!this_board->n_aochan) {
1945 		s->type = COMEDI_SUBD_UNUSED;
1946 	} else {
1947 		s->type = COMEDI_SUBD_AO;
1948 		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1949 		s->n_chan = this_board->n_aochan;
1950 		s->maxdata = this_board->ao_maxdata;
1951 		s->len_chanlist = this_board->n_aochan;
1952 		s->range_table = this_board->ao_range_type;
1953 		s->insn_read = pcl818_ao_insn_read;
1954 		s->insn_write = pcl818_ao_insn_write;
1955 #ifdef unused
1956 #ifdef PCL818_MODE13_AO
1957 		if (irq) {
1958 			s->trig[1] = pcl818_ao_mode1;
1959 			s->trig[3] = pcl818_ao_mode3;
1960 		}
1961 #endif
1962 #endif
1963 		if (this_board->is_818) {
1964 			if ((it->options[4] == 1) || (it->options[4] == 10))
1965 				s->range_table = &range_unipolar10;
1966 			if (it->options[4] == 2)
1967 				s->range_table = &range_unknown;
1968 		} else {
1969 			if ((it->options[5] == 1) || (it->options[5] == 10))
1970 				s->range_table = &range_unipolar10;
1971 			if (it->options[5] == 2)
1972 				s->range_table = &range_unknown;
1973 		}
1974 	}
1975 
1976 	s = dev->subdevices + 2;
1977 	if (!this_board->n_dichan) {
1978 		s->type = COMEDI_SUBD_UNUSED;
1979 	} else {
1980 		s->type = COMEDI_SUBD_DI;
1981 		s->subdev_flags = SDF_READABLE;
1982 		s->n_chan = this_board->n_dichan;
1983 		s->maxdata = 1;
1984 		s->len_chanlist = this_board->n_dichan;
1985 		s->range_table = &range_digital;
1986 		s->insn_bits = pcl818_di_insn_bits;
1987 	}
1988 
1989 	s = dev->subdevices + 3;
1990 	if (!this_board->n_dochan) {
1991 		s->type = COMEDI_SUBD_UNUSED;
1992 	} else {
1993 		s->type = COMEDI_SUBD_DO;
1994 		s->subdev_flags = SDF_WRITABLE;
1995 		s->n_chan = this_board->n_dochan;
1996 		s->maxdata = 1;
1997 		s->len_chanlist = this_board->n_dochan;
1998 		s->range_table = &range_digital;
1999 		s->insn_bits = pcl818_do_insn_bits;
2000 	}
2001 
2002 	/* select 1/10MHz oscilator */
2003 	if ((it->options[3] == 0) || (it->options[3] == 10))
2004 		devpriv->i8253_osc_base = 100;
2005 	else
2006 		devpriv->i8253_osc_base = 1000;
2007 
2008 	/* max sampling speed */
2009 	devpriv->ns_min = this_board->ns_min;
2010 
2011 	if (!this_board->is_818) {
2012 		if ((it->options[6] == 1) || (it->options[6] == 100))
2013 			devpriv->ns_min = 10000;	/* extended PCL718 to 100kHz DAC */
2014 	}
2015 
2016 	pcl818_reset(dev);
2017 
2018 	printk("\n");
2019 
2020 	return 0;
2021 }
2022 
2023 /*
2024 ==============================================================================
2025   Removes device
2026  */
pcl818_detach(struct comedi_device * dev)2027 static int pcl818_detach(struct comedi_device *dev)
2028 {
2029 	/*   printk("comedi%d: pcl818: remove\n", dev->minor); */
2030 	free_resources(dev);
2031 	return 0;
2032 }
2033 
2034 MODULE_AUTHOR("Comedi http://www.comedi.org");
2035 MODULE_DESCRIPTION("Comedi low-level driver");
2036 MODULE_LICENSE("GPL");
2037