staging: comedi: pcl816: remove unused RTC dma support
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / comedi / drivers / pcl816.c
1 /*
2 comedi/drivers/pcl816.c
3
4 Author: Juan Grigera <juan@grigera.com.ar>
5 based on pcl818 by Michal Dobes <dobes@tesnet.cz> and bits of pcl812
6
7 hardware driver for Advantech cards:
8 card: PCL-816, PCL814B
9 driver: pcl816
10 */
11 /*
12 Driver: pcl816
13 Description: Advantech PCL-816 cards, PCL-814
14 Author: Juan Grigera <juan@grigera.com.ar>
15 Devices: [Advantech] PCL-816 (pcl816), PCL-814B (pcl814b)
16 Status: works
17 Updated: Tue, 2 Apr 2002 23:15:21 -0800
18
19 PCL 816 and 814B have 16 SE/DIFF ADCs, 16 DACs, 16 DI and 16 DO.
20 Differences are at resolution (16 vs 12 bits).
21
22 The driver support AI command mode, other subdevices not written.
23
24 Analog output and digital input and output are not supported.
25
26 Configuration Options:
27 [0] - IO Base
28 [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
29 [2] - DMA (0=disable, 1, 3)
30 [3] - 0, 10=10MHz clock for 8254
31 1= 1MHz clock for 8254
32
33 */
34
35 #include "../comedidev.h"
36
37 #include <linux/ioport.h>
38 #include <linux/gfp.h>
39 #include <linux/delay.h>
40 #include <linux/io.h>
41 #include <linux/interrupt.h>
42 #include <asm/dma.h>
43
44 #include "comedi_fc.h"
45 #include "8253.h"
46
47 #define DEBUG(x) x
48
49 /* boards constants */
50 /* IO space len */
51 #define PCLx1x_RANGE 16
52
53 /* #define outb(x,y) printk("OUTB(%x, 200+%d)\n", x,y-0x200); outb(x,y) */
54
55 /* INTEL 8254 counters */
56 #define PCL816_CTR0 4
57 #define PCL816_CTR1 5
58 #define PCL816_CTR2 6
59 /* R: counter read-back register W: counter control */
60 #define PCL816_CTRCTL 7
61
62 /* R: A/D high byte W: A/D range control */
63 #define PCL816_RANGE 9
64 /* W: clear INT request */
65 #define PCL816_CLRINT 10
66 /* R: next mux scan channel W: mux scan channel & range control pointer */
67 #define PCL816_MUX 11
68 /* R/W: operation control register */
69 #define PCL816_CONTROL 12
70
71 /* R: return status byte W: set DMA/IRQ */
72 #define PCL816_STATUS 13
73 #define PCL816_STATUS_DRDY_MASK 0x80
74
75 /* R: low byte of A/D W: soft A/D trigger */
76 #define PCL816_AD_LO 8
77 /* R: high byte of A/D W: A/D range control */
78 #define PCL816_AD_HI 9
79
80 /* type of interrupt handler */
81 #define INT_TYPE_AI1_INT 1
82 #define INT_TYPE_AI1_DMA 2
83 #define INT_TYPE_AI3_INT 4
84 #define INT_TYPE_AI3_DMA 5
85
86 #define MAGIC_DMA_WORD 0x5a5a
87
88 static const struct comedi_lrange range_pcl816 = { 8, {
89 BIP_RANGE(10),
90 BIP_RANGE(5),
91 BIP_RANGE(2.5),
92 BIP_RANGE(1.25),
93 UNI_RANGE(10),
94 UNI_RANGE(5),
95 UNI_RANGE(2.5),
96 UNI_RANGE(1.25),
97 }
98 };
99
100 struct pcl816_board {
101
102 const char *name; /* board name */
103 int n_ranges; /* len of range list */
104 int n_aichan; /* num of A/D chans in diferencial mode */
105 unsigned int ai_ns_min; /* minimal allowed delay between samples (in ns) */
106 int n_aochan; /* num of D/A chans */
107 int n_dichan; /* num of DI chans */
108 int n_dochan; /* num of DO chans */
109 const struct comedi_lrange *ai_range_type; /* default A/D rangelist */
110 const struct comedi_lrange *ao_range_type; /* default D/A rangelist */
111 unsigned int io_range; /* len of IO space */
112 unsigned int IRQbits; /* allowed interrupts */
113 unsigned int DMAbits; /* allowed DMA chans */
114 int ai_maxdata; /* maxdata for A/D */
115 int ao_maxdata; /* maxdata for D/A */
116 int ai_chanlist; /* allowed len of channel list A/D */
117 int ao_chanlist; /* allowed len of channel list D/A */
118 int i8254_osc_base; /* 1/frequency of on board oscilator in ns */
119 };
120
121 struct pcl816_private {
122
123 unsigned int dma; /* used DMA, 0=don't use DMA */
124 unsigned long dmabuf[2]; /* pointers to begin of DMA buffers */
125 unsigned int dmapages[2]; /* len of DMA buffers in PAGE_SIZEs */
126 unsigned int hwdmaptr[2]; /* hardware address of DMA buffers */
127 unsigned int hwdmasize[2]; /* len of DMA buffers in Bytes */
128 unsigned int dmasamplsize; /* size in samples hwdmasize[0]/2 */
129 int next_dma_buf; /* which DMA buffer will be used next round */
130 long dma_runs_to_end; /* how many we must permorm DMA transfer to end of record */
131 unsigned long last_dma_run; /* how many bytes we must transfer on last DMA page */
132
133 unsigned int ai_scans; /* len of scanlist */
134 unsigned char ai_neverending; /* if=1, then we do neverending record (you must use cancel()) */
135 int irq_free; /* 1=have allocated IRQ */
136 int irq_blocked; /* 1=IRQ now uses any subdev */
137 int irq_was_now_closed; /* when IRQ finish, there's stored int816_mode for last interrupt */
138 int int816_mode; /* who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
139 struct comedi_subdevice *last_int_sub; /* ptr to subdevice which now finish */
140 int ai_act_scan; /* how many scans we finished */
141 unsigned int ai_act_chanlist[16]; /* MUX setting for actual AI operations */
142 unsigned int ai_act_chanlist_len; /* how long is actual MUX list */
143 unsigned int ai_act_chanlist_pos; /* actual position in MUX list */
144 unsigned int ai_n_chan; /* how many channels per scan */
145 unsigned int ai_poll_ptr; /* how many sampes transfer poll */
146 struct comedi_subdevice *sub_ai; /* ptr to AI subdevice */
147 };
148
149 /*
150 ==============================================================================
151 */
152 static int check_channel_list(struct comedi_device *dev,
153 struct comedi_subdevice *s,
154 unsigned int *chanlist, unsigned int chanlen);
155 static void setup_channel_list(struct comedi_device *dev,
156 struct comedi_subdevice *s,
157 unsigned int *chanlist, unsigned int seglen);
158 static int pcl816_ai_cancel(struct comedi_device *dev,
159 struct comedi_subdevice *s);
160 static void start_pacer(struct comedi_device *dev, int mode,
161 unsigned int divisor1, unsigned int divisor2);
162
163 static int pcl816_ai_cmdtest(struct comedi_device *dev,
164 struct comedi_subdevice *s,
165 struct comedi_cmd *cmd);
166 static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
167
168 /*
169 ==============================================================================
170 ANALOG INPUT MODE0, 816 cards, slow version
171 */
172 static int pcl816_ai_insn_read(struct comedi_device *dev,
173 struct comedi_subdevice *s,
174 struct comedi_insn *insn, unsigned int *data)
175 {
176 int n;
177 int timeout;
178
179 DPRINTK("mode 0 analog input\n");
180 /* software trigger, DMA and INT off */
181 outb(0, dev->iobase + PCL816_CONTROL);
182 /* clear INT (conversion end) flag */
183 outb(0, dev->iobase + PCL816_CLRINT);
184
185 /* Set the input channel */
186 outb(CR_CHAN(insn->chanspec) & 0xf, dev->iobase + PCL816_MUX);
187 /* select gain */
188 outb(CR_RANGE(insn->chanspec), dev->iobase + PCL816_RANGE);
189
190 for (n = 0; n < insn->n; n++) {
191
192 outb(0, dev->iobase + PCL816_AD_LO); /* start conversion */
193
194 timeout = 100;
195 while (timeout--) {
196 if (!(inb(dev->iobase + PCL816_STATUS) &
197 PCL816_STATUS_DRDY_MASK)) {
198 /* return read value */
199 data[n] =
200 ((inb(dev->iobase +
201 PCL816_AD_HI) << 8) |
202 (inb(dev->iobase + PCL816_AD_LO)));
203 /* clear INT (conversion end) flag */
204 outb(0, dev->iobase + PCL816_CLRINT);
205 break;
206 }
207 udelay(1);
208 }
209 /* Return timeout error */
210 if (!timeout) {
211 comedi_error(dev, "A/D insn timeout\n");
212 data[0] = 0;
213 /* clear INT (conversion end) flag */
214 outb(0, dev->iobase + PCL816_CLRINT);
215 return -EIO;
216 }
217
218 }
219 return n;
220 }
221
222 /*
223 ==============================================================================
224 analog input interrupt mode 1 & 3, 818 cards
225 one sample per interrupt version
226 */
227 static irqreturn_t interrupt_pcl816_ai_mode13_int(int irq, void *d)
228 {
229 struct comedi_device *dev = d;
230 struct pcl816_private *devpriv = dev->private;
231 struct comedi_subdevice *s = &dev->subdevices[0];
232 int low, hi;
233 int timeout = 50; /* wait max 50us */
234
235 while (timeout--) {
236 if (!(inb(dev->iobase + PCL816_STATUS) &
237 PCL816_STATUS_DRDY_MASK))
238 break;
239 udelay(1);
240 }
241 if (!timeout) { /* timeout, bail error */
242 outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */
243 comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
244 pcl816_ai_cancel(dev, s);
245 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
246 comedi_event(dev, s);
247 return IRQ_HANDLED;
248
249 }
250
251 /* get the sample */
252 low = inb(dev->iobase + PCL816_AD_LO);
253 hi = inb(dev->iobase + PCL816_AD_HI);
254
255 comedi_buf_put(s->async, (hi << 8) | low);
256
257 outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */
258
259 if (++devpriv->ai_act_chanlist_pos >= devpriv->ai_act_chanlist_len)
260 devpriv->ai_act_chanlist_pos = 0;
261
262 s->async->cur_chan++;
263 if (s->async->cur_chan >= devpriv->ai_n_chan) {
264 s->async->cur_chan = 0;
265 devpriv->ai_act_scan++;
266 }
267
268 if (!devpriv->ai_neverending)
269 /* all data sampled */
270 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
271 /* all data sampled */
272 pcl816_ai_cancel(dev, s);
273 s->async->events |= COMEDI_CB_EOA;
274 }
275 comedi_event(dev, s);
276 return IRQ_HANDLED;
277 }
278
279 /*
280 ==============================================================================
281 analog input dma mode 1 & 3, 816 cards
282 */
283 static void transfer_from_dma_buf(struct comedi_device *dev,
284 struct comedi_subdevice *s, short *ptr,
285 unsigned int bufptr, unsigned int len)
286 {
287 struct pcl816_private *devpriv = dev->private;
288 int i;
289
290 s->async->events = 0;
291
292 for (i = 0; i < len; i++) {
293
294 comedi_buf_put(s->async, ptr[bufptr++]);
295
296 if (++devpriv->ai_act_chanlist_pos >=
297 devpriv->ai_act_chanlist_len) {
298 devpriv->ai_act_chanlist_pos = 0;
299 }
300
301 s->async->cur_chan++;
302 if (s->async->cur_chan >= devpriv->ai_n_chan) {
303 s->async->cur_chan = 0;
304 devpriv->ai_act_scan++;
305 }
306
307 if (!devpriv->ai_neverending)
308 /* all data sampled */
309 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
310 pcl816_ai_cancel(dev, s);
311 s->async->events |= COMEDI_CB_EOA;
312 s->async->events |= COMEDI_CB_BLOCK;
313 break;
314 }
315 }
316
317 comedi_event(dev, s);
318 }
319
320 static irqreturn_t interrupt_pcl816_ai_mode13_dma(int irq, void *d)
321 {
322 struct comedi_device *dev = d;
323 struct pcl816_private *devpriv = dev->private;
324 struct comedi_subdevice *s = &dev->subdevices[0];
325 int len, bufptr, this_dma_buf;
326 unsigned long dma_flags;
327 short *ptr;
328
329 disable_dma(devpriv->dma);
330 this_dma_buf = devpriv->next_dma_buf;
331
332 /* switch dma bufs */
333 if ((devpriv->dma_runs_to_end > -1) || devpriv->ai_neverending) {
334
335 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
336 set_dma_mode(devpriv->dma, DMA_MODE_READ);
337 dma_flags = claim_dma_lock();
338 /* clear_dma_ff (devpriv->dma); */
339 set_dma_addr(devpriv->dma,
340 devpriv->hwdmaptr[devpriv->next_dma_buf]);
341 if (devpriv->dma_runs_to_end) {
342 set_dma_count(devpriv->dma,
343 devpriv->hwdmasize[devpriv->
344 next_dma_buf]);
345 } else {
346 set_dma_count(devpriv->dma, devpriv->last_dma_run);
347 }
348 release_dma_lock(dma_flags);
349 enable_dma(devpriv->dma);
350 }
351
352 devpriv->dma_runs_to_end--;
353 outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */
354
355 ptr = (short *)devpriv->dmabuf[this_dma_buf];
356
357 len = (devpriv->hwdmasize[0] >> 1) - devpriv->ai_poll_ptr;
358 bufptr = devpriv->ai_poll_ptr;
359 devpriv->ai_poll_ptr = 0;
360
361 transfer_from_dma_buf(dev, s, ptr, bufptr, len);
362 return IRQ_HANDLED;
363 }
364
365 /*
366 ==============================================================================
367 INT procedure
368 */
369 static irqreturn_t interrupt_pcl816(int irq, void *d)
370 {
371 struct comedi_device *dev = d;
372 struct pcl816_private *devpriv = dev->private;
373
374 DPRINTK("<I>");
375
376 if (!dev->attached) {
377 comedi_error(dev, "premature interrupt");
378 return IRQ_HANDLED;
379 }
380
381 switch (devpriv->int816_mode) {
382 case INT_TYPE_AI1_DMA:
383 case INT_TYPE_AI3_DMA:
384 return interrupt_pcl816_ai_mode13_dma(irq, d);
385 case INT_TYPE_AI1_INT:
386 case INT_TYPE_AI3_INT:
387 return interrupt_pcl816_ai_mode13_int(irq, d);
388 }
389
390 outb(0, dev->iobase + PCL816_CLRINT); /* clear INT request */
391 if (!dev->irq || !devpriv->irq_free || !devpriv->irq_blocked ||
392 !devpriv->int816_mode) {
393 if (devpriv->irq_was_now_closed) {
394 devpriv->irq_was_now_closed = 0;
395 /* comedi_error(dev,"last IRQ.."); */
396 return IRQ_HANDLED;
397 }
398 comedi_error(dev, "bad IRQ!");
399 return IRQ_NONE;
400 }
401 comedi_error(dev, "IRQ from unknown source!");
402 return IRQ_NONE;
403 }
404
405 /*
406 ==============================================================================
407 COMMAND MODE
408 */
409 static void pcl816_cmdtest_out(int e, struct comedi_cmd *cmd)
410 {
411 printk(KERN_INFO "pcl816 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
412 cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
413 printk(KERN_INFO "pcl816 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
414 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
415 printk(KERN_INFO "pcl816 e=%d stopsrc=%x scanend=%x\n", e,
416 cmd->stop_src, cmd->scan_end_src);
417 printk(KERN_INFO "pcl816 e=%d stoparg=%d scanendarg=%d chanlistlen=%d\n",
418 e, cmd->stop_arg, cmd->scan_end_arg, cmd->chanlist_len);
419 }
420
421 /*
422 ==============================================================================
423 */
424 static int pcl816_ai_cmdtest(struct comedi_device *dev,
425 struct comedi_subdevice *s, struct comedi_cmd *cmd)
426 {
427 const struct pcl816_board *board = comedi_board(dev);
428 int err = 0;
429 int tmp, divisor1 = 0, divisor2 = 0;
430
431 DEBUG(printk(KERN_INFO "pcl816 pcl812_ai_cmdtest\n");
432 pcl816_cmdtest_out(-1, cmd);
433 );
434
435 /* Step 1 : check if triggers are trivially valid */
436
437 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
438 err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
439 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_EXT | TRIG_TIMER);
440 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
441 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
442
443 if (err)
444 return 1;
445
446 /* Step 2a : make sure trigger sources are unique */
447
448 err |= cfc_check_trigger_is_unique(cmd->convert_src);
449 err |= cfc_check_trigger_is_unique(cmd->stop_src);
450
451 /* Step 2b : and mutually compatible */
452
453 if (err)
454 return 2;
455
456
457 /* Step 3: check if arguments are trivially valid */
458
459 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
460 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
461
462 if (cmd->convert_src == TRIG_TIMER)
463 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
464 board->ai_ns_min);
465 else /* TRIG_EXT */
466 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
467
468 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
469
470 if (cmd->stop_src == TRIG_COUNT)
471 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
472 else /* TRIG_NONE */
473 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
474
475 if (err)
476 return 3;
477
478
479 /* step 4: fix up any arguments */
480 if (cmd->convert_src == TRIG_TIMER) {
481 tmp = cmd->convert_arg;
482 i8253_cascade_ns_to_timer(board->i8254_osc_base,
483 &divisor1, &divisor2,
484 &cmd->convert_arg,
485 cmd->flags & TRIG_ROUND_MASK);
486 if (cmd->convert_arg < board->ai_ns_min)
487 cmd->convert_arg = board->ai_ns_min;
488 if (tmp != cmd->convert_arg)
489 err++;
490 }
491
492 if (err)
493 return 4;
494
495
496 /* step 5: complain about special chanlist considerations */
497
498 if (cmd->chanlist) {
499 if (!check_channel_list(dev, s, cmd->chanlist,
500 cmd->chanlist_len))
501 return 5; /* incorrect channels list */
502 }
503
504 return 0;
505 }
506
507 static int pcl816_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
508 {
509 const struct pcl816_board *board = comedi_board(dev);
510 struct pcl816_private *devpriv = dev->private;
511 unsigned int divisor1 = 0, divisor2 = 0, dma_flags, bytes, dmairq;
512 struct comedi_cmd *cmd = &s->async->cmd;
513 unsigned int seglen;
514
515 if (cmd->start_src != TRIG_NOW)
516 return -EINVAL;
517 if (cmd->scan_begin_src != TRIG_FOLLOW)
518 return -EINVAL;
519 if (cmd->scan_end_src != TRIG_COUNT)
520 return -EINVAL;
521 if (cmd->scan_end_arg != cmd->chanlist_len)
522 return -EINVAL;
523 /* if(cmd->chanlist_len>MAX_CHANLIST_LEN) return -EINVAL; */
524 if (devpriv->irq_blocked)
525 return -EBUSY;
526
527 if (cmd->convert_src == TRIG_TIMER) {
528 if (cmd->convert_arg < board->ai_ns_min)
529 cmd->convert_arg = board->ai_ns_min;
530
531 i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
532 &divisor2, &cmd->convert_arg,
533 cmd->flags & TRIG_ROUND_MASK);
534
535 /* PCL816 crash if any divisor is set to 1 */
536 if (divisor1 == 1) {
537 divisor1 = 2;
538 divisor2 /= 2;
539 }
540 if (divisor2 == 1) {
541 divisor2 = 2;
542 divisor1 /= 2;
543 }
544 }
545
546 start_pacer(dev, -1, 0, 0); /* stop pacer */
547
548 seglen = check_channel_list(dev, s, cmd->chanlist, cmd->chanlist_len);
549 if (seglen < 1)
550 return -EINVAL;
551 setup_channel_list(dev, s, cmd->chanlist, seglen);
552 udelay(1);
553
554 devpriv->ai_n_chan = cmd->chanlist_len;
555 devpriv->ai_act_scan = 0;
556 s->async->cur_chan = 0;
557 devpriv->irq_blocked = 1;
558 devpriv->ai_poll_ptr = 0;
559 devpriv->irq_was_now_closed = 0;
560
561 if (cmd->stop_src == TRIG_COUNT) {
562 devpriv->ai_scans = cmd->stop_arg;
563 devpriv->ai_neverending = 0;
564 } else {
565 devpriv->ai_scans = 0;
566 devpriv->ai_neverending = 1;
567 }
568
569 /* don't we want wake up every scan? */
570 if ((cmd->flags & TRIG_WAKE_EOS)) {
571 printk(KERN_INFO
572 "pl816: You wankt WAKE_EOS but I dont want handle it");
573 /* devpriv->ai_eos=1; */
574 /* if (devpriv->ai_n_chan==1) */
575 /* devpriv->dma=0; // DMA is useless for this situation */
576 }
577
578 if (devpriv->dma) {
579 bytes = devpriv->hwdmasize[0];
580 if (!devpriv->ai_neverending) {
581 /* how many */
582 bytes = s->async->cmd.chanlist_len *
583 s->async->cmd.chanlist_len *
584 sizeof(short);
585
586 /* how many DMA pages we must fill */
587 devpriv->dma_runs_to_end = bytes /
588 devpriv->hwdmasize[0];
589
590 /* on last dma transfer must be moved */
591 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];
592 devpriv->dma_runs_to_end--;
593 if (devpriv->dma_runs_to_end >= 0)
594 bytes = devpriv->hwdmasize[0];
595 } else
596 devpriv->dma_runs_to_end = -1;
597
598 devpriv->next_dma_buf = 0;
599 set_dma_mode(devpriv->dma, DMA_MODE_READ);
600 dma_flags = claim_dma_lock();
601 clear_dma_ff(devpriv->dma);
602 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
603 set_dma_count(devpriv->dma, bytes);
604 release_dma_lock(dma_flags);
605 enable_dma(devpriv->dma);
606 }
607
608 start_pacer(dev, 1, divisor1, divisor2);
609 dmairq = ((devpriv->dma & 0x3) << 4) | (dev->irq & 0x7);
610
611 switch (cmd->convert_src) {
612 case TRIG_TIMER:
613 devpriv->int816_mode = INT_TYPE_AI1_DMA;
614
615 /* Pacer+IRQ+DMA */
616 outb(0x32, dev->iobase + PCL816_CONTROL);
617
618 /* write irq and DMA to card */
619 outb(dmairq, dev->iobase + PCL816_STATUS);
620 break;
621
622 default:
623 devpriv->int816_mode = INT_TYPE_AI3_DMA;
624
625 /* Ext trig+IRQ+DMA */
626 outb(0x34, dev->iobase + PCL816_CONTROL);
627
628 /* write irq to card */
629 outb(dmairq, dev->iobase + PCL816_STATUS);
630 break;
631 }
632
633 DPRINTK("pcl816 END: pcl812_ai_cmd()\n");
634 return 0;
635 }
636
637 static int pcl816_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
638 {
639 struct pcl816_private *devpriv = dev->private;
640 unsigned long flags;
641 unsigned int top1, top2, i;
642
643 if (!devpriv->dma)
644 return 0; /* poll is valid only for DMA transfer */
645
646 spin_lock_irqsave(&dev->spinlock, flags);
647
648 for (i = 0; i < 20; i++) {
649 top1 = get_dma_residue(devpriv->dma); /* where is now DMA */
650 top2 = get_dma_residue(devpriv->dma);
651 if (top1 == top2)
652 break;
653 }
654 if (top1 != top2) {
655 spin_unlock_irqrestore(&dev->spinlock, flags);
656 return 0;
657 }
658
659 /* where is now DMA in buffer */
660 top1 = devpriv->hwdmasize[0] - top1;
661 top1 >>= 1; /* sample position */
662 top2 = top1 - devpriv->ai_poll_ptr;
663 if (top2 < 1) { /* no new samples */
664 spin_unlock_irqrestore(&dev->spinlock, flags);
665 return 0;
666 }
667
668 transfer_from_dma_buf(dev, s,
669 (short *)devpriv->dmabuf[devpriv->next_dma_buf],
670 devpriv->ai_poll_ptr, top2);
671
672 devpriv->ai_poll_ptr = top1; /* new buffer position */
673 spin_unlock_irqrestore(&dev->spinlock, flags);
674
675 return s->async->buf_write_count - s->async->buf_read_count;
676 }
677
678 /*
679 ==============================================================================
680 cancel any mode 1-4 AI
681 */
682 static int pcl816_ai_cancel(struct comedi_device *dev,
683 struct comedi_subdevice *s)
684 {
685 struct pcl816_private *devpriv = dev->private;
686
687 /* DEBUG(printk("pcl816_ai_cancel()\n");) */
688
689 if (devpriv->irq_blocked > 0) {
690 switch (devpriv->int816_mode) {
691 case INT_TYPE_AI1_DMA:
692 case INT_TYPE_AI3_DMA:
693 disable_dma(devpriv->dma);
694 case INT_TYPE_AI1_INT:
695 case INT_TYPE_AI3_INT:
696 outb(inb(dev->iobase + PCL816_CONTROL) & 0x73,
697 dev->iobase + PCL816_CONTROL); /* Stop A/D */
698 udelay(1);
699 outb(0, dev->iobase + PCL816_CONTROL); /* Stop A/D */
700
701 /* Stop pacer */
702 outb(0xb0, dev->iobase + PCL816_CTRCTL);
703 outb(0x70, dev->iobase + PCL816_CTRCTL);
704 outb(0, dev->iobase + PCL816_AD_LO);
705 inb(dev->iobase + PCL816_AD_LO);
706 inb(dev->iobase + PCL816_AD_HI);
707
708 /* clear INT request */
709 outb(0, dev->iobase + PCL816_CLRINT);
710
711 /* Stop A/D */
712 outb(0, dev->iobase + PCL816_CONTROL);
713 devpriv->irq_blocked = 0;
714 devpriv->irq_was_now_closed = devpriv->int816_mode;
715 devpriv->int816_mode = 0;
716 devpriv->last_int_sub = s;
717 /* s->busy = 0; */
718 break;
719 }
720 }
721
722 DEBUG(printk("comedi: pcl816_ai_cancel() successful\n");)
723 return 0;
724 }
725
726 /*
727 ==============================================================================
728 chech for PCL816
729 */
730 static int pcl816_check(unsigned long iobase)
731 {
732 outb(0x00, iobase + PCL816_MUX);
733 udelay(1);
734 if (inb(iobase + PCL816_MUX) != 0x00)
735 return 1; /* there isn't card */
736 outb(0x55, iobase + PCL816_MUX);
737 udelay(1);
738 if (inb(iobase + PCL816_MUX) != 0x55)
739 return 1; /* there isn't card */
740 outb(0x00, iobase + PCL816_MUX);
741 udelay(1);
742 outb(0x18, iobase + PCL816_CONTROL);
743 udelay(1);
744 if (inb(iobase + PCL816_CONTROL) != 0x18)
745 return 1; /* there isn't card */
746 return 0; /* ok, card exist */
747 }
748
749 /*
750 ==============================================================================
751 reset whole PCL-816 cards
752 */
753 static void pcl816_reset(struct comedi_device *dev)
754 {
755 /* outb (0, dev->iobase + PCL818_DA_LO); DAC=0V */
756 /* outb (0, dev->iobase + PCL818_DA_HI); */
757 /* udelay (1); */
758 /* outb (0, dev->iobase + PCL818_DO_HI); DO=$0000 */
759 /* outb (0, dev->iobase + PCL818_DO_LO); */
760 /* udelay (1); */
761 outb(0, dev->iobase + PCL816_CONTROL);
762 outb(0, dev->iobase + PCL816_MUX);
763 outb(0, dev->iobase + PCL816_CLRINT);
764 outb(0xb0, dev->iobase + PCL816_CTRCTL); /* Stop pacer */
765 outb(0x70, dev->iobase + PCL816_CTRCTL);
766 outb(0x30, dev->iobase + PCL816_CTRCTL);
767 outb(0, dev->iobase + PCL816_RANGE);
768 }
769
770 /*
771 ==============================================================================
772 Start/stop pacer onboard pacer
773 */
774 static void
775 start_pacer(struct comedi_device *dev, int mode, unsigned int divisor1,
776 unsigned int divisor2)
777 {
778 outb(0x32, dev->iobase + PCL816_CTRCTL);
779 outb(0xff, dev->iobase + PCL816_CTR0);
780 outb(0x00, dev->iobase + PCL816_CTR0);
781 udelay(1);
782
783 /* set counter 2 as mode 3 */
784 outb(0xb4, dev->iobase + PCL816_CTRCTL);
785 /* set counter 1 as mode 3 */
786 outb(0x74, dev->iobase + PCL816_CTRCTL);
787 udelay(1);
788
789 if (mode == 1) {
790 DPRINTK("mode %d, divisor1 %d, divisor2 %d\n", mode, divisor1,
791 divisor2);
792 outb(divisor2 & 0xff, dev->iobase + PCL816_CTR2);
793 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL816_CTR2);
794 outb(divisor1 & 0xff, dev->iobase + PCL816_CTR1);
795 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL816_CTR1);
796 }
797
798 /* clear pending interrupts (just in case) */
799 /* outb(0, dev->iobase + PCL816_CLRINT); */
800 }
801
802 /*
803 ==============================================================================
804 Check if channel list from user is built correctly
805 If it's ok, then return non-zero length of repeated segment of channel list
806 */
807 static int
808 check_channel_list(struct comedi_device *dev,
809 struct comedi_subdevice *s, unsigned int *chanlist,
810 unsigned int chanlen)
811 {
812 unsigned int chansegment[16];
813 unsigned int i, nowmustbechan, seglen, segpos;
814
815 /* correct channel and range number check itself comedi/range.c */
816 if (chanlen < 1) {
817 comedi_error(dev, "range/channel list is empty!");
818 return 0;
819 }
820
821 if (chanlen > 1) {
822 /* first channel is every time ok */
823 chansegment[0] = chanlist[0];
824 for (i = 1, seglen = 1; i < chanlen; i++, seglen++) {
825 /* build part of chanlist */
826 DEBUG(printk(KERN_INFO "%d. %d %d\n", i,
827 CR_CHAN(chanlist[i]),
828 CR_RANGE(chanlist[i]));)
829
830 /* we detect loop, this must by finish */
831 if (chanlist[0] == chanlist[i])
832 break;
833 nowmustbechan =
834 (CR_CHAN(chansegment[i - 1]) + 1) % chanlen;
835 if (nowmustbechan != CR_CHAN(chanlist[i])) {
836 /* channel list isn't continuous :-( */
837 printk(KERN_WARNING
838 "comedi%d: pcl816: channel list must "
839 "be continuous! chanlist[%i]=%d but "
840 "must be %d or %d!\n", dev->minor,
841 i, CR_CHAN(chanlist[i]), nowmustbechan,
842 CR_CHAN(chanlist[0]));
843 return 0;
844 }
845 /* well, this is next correct channel in list */
846 chansegment[i] = chanlist[i];
847 }
848
849 /* check whole chanlist */
850 for (i = 0, segpos = 0; i < chanlen; i++) {
851 DEBUG(printk("%d %d=%d %d\n",
852 CR_CHAN(chansegment[i % seglen]),
853 CR_RANGE(chansegment[i % seglen]),
854 CR_CHAN(chanlist[i]),
855 CR_RANGE(chanlist[i]));)
856 if (chanlist[i] != chansegment[i % seglen]) {
857 printk(KERN_WARNING
858 "comedi%d: pcl816: bad channel or range"
859 " number! chanlist[%i]=%d,%d,%d and not"
860 " %d,%d,%d!\n", dev->minor, i,
861 CR_CHAN(chansegment[i]),
862 CR_RANGE(chansegment[i]),
863 CR_AREF(chansegment[i]),
864 CR_CHAN(chanlist[i % seglen]),
865 CR_RANGE(chanlist[i % seglen]),
866 CR_AREF(chansegment[i % seglen]));
867 return 0; /* chan/gain list is strange */
868 }
869 }
870 } else {
871 seglen = 1;
872 }
873
874 return seglen; /* we can serve this with MUX logic */
875 }
876
877 /*
878 ==============================================================================
879 Program scan/gain logic with channel list.
880 */
881 static void
882 setup_channel_list(struct comedi_device *dev,
883 struct comedi_subdevice *s, unsigned int *chanlist,
884 unsigned int seglen)
885 {
886 struct pcl816_private *devpriv = dev->private;
887 unsigned int i;
888
889 devpriv->ai_act_chanlist_len = seglen;
890 devpriv->ai_act_chanlist_pos = 0;
891
892 for (i = 0; i < seglen; i++) { /* store range list to card */
893 devpriv->ai_act_chanlist[i] = CR_CHAN(chanlist[i]);
894 outb(CR_CHAN(chanlist[0]) & 0xf, dev->iobase + PCL816_MUX);
895 /* select gain */
896 outb(CR_RANGE(chanlist[0]), dev->iobase + PCL816_RANGE);
897 }
898
899 udelay(1);
900 /* select channel interval to scan */
901 outb(devpriv->ai_act_chanlist[0] |
902 (devpriv->ai_act_chanlist[seglen - 1] << 4),
903 dev->iobase + PCL816_MUX);
904 }
905
906 static int pcl816_attach(struct comedi_device *dev, struct comedi_devconfig *it)
907 {
908 const struct pcl816_board *board = comedi_board(dev);
909 struct pcl816_private *devpriv;
910 int ret;
911 unsigned int irq, dma;
912 unsigned long pages;
913 /* int i; */
914 struct comedi_subdevice *s;
915
916 ret = comedi_request_region(dev, it->options[0], board->io_range);
917 if (ret)
918 return ret;
919
920 if (pcl816_check(dev->iobase)) {
921 printk(KERN_ERR ", I cann't detect board. FAIL!\n");
922 return -EIO;
923 }
924
925 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
926 if (!devpriv)
927 return -ENOMEM;
928 dev->private = devpriv;
929
930 /* grab our IRQ */
931 irq = 0;
932 if (board->IRQbits != 0) { /* board support IRQ */
933 irq = it->options[1];
934 if (irq) { /* we want to use IRQ */
935 if (((1 << irq) & board->IRQbits) == 0) {
936 printk
937 (", IRQ %u is out of allowed range, "
938 "DISABLING IT", irq);
939 irq = 0; /* Bad IRQ */
940 } else {
941 if (request_irq(irq, interrupt_pcl816, 0,
942 dev->board_name, dev)) {
943 printk
944 (", unable to allocate IRQ %u, "
945 "DISABLING IT", irq);
946 irq = 0; /* Can't use IRQ */
947 } else {
948 printk(KERN_INFO ", irq=%u", irq);
949 }
950 }
951 }
952 }
953
954 dev->irq = irq;
955 if (irq) /* 1=we have allocated irq */
956 devpriv->irq_free = 1;
957 else
958 devpriv->irq_free = 0;
959
960 devpriv->irq_blocked = 0; /* number of subdevice which use IRQ */
961 devpriv->int816_mode = 0; /* mode of irq */
962
963 /* grab our DMA */
964 dma = 0;
965 devpriv->dma = dma;
966 if (!devpriv->irq_free)
967 goto no_dma; /* if we haven't IRQ, we can't use DMA */
968
969 if (board->DMAbits != 0) { /* board support DMA */
970 dma = it->options[2];
971 if (dma < 1)
972 goto no_dma; /* DMA disabled */
973
974 if (((1 << dma) & board->DMAbits) == 0) {
975 printk(", DMA is out of allowed range, FAIL!\n");
976 return -EINVAL; /* Bad DMA */
977 }
978 ret = request_dma(dma, dev->board_name);
979 if (ret) {
980 printk(KERN_ERR
981 ", unable to allocate DMA %u, FAIL!\n", dma);
982 return -EBUSY; /* DMA isn't free */
983 }
984
985 devpriv->dma = dma;
986 printk(KERN_INFO ", dma=%u", dma);
987 pages = 2; /* we need 16KB */
988 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
989
990 if (!devpriv->dmabuf[0]) {
991 printk(", unable to allocate DMA buffer, FAIL!\n");
992 /*
993 * maybe experiment with try_to_free_pages()
994 * will help ....
995 */
996 return -EBUSY; /* no buffer :-( */
997 }
998 devpriv->dmapages[0] = pages;
999 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1000 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1001 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1002
1003 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1004 if (!devpriv->dmabuf[1]) {
1005 printk(KERN_ERR
1006 ", unable to allocate DMA buffer, "
1007 "FAIL!\n");
1008 return -EBUSY;
1009 }
1010 devpriv->dmapages[1] = pages;
1011 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1012 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1013 }
1014
1015 no_dma:
1016
1017 /* if (board->n_aochan > 0)
1018 subdevs[1] = COMEDI_SUBD_AO;
1019 if (board->n_dichan > 0)
1020 subdevs[2] = COMEDI_SUBD_DI;
1021 if (board->n_dochan > 0)
1022 subdevs[3] = COMEDI_SUBD_DO;
1023 */
1024
1025 ret = comedi_alloc_subdevices(dev, 1);
1026 if (ret)
1027 return ret;
1028
1029 s = &dev->subdevices[0];
1030 if (board->n_aichan > 0) {
1031 s->type = COMEDI_SUBD_AI;
1032 devpriv->sub_ai = s;
1033 dev->read_subdev = s;
1034 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1035 s->n_chan = board->n_aichan;
1036 s->subdev_flags |= SDF_DIFF;
1037 /* printk (", %dchans DIFF DAC - %d", s->n_chan, i); */
1038 s->maxdata = board->ai_maxdata;
1039 s->len_chanlist = board->ai_chanlist;
1040 s->range_table = board->ai_range_type;
1041 s->cancel = pcl816_ai_cancel;
1042 s->do_cmdtest = pcl816_ai_cmdtest;
1043 s->do_cmd = pcl816_ai_cmd;
1044 s->poll = pcl816_ai_poll;
1045 s->insn_read = pcl816_ai_insn_read;
1046 } else {
1047 s->type = COMEDI_SUBD_UNUSED;
1048 }
1049
1050 #if 0
1051 case COMEDI_SUBD_AO:
1052 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1053 s->n_chan = board->n_aochan;
1054 s->maxdata = board->ao_maxdata;
1055 s->len_chanlist = board->ao_chanlist;
1056 s->range_table = board->ao_range_type;
1057 break;
1058
1059 case COMEDI_SUBD_DI:
1060 s->subdev_flags = SDF_READABLE;
1061 s->n_chan = board->n_dichan;
1062 s->maxdata = 1;
1063 s->len_chanlist = board->n_dichan;
1064 s->range_table = &range_digital;
1065 break;
1066
1067 case COMEDI_SUBD_DO:
1068 s->subdev_flags = SDF_WRITABLE;
1069 s->n_chan = board->n_dochan;
1070 s->maxdata = 1;
1071 s->len_chanlist = board->n_dochan;
1072 s->range_table = &range_digital;
1073 break;
1074 #endif
1075
1076 pcl816_reset(dev);
1077
1078 printk("\n");
1079
1080 return 0;
1081 }
1082
1083 static void pcl816_detach(struct comedi_device *dev)
1084 {
1085 struct pcl816_private *devpriv = dev->private;
1086
1087 if (dev->private) {
1088 pcl816_ai_cancel(dev, devpriv->sub_ai);
1089 pcl816_reset(dev);
1090 if (devpriv->dma)
1091 free_dma(devpriv->dma);
1092 if (devpriv->dmabuf[0])
1093 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1094 if (devpriv->dmabuf[1])
1095 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1096 }
1097 comedi_legacy_detach(dev);
1098 }
1099
1100 static const struct pcl816_board boardtypes[] = {
1101 {"pcl816", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1102 &range_pcl816, PCLx1x_RANGE,
1103 0x00fc, /* IRQ mask */
1104 0x0a, /* DMA mask */
1105 0xffff, /* 16-bit card */
1106 0xffff, /* D/A maxdata */
1107 1024,
1108 1, /* ao chan list */
1109 100},
1110 {"pcl814b", 8, 16, 10000, 1, 16, 16, &range_pcl816,
1111 &range_pcl816, PCLx1x_RANGE,
1112 0x00fc,
1113 0x0a,
1114 0x3fff, /* 14 bit card */
1115 0x3fff,
1116 1024,
1117 1,
1118 100},
1119 };
1120
1121 static struct comedi_driver pcl816_driver = {
1122 .driver_name = "pcl816",
1123 .module = THIS_MODULE,
1124 .attach = pcl816_attach,
1125 .detach = pcl816_detach,
1126 .board_name = &boardtypes[0].name,
1127 .num_names = ARRAY_SIZE(boardtypes),
1128 .offset = sizeof(struct pcl816_board),
1129 };
1130 module_comedi_driver(pcl816_driver);
1131
1132 MODULE_AUTHOR("Comedi http://www.comedi.org");
1133 MODULE_DESCRIPTION("Comedi low-level driver");
1134 MODULE_LICENSE("GPL");