staging: comedi: propogate error code from comedi_alloc_subdevices
[deliverable/linux.git] / drivers / staging / comedi / drivers / pcl812.c
1 /*
2 * comedi/drivers/pcl812.c
3 *
4 * Author: Michal Dobes <dobes@tesnet.cz>
5 *
6 * hardware driver for Advantech cards
7 * card: PCL-812, PCL-812PG, PCL-813, PCL-813B
8 * driver: pcl812, pcl812pg, pcl813, pcl813b
9 * and for ADlink cards
10 * card: ACL-8112DG, ACL-8112HG, ACL-8112PG, ACL-8113, ACL-8216
11 * driver: acl8112dg, acl8112hg, acl8112pg, acl8113, acl8216
12 * and for ICP DAS cards
13 * card: ISO-813, A-821PGH, A-821PGL, A-821PGL-NDA, A-822PGH, A-822PGL,
14 * driver: iso813, a821pgh, a-821pgl, a-821pglnda, a822pgh, a822pgl,
15 * card: A-823PGH, A-823PGL, A-826PG
16 * driver: a823pgh, a823pgl, a826pg
17 */
18
19 /*
20 * Driver: pcl812
21 * Description: Advantech PCL-812/PG, PCL-813/B,
22 * ADLink ACL-8112DG/HG/PG, ACL-8113, ACL-8216,
23 * ICP DAS A-821PGH/PGL/PGL-NDA, A-822PGH/PGL, A-823PGH/PGL, A-826PG,
24 * ICP DAS ISO-813
25 * Author: Michal Dobes <dobes@tesnet.cz>
26 * Devices: [Advantech] PCL-812 (pcl812), PCL-812PG (pcl812pg),
27 * PCL-813 (pcl813), PCL-813B (pcl813b), [ADLink] ACL-8112DG (acl8112dg),
28 * ACL-8112HG (acl8112hg), ACL-8113 (acl-8113), ACL-8216 (acl8216),
29 * [ICP] ISO-813 (iso813), A-821PGH (a821pgh), A-821PGL (a821pgl),
30 * A-821PGL-NDA (a821pclnda), A-822PGH (a822pgh), A-822PGL (a822pgl),
31 * A-823PGH (a823pgh), A-823PGL (a823pgl), A-826PG (a826pg)
32 * Updated: Mon, 06 Aug 2007 12:03:15 +0100
33 * Status: works (I hope. My board fire up under my hands
34 * and I cann't test all features.)
35 *
36 * This driver supports insn and cmd interfaces. Some boards support only insn
37 * because their hardware don't allow more (PCL-813/B, ACL-8113, ISO-813).
38 * Data transfer over DMA is supported only when you measure only one
39 * channel, this is too hardware limitation of these boards.
40 *
41 * Options for PCL-812:
42 * [0] - IO Base
43 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
44 * [2] - DMA (0=disable, 1, 3)
45 * [3] - 0=trigger source is internal 8253 with 2MHz clock
46 * 1=trigger source is external
47 * [4] - 0=A/D input range is +/-10V
48 * 1=A/D input range is +/-5V
49 * 2=A/D input range is +/-2.5V
50 * 3=A/D input range is +/-1.25V
51 * 4=A/D input range is +/-0.625V
52 * 5=A/D input range is +/-0.3125V
53 * [5] - 0=D/A outputs 0-5V (internal reference -5V)
54 * 1=D/A outputs 0-10V (internal reference -10V)
55 * 2=D/A outputs unknown (external reference)
56 *
57 * Options for PCL-812PG, ACL-8112PG:
58 * [0] - IO Base
59 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
60 * [2] - DMA (0=disable, 1, 3)
61 * [3] - 0=trigger source is internal 8253 with 2MHz clock
62 * 1=trigger source is external
63 * [4] - 0=A/D have max +/-5V input
64 * 1=A/D have max +/-10V input
65 * [5] - 0=D/A outputs 0-5V (internal reference -5V)
66 * 1=D/A outputs 0-10V (internal reference -10V)
67 * 2=D/A outputs unknown (external reference)
68 *
69 * Options for ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH, ACL-8216, A-826PG:
70 * [0] - IO Base
71 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7; 10, 11, 12, 14, 15)
72 * [2] - DMA (0=disable, 1, 3)
73 * [3] - 0=trigger source is internal 8253 with 2MHz clock
74 * 1=trigger source is external
75 * [4] - 0=A/D channels are S.E.
76 * 1=A/D channels are DIFF
77 * [5] - 0=D/A outputs 0-5V (internal reference -5V)
78 * 1=D/A outputs 0-10V (internal reference -10V)
79 * 2=D/A outputs unknown (external reference)
80 *
81 * Options for A-821PGL/PGH:
82 * [0] - IO Base
83 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
84 * [2] - 0=A/D channels are S.E.
85 * 1=A/D channels are DIFF
86 * [3] - 0=D/A output 0-5V (internal reference -5V)
87 * 1=D/A output 0-10V (internal reference -10V)
88 *
89 * Options for A-821PGL-NDA:
90 * [0] - IO Base
91 * [1] - IRQ (0=disable, 2, 3, 4, 5, 6, 7)
92 * [2] - 0=A/D channels are S.E.
93 * 1=A/D channels are DIFF
94 *
95 * Options for PCL-813:
96 * [0] - IO Base
97 *
98 * Options for PCL-813B:
99 * [0] - IO Base
100 * [1] - 0= bipolar inputs
101 * 1= unipolar inputs
102 *
103 * Options for ACL-8113, ISO-813:
104 * [0] - IO Base
105 * [1] - 0= 10V bipolar inputs
106 * 1= 10V unipolar inputs
107 * 2= 20V bipolar inputs
108 * 3= 20V unipolar inputs
109 */
110
111 #include <linux/interrupt.h>
112 #include <linux/gfp.h>
113 #include "../comedidev.h"
114
115 #include <linux/delay.h>
116 #include <linux/ioport.h>
117 #include <linux/io.h>
118 #include <asm/dma.h>
119
120 #include "8253.h"
121
122 /* if this is defined then a lot of messages is printed */
123 #undef PCL812_EXTDEBUG
124
125 /* hardware types of the cards */
126 #define boardPCL812PG 0 /* and ACL-8112PG */
127 #define boardPCL813B 1
128 #define boardPCL812 2
129 #define boardPCL813 3
130 #define boardISO813 5
131 #define boardACL8113 6
132 #define boardACL8112 7 /* ACL-8112DG/HG, A-822PGL/PGH, A-823PGL/PGH */
133 #define boardACL8216 8 /* and ICP DAS A-826PG */
134 #define boardA821 9 /* PGH, PGL, PGL/NDA versions */
135
136 #define PCLx1x_IORANGE 16
137
138 #define PCL812_CTR0 0
139 #define PCL812_CTR1 1
140 #define PCL812_CTR2 2
141 #define PCL812_CTRCTL 3
142 #define PCL812_AD_LO 4
143 #define PCL812_DA1_LO 4
144 #define PCL812_AD_HI 5
145 #define PCL812_DA1_HI 5
146 #define PCL812_DA2_LO 6
147 #define PCL812_DI_LO 6
148 #define PCL812_DA2_HI 7
149 #define PCL812_DI_HI 7
150 #define PCL812_CLRINT 8
151 #define PCL812_GAIN 9
152 #define PCL812_MUX 10
153 #define PCL812_MODE 11
154 #define PCL812_CNTENABLE 10
155 #define PCL812_SOFTTRIG 12
156 #define PCL812_DO_LO 13
157 #define PCL812_DO_HI 14
158
159 #define PCL812_DRDY 0x10 /* =0 data ready */
160
161 #define ACL8216_STATUS 8 /* 5. bit signalize data ready */
162
163 #define ACL8216_DRDY 0x20 /* =0 data ready */
164
165 #define MAX_CHANLIST_LEN 256 /* length of scan list */
166
167 static const struct comedi_lrange range_pcl812pg_ai = { 5, {
168 BIP_RANGE(5),
169 BIP_RANGE(2.5),
170 BIP_RANGE(1.25),
171 BIP_RANGE(0.625),
172 BIP_RANGE(0.3125),
173 }
174 };
175
176 static const struct comedi_lrange range_pcl812pg2_ai = { 5, {
177 BIP_RANGE(10),
178 BIP_RANGE(5),
179 BIP_RANGE(2.5),
180 BIP_RANGE(1.25),
181 BIP_RANGE(0.625),
182 }
183 };
184
185 static const struct comedi_lrange range812_bipolar1_25 = { 1, {
186 BIP_RANGE(1.25),
187 }
188 };
189
190 static const struct comedi_lrange range812_bipolar0_625 = { 1, {
191 BIP_RANGE
192 (0.625),
193 }
194 };
195
196 static const struct comedi_lrange range812_bipolar0_3125 = { 1, {
197 BIP_RANGE
198 (0.3125),
199 }
200 };
201
202 static const struct comedi_lrange range_pcl813b_ai = { 4, {
203 BIP_RANGE(5),
204 BIP_RANGE(2.5),
205 BIP_RANGE(1.25),
206 BIP_RANGE(0.625),
207 }
208 };
209
210 static const struct comedi_lrange range_pcl813b2_ai = { 4, {
211 UNI_RANGE(10),
212 UNI_RANGE(5),
213 UNI_RANGE(2.5),
214 UNI_RANGE(1.25),
215 }
216 };
217
218 static const struct comedi_lrange range_iso813_1_ai = { 5, {
219 BIP_RANGE(5),
220 BIP_RANGE(2.5),
221 BIP_RANGE(1.25),
222 BIP_RANGE(0.625),
223 BIP_RANGE(0.3125),
224 }
225 };
226
227 static const struct comedi_lrange range_iso813_1_2_ai = { 5, {
228 UNI_RANGE(10),
229 UNI_RANGE(5),
230 UNI_RANGE(2.5),
231 UNI_RANGE(1.25),
232 UNI_RANGE(0.625),
233 }
234 };
235
236 static const struct comedi_lrange range_iso813_2_ai = { 4, {
237 BIP_RANGE(5),
238 BIP_RANGE(2.5),
239 BIP_RANGE(1.25),
240 BIP_RANGE(0.625),
241 }
242 };
243
244 static const struct comedi_lrange range_iso813_2_2_ai = { 4, {
245 UNI_RANGE(10),
246 UNI_RANGE(5),
247 UNI_RANGE(2.5),
248 UNI_RANGE(1.25),
249 }
250 };
251
252 static const struct comedi_lrange range_acl8113_1_ai = { 4, {
253 BIP_RANGE(5),
254 BIP_RANGE(2.5),
255 BIP_RANGE(1.25),
256 BIP_RANGE(0.625),
257 }
258 };
259
260 static const struct comedi_lrange range_acl8113_1_2_ai = { 4, {
261 UNI_RANGE(10),
262 UNI_RANGE(5),
263 UNI_RANGE(2.5),
264 UNI_RANGE(1.25),
265 }
266 };
267
268 static const struct comedi_lrange range_acl8113_2_ai = { 3, {
269 BIP_RANGE(5),
270 BIP_RANGE(2.5),
271 BIP_RANGE(1.25),
272 }
273 };
274
275 static const struct comedi_lrange range_acl8113_2_2_ai = { 3, {
276 UNI_RANGE(10),
277 UNI_RANGE(5),
278 UNI_RANGE(2.5),
279 }
280 };
281
282 static const struct comedi_lrange range_acl8112dg_ai = { 9, {
283 BIP_RANGE(5),
284 BIP_RANGE(2.5),
285 BIP_RANGE(1.25),
286 BIP_RANGE(0.625),
287 UNI_RANGE(10),
288 UNI_RANGE(5),
289 UNI_RANGE(2.5),
290 UNI_RANGE(1.25),
291 BIP_RANGE(10),
292 }
293 };
294
295 static const struct comedi_lrange range_acl8112hg_ai = { 12, {
296 BIP_RANGE(5),
297 BIP_RANGE(0.5),
298 BIP_RANGE(0.05),
299 BIP_RANGE(0.005),
300 UNI_RANGE(10),
301 UNI_RANGE(1),
302 UNI_RANGE(0.1),
303 UNI_RANGE(0.01),
304 BIP_RANGE(10),
305 BIP_RANGE(1),
306 BIP_RANGE(0.1),
307 BIP_RANGE(0.01),
308 }
309 };
310
311 static const struct comedi_lrange range_a821pgh_ai = { 4, {
312 BIP_RANGE(5),
313 BIP_RANGE(0.5),
314 BIP_RANGE(0.05),
315 BIP_RANGE(0.005),
316 }
317 };
318
319 struct pcl812_board {
320
321 const char *name; /* board name */
322 int board_type; /* type of this board */
323 int n_aichan; /* num of AI chans in S.E. */
324 int n_aichan_diff; /* DIFF num of chans */
325 int n_aochan; /* num of DA chans */
326 int n_dichan; /* DI and DO chans */
327 int n_dochan;
328 int ai_maxdata; /* AI resolution */
329 unsigned int ai_ns_min; /* max sample speed of card v ns */
330 unsigned int i8254_osc_base; /* clock base */
331 const struct comedi_lrange *rangelist_ai; /* rangelist for A/D */
332 const struct comedi_lrange *rangelist_ao; /* rangelist for D/A */
333 unsigned int IRQbits; /* allowed IRQ */
334 unsigned char DMAbits; /* allowed DMA chans */
335 unsigned char io_range; /* iorange for this board */
336 unsigned char haveMPC508; /* 1=board use MPC508A multiplexor */
337 };
338
339 struct pcl812_private {
340
341 unsigned char valid; /* =1 device is OK */
342 unsigned char dma; /* >0 use dma ( usedDMA channel) */
343 unsigned char use_diff; /* =1 diff inputs */
344 unsigned char use_MPC; /* 1=board uses MPC508A multiplexor */
345 unsigned char use_ext_trg; /* 1=board uses external trigger */
346 unsigned char range_correction; /* =1 we must add 1 to range number */
347 unsigned char old_chan_reg; /* lastly used chan/gain pair */
348 unsigned char old_gain_reg;
349 unsigned char mode_reg_int; /* there is stored INT number for some card */
350 unsigned char ai_neverending; /* =1 we do unlimited AI */
351 unsigned char ai_eos; /* 1=EOS wake up */
352 unsigned char ai_dma; /* =1 we use DMA */
353 unsigned int ai_poll_ptr; /* how many sampes transfer poll */
354 unsigned int ai_scans; /* len of scanlist */
355 unsigned int ai_act_scan; /* how many scans we finished */
356 unsigned int ai_chanlist[MAX_CHANLIST_LEN]; /* our copy of channel/range list */
357 unsigned int ai_n_chan; /* how many channels is measured */
358 unsigned int ai_flags; /* flaglist */
359 unsigned int ai_data_len; /* len of data buffer */
360 short *ai_data; /* data buffer */
361 unsigned int ai_is16b; /* =1 we have 16 bit card */
362 unsigned long dmabuf[2]; /* PTR to DMA buf */
363 unsigned int dmapages[2]; /* how many pages we have allocated */
364 unsigned int hwdmaptr[2]; /* HW PTR to DMA buf */
365 unsigned int hwdmasize[2]; /* DMA buf size in bytes */
366 unsigned int dmabytestomove[2]; /* how many bytes DMA transfer */
367 int next_dma_buf; /* which buffer is next to use */
368 unsigned int dma_runs_to_end; /* how many times we must switch DMA buffers */
369 unsigned int last_dma_run; /* how many bytes to transfer on last DMA buffer */
370 unsigned int max_812_ai_mode0_rangewait; /* setling time for gain */
371 unsigned int ao_readback[2]; /* data for AO readback */
372 };
373
374 #define devpriv ((struct pcl812_private *)dev->private)
375
376 /*
377 ==============================================================================
378 */
379 static void start_pacer(struct comedi_device *dev, int mode,
380 unsigned int divisor1, unsigned int divisor2);
381 static void setup_range_channel(struct comedi_device *dev,
382 struct comedi_subdevice *s,
383 unsigned int rangechan, char wait);
384 static int pcl812_ai_cancel(struct comedi_device *dev,
385 struct comedi_subdevice *s);
386 /*
387 ==============================================================================
388 */
389 static int pcl812_ai_insn_read(struct comedi_device *dev,
390 struct comedi_subdevice *s,
391 struct comedi_insn *insn, unsigned int *data)
392 {
393 int n;
394 int timeout, hi;
395
396 /* select software trigger */
397 outb(devpriv->mode_reg_int | 1, dev->iobase + PCL812_MODE);
398 /* select channel and renge */
399 setup_range_channel(dev, s, insn->chanspec, 1);
400 for (n = 0; n < insn->n; n++) {
401 /* start conversion */
402 outb(255, dev->iobase + PCL812_SOFTTRIG);
403 udelay(5);
404 timeout = 50; /* wait max 50us, it must finish under 33us */
405 while (timeout--) {
406 hi = inb(dev->iobase + PCL812_AD_HI);
407 if (!(hi & PCL812_DRDY))
408 goto conv_finish;
409 udelay(1);
410 }
411 printk
412 ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n",
413 dev->minor, dev->board_name, dev->iobase);
414 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
415 return -ETIME;
416
417 conv_finish:
418 data[n] = ((hi & 0xf) << 8) | inb(dev->iobase + PCL812_AD_LO);
419 }
420 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
421 return n;
422 }
423
424 /*
425 ==============================================================================
426 */
427 static int acl8216_ai_insn_read(struct comedi_device *dev,
428 struct comedi_subdevice *s,
429 struct comedi_insn *insn, unsigned int *data)
430 {
431 int n;
432 int timeout;
433
434 /* select software trigger */
435 outb(1, dev->iobase + PCL812_MODE);
436 /* select channel and renge */
437 setup_range_channel(dev, s, insn->chanspec, 1);
438 for (n = 0; n < insn->n; n++) {
439 /* start conversion */
440 outb(255, dev->iobase + PCL812_SOFTTRIG);
441 udelay(5);
442 timeout = 50; /* wait max 50us, it must finish under 33us */
443 while (timeout--) {
444 if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY))
445 goto conv_finish;
446 udelay(1);
447 }
448 printk
449 ("comedi%d: pcl812: (%s at 0x%lx) A/D insn read timeout\n",
450 dev->minor, dev->board_name, dev->iobase);
451 outb(0, dev->iobase + PCL812_MODE);
452 return -ETIME;
453
454 conv_finish:
455 data[n] =
456 (inb(dev->iobase +
457 PCL812_AD_HI) << 8) | inb(dev->iobase + PCL812_AD_LO);
458 }
459 outb(0, dev->iobase + PCL812_MODE);
460 return n;
461 }
462
463 /*
464 ==============================================================================
465 */
466 static int pcl812_ao_insn_write(struct comedi_device *dev,
467 struct comedi_subdevice *s,
468 struct comedi_insn *insn, unsigned int *data)
469 {
470 int chan = CR_CHAN(insn->chanspec);
471 int i;
472
473 for (i = 0; i < insn->n; i++) {
474 outb((data[i] & 0xff),
475 dev->iobase + (chan ? PCL812_DA2_LO : PCL812_DA1_LO));
476 outb((data[i] >> 8) & 0x0f,
477 dev->iobase + (chan ? PCL812_DA2_HI : PCL812_DA1_HI));
478 devpriv->ao_readback[chan] = data[i];
479 }
480
481 return i;
482 }
483
484 /*
485 ==============================================================================
486 */
487 static int pcl812_ao_insn_read(struct comedi_device *dev,
488 struct comedi_subdevice *s,
489 struct comedi_insn *insn, unsigned int *data)
490 {
491 int chan = CR_CHAN(insn->chanspec);
492 int i;
493
494 for (i = 0; i < insn->n; i++)
495 data[i] = devpriv->ao_readback[chan];
496
497 return i;
498 }
499
500 /*
501 ==============================================================================
502 */
503 static int pcl812_di_insn_bits(struct comedi_device *dev,
504 struct comedi_subdevice *s,
505 struct comedi_insn *insn, unsigned int *data)
506 {
507 if (insn->n != 2)
508 return -EINVAL;
509
510 data[1] = inb(dev->iobase + PCL812_DI_LO);
511 data[1] |= inb(dev->iobase + PCL812_DI_HI) << 8;
512
513 return 2;
514 }
515
516 /*
517 ==============================================================================
518 */
519 static int pcl812_do_insn_bits(struct comedi_device *dev,
520 struct comedi_subdevice *s,
521 struct comedi_insn *insn, unsigned int *data)
522 {
523 if (insn->n != 2)
524 return -EINVAL;
525
526 if (data[0]) {
527 s->state &= ~data[0];
528 s->state |= data[0] & data[1];
529 outb(s->state & 0xff, dev->iobase + PCL812_DO_LO);
530 outb((s->state >> 8), dev->iobase + PCL812_DO_HI);
531 }
532 data[1] = s->state;
533
534 return 2;
535 }
536
537 #ifdef PCL812_EXTDEBUG
538 /*
539 ==============================================================================
540 */
541 static void pcl812_cmdtest_out(int e, struct comedi_cmd *cmd)
542 {
543 printk(KERN_INFO "pcl812 e=%d startsrc=%x scansrc=%x convsrc=%x\n", e,
544 cmd->start_src, cmd->scan_begin_src, cmd->convert_src);
545 printk(KERN_INFO "pcl812 e=%d startarg=%d scanarg=%d convarg=%d\n", e,
546 cmd->start_arg, cmd->scan_begin_arg, cmd->convert_arg);
547 printk(KERN_INFO "pcl812 e=%d stopsrc=%x scanend=%x\n", e,
548 cmd->stop_src, cmd->scan_end_src);
549 printk(KERN_INFO "pcl812 e=%d stoparg=%d scanendarg=%d "
550 "chanlistlen=%d\n", e, cmd->stop_arg, cmd->scan_end_arg,
551 cmd->chanlist_len);
552 }
553 #endif
554
555 /*
556 ==============================================================================
557 */
558 static int pcl812_ai_cmdtest(struct comedi_device *dev,
559 struct comedi_subdevice *s, struct comedi_cmd *cmd)
560 {
561 const struct pcl812_board *board = comedi_board(dev);
562 int err = 0;
563 int tmp, divisor1, divisor2;
564
565 #ifdef PCL812_EXTDEBUG
566 printk("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...)\n");
567 pcl812_cmdtest_out(-1, cmd);
568 #endif
569 /* step 1: make sure trigger sources are trivially valid */
570
571 tmp = cmd->start_src;
572 cmd->start_src &= TRIG_NOW;
573 if (!cmd->start_src || tmp != cmd->start_src)
574 err++;
575
576 tmp = cmd->scan_begin_src;
577 cmd->scan_begin_src &= TRIG_FOLLOW;
578 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
579 err++;
580
581 tmp = cmd->convert_src;
582 if (devpriv->use_ext_trg)
583 cmd->convert_src &= TRIG_EXT;
584 else
585 cmd->convert_src &= TRIG_TIMER;
586
587 if (!cmd->convert_src || tmp != cmd->convert_src)
588 err++;
589
590 tmp = cmd->scan_end_src;
591 cmd->scan_end_src &= TRIG_COUNT;
592 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
593 err++;
594
595 tmp = cmd->stop_src;
596 cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
597 if (!cmd->stop_src || tmp != cmd->stop_src)
598 err++;
599
600 if (err) {
601 #ifdef PCL812_EXTDEBUG
602 pcl812_cmdtest_out(1, cmd);
603 printk
604 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=1\n",
605 err);
606 #endif
607 return 1;
608 }
609
610 /*
611 * step 2: make sure trigger sources are
612 * unique and mutually compatible
613 */
614
615 if (cmd->start_src != TRIG_NOW) {
616 cmd->start_src = TRIG_NOW;
617 err++;
618 }
619
620 if (cmd->scan_begin_src != TRIG_FOLLOW) {
621 cmd->scan_begin_src = TRIG_FOLLOW;
622 err++;
623 }
624
625 if (devpriv->use_ext_trg) {
626 if (cmd->convert_src != TRIG_EXT) {
627 cmd->convert_src = TRIG_EXT;
628 err++;
629 }
630 } else {
631 if (cmd->convert_src != TRIG_TIMER) {
632 cmd->convert_src = TRIG_TIMER;
633 err++;
634 }
635 }
636
637 if (cmd->scan_end_src != TRIG_COUNT) {
638 cmd->scan_end_src = TRIG_COUNT;
639 err++;
640 }
641
642 if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
643 err++;
644
645 if (err) {
646 #ifdef PCL812_EXTDEBUG
647 pcl812_cmdtest_out(2, cmd);
648 printk
649 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=2\n",
650 err);
651 #endif
652 return 2;
653 }
654
655 /* step 3: make sure arguments are trivially compatible */
656
657 if (cmd->start_arg != 0) {
658 cmd->start_arg = 0;
659 err++;
660 }
661
662 if (cmd->scan_begin_arg != 0) {
663 cmd->scan_begin_arg = 0;
664 err++;
665 }
666
667 if (cmd->convert_src == TRIG_TIMER) {
668 if (cmd->convert_arg < board->ai_ns_min) {
669 cmd->convert_arg = board->ai_ns_min;
670 err++;
671 }
672 } else { /* TRIG_EXT */
673 if (cmd->convert_arg != 0) {
674 cmd->convert_arg = 0;
675 err++;
676 }
677 }
678
679 if (!cmd->chanlist_len) {
680 cmd->chanlist_len = 1;
681 err++;
682 }
683 if (cmd->chanlist_len > MAX_CHANLIST_LEN) {
684 cmd->chanlist_len = board->n_aichan;
685 err++;
686 }
687 if (cmd->scan_end_arg != cmd->chanlist_len) {
688 cmd->scan_end_arg = cmd->chanlist_len;
689 err++;
690 }
691 if (cmd->stop_src == TRIG_COUNT) {
692 if (!cmd->stop_arg) {
693 cmd->stop_arg = 1;
694 err++;
695 }
696 } else { /* TRIG_NONE */
697 if (cmd->stop_arg != 0) {
698 cmd->stop_arg = 0;
699 err++;
700 }
701 }
702
703 if (err) {
704 #ifdef PCL812_EXTDEBUG
705 pcl812_cmdtest_out(3, cmd);
706 printk
707 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=3\n",
708 err);
709 #endif
710 return 3;
711 }
712
713 /* step 4: fix up any arguments */
714
715 if (cmd->convert_src == TRIG_TIMER) {
716 tmp = cmd->convert_arg;
717 i8253_cascade_ns_to_timer(board->i8254_osc_base, &divisor1,
718 &divisor2, &cmd->convert_arg,
719 cmd->flags & TRIG_ROUND_MASK);
720 if (cmd->convert_arg < board->ai_ns_min)
721 cmd->convert_arg = board->ai_ns_min;
722 if (tmp != cmd->convert_arg)
723 err++;
724 }
725
726 if (err) {
727 #ifdef PCL812_EXTDEBUG
728 printk
729 ("pcl812 EDBG: BGN: pcl812_ai_cmdtest(...) err=%d ret=4\n",
730 err);
731 #endif
732 return 4;
733 }
734
735 return 0;
736 }
737
738 /*
739 ==============================================================================
740 */
741 static int pcl812_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
742 {
743 const struct pcl812_board *board = comedi_board(dev);
744 unsigned int divisor1 = 0, divisor2 = 0, i, dma_flags, bytes;
745 struct comedi_cmd *cmd = &s->async->cmd;
746
747 #ifdef PCL812_EXTDEBUG
748 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cmd(...)\n");
749 #endif
750
751 if (cmd->start_src != TRIG_NOW)
752 return -EINVAL;
753 if (cmd->scan_begin_src != TRIG_FOLLOW)
754 return -EINVAL;
755 if (devpriv->use_ext_trg) {
756 if (cmd->convert_src != TRIG_EXT)
757 return -EINVAL;
758 } else {
759 if (cmd->convert_src != TRIG_TIMER)
760 return -EINVAL;
761 }
762 if (cmd->scan_end_src != TRIG_COUNT)
763 return -EINVAL;
764 if (cmd->scan_end_arg != cmd->chanlist_len)
765 return -EINVAL;
766 if (cmd->chanlist_len > MAX_CHANLIST_LEN)
767 return -EINVAL;
768
769 if (cmd->convert_src == TRIG_TIMER) {
770 if (cmd->convert_arg < board->ai_ns_min)
771 cmd->convert_arg = board->ai_ns_min;
772 i8253_cascade_ns_to_timer(board->i8254_osc_base,
773 &divisor1, &divisor2,
774 &cmd->convert_arg,
775 cmd->flags & TRIG_ROUND_MASK);
776 }
777
778 start_pacer(dev, -1, 0, 0); /* stop pacer */
779
780 devpriv->ai_n_chan = cmd->chanlist_len;
781 memcpy(devpriv->ai_chanlist, cmd->chanlist,
782 sizeof(unsigned int) * cmd->scan_end_arg);
783 /* select first channel and range */
784 setup_range_channel(dev, s, devpriv->ai_chanlist[0], 1);
785
786 if (devpriv->dma) { /* check if we can use DMA transfer */
787 devpriv->ai_dma = 1;
788 for (i = 1; i < devpriv->ai_n_chan; i++)
789 if (devpriv->ai_chanlist[0] != devpriv->ai_chanlist[i]) {
790 /* we cann't use DMA :-( */
791 devpriv->ai_dma = 0;
792 break;
793 }
794 } else
795 devpriv->ai_dma = 0;
796
797 devpriv->ai_flags = cmd->flags;
798 devpriv->ai_data_len = s->async->prealloc_bufsz;
799 devpriv->ai_data = s->async->prealloc_buf;
800 if (cmd->stop_src == TRIG_COUNT) {
801 devpriv->ai_scans = cmd->stop_arg;
802 devpriv->ai_neverending = 0;
803 } else {
804 devpriv->ai_scans = 0;
805 devpriv->ai_neverending = 1;
806 }
807
808 devpriv->ai_act_scan = 0;
809 devpriv->ai_poll_ptr = 0;
810 s->async->cur_chan = 0;
811
812 /* don't we want wake up every scan? */
813 if ((devpriv->ai_flags & TRIG_WAKE_EOS)) {
814 devpriv->ai_eos = 1;
815
816 /* DMA is useless for this situation */
817 if (devpriv->ai_n_chan == 1)
818 devpriv->ai_dma = 0;
819 }
820
821 if (devpriv->ai_dma) {
822 /* we use EOS, so adapt DMA buffer to one scan */
823 if (devpriv->ai_eos) {
824 devpriv->dmabytestomove[0] =
825 devpriv->ai_n_chan * sizeof(short);
826 devpriv->dmabytestomove[1] =
827 devpriv->ai_n_chan * sizeof(short);
828 devpriv->dma_runs_to_end = 1;
829 } else {
830 devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
831 devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
832 if (devpriv->ai_data_len < devpriv->hwdmasize[0])
833 devpriv->dmabytestomove[0] =
834 devpriv->ai_data_len;
835 if (devpriv->ai_data_len < devpriv->hwdmasize[1])
836 devpriv->dmabytestomove[1] =
837 devpriv->ai_data_len;
838 if (devpriv->ai_neverending) {
839 devpriv->dma_runs_to_end = 1;
840 } else {
841 /* how many samples we must transfer? */
842 bytes = devpriv->ai_n_chan *
843 devpriv->ai_scans * sizeof(short);
844
845 /* how many DMA pages we must fill */
846 devpriv->dma_runs_to_end =
847 bytes / devpriv->dmabytestomove[0];
848
849 /* on last dma transfer must be moved */
850 devpriv->last_dma_run =
851 bytes % devpriv->dmabytestomove[0];
852 if (devpriv->dma_runs_to_end == 0)
853 devpriv->dmabytestomove[0] =
854 devpriv->last_dma_run;
855 devpriv->dma_runs_to_end--;
856 }
857 }
858 if (devpriv->dmabytestomove[0] > devpriv->hwdmasize[0]) {
859 devpriv->dmabytestomove[0] = devpriv->hwdmasize[0];
860 devpriv->ai_eos = 0;
861 }
862 if (devpriv->dmabytestomove[1] > devpriv->hwdmasize[1]) {
863 devpriv->dmabytestomove[1] = devpriv->hwdmasize[1];
864 devpriv->ai_eos = 0;
865 }
866 devpriv->next_dma_buf = 0;
867 set_dma_mode(devpriv->dma, DMA_MODE_READ);
868 dma_flags = claim_dma_lock();
869 clear_dma_ff(devpriv->dma);
870 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
871 set_dma_count(devpriv->dma, devpriv->dmabytestomove[0]);
872 release_dma_lock(dma_flags);
873 enable_dma(devpriv->dma);
874 #ifdef PCL812_EXTDEBUG
875 printk
876 ("pcl812 EDBG: DMA %d PTR 0x%0x/0x%0x LEN %u/%u EOS %d\n",
877 devpriv->dma, devpriv->hwdmaptr[0],
878 devpriv->hwdmaptr[1], devpriv->dmabytestomove[0],
879 devpriv->dmabytestomove[1], devpriv->ai_eos);
880 #endif
881 }
882
883 switch (cmd->convert_src) {
884 case TRIG_TIMER:
885 start_pacer(dev, 1, divisor1, divisor2);
886 break;
887 }
888
889 if (devpriv->ai_dma) /* let's go! */
890 outb(devpriv->mode_reg_int | 2, dev->iobase + PCL812_MODE);
891 else /* let's go! */
892 outb(devpriv->mode_reg_int | 6, dev->iobase + PCL812_MODE);
893
894 #ifdef PCL812_EXTDEBUG
895 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cmd(...)\n");
896 #endif
897
898 return 0;
899 }
900
901 /*
902 ==============================================================================
903 */
904 static irqreturn_t interrupt_pcl812_ai_int(int irq, void *d)
905 {
906 char err = 1;
907 unsigned int mask, timeout;
908 struct comedi_device *dev = d;
909 struct comedi_subdevice *s = dev->subdevices + 0;
910 unsigned int next_chan;
911
912 s->async->events = 0;
913
914 timeout = 50; /* wait max 50us, it must finish under 33us */
915 if (devpriv->ai_is16b) {
916 mask = 0xffff;
917 while (timeout--) {
918 if (!(inb(dev->iobase + ACL8216_STATUS) & ACL8216_DRDY)) {
919 err = 0;
920 break;
921 }
922 udelay(1);
923 }
924 } else {
925 mask = 0x0fff;
926 while (timeout--) {
927 if (!(inb(dev->iobase + PCL812_AD_HI) & PCL812_DRDY)) {
928 err = 0;
929 break;
930 }
931 udelay(1);
932 }
933 }
934
935 if (err) {
936 printk
937 ("comedi%d: pcl812: (%s at 0x%lx) "
938 "A/D cmd IRQ without DRDY!\n",
939 dev->minor, dev->board_name, dev->iobase);
940 pcl812_ai_cancel(dev, s);
941 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
942 comedi_event(dev, s);
943 return IRQ_HANDLED;
944 }
945
946 comedi_buf_put(s->async,
947 ((inb(dev->iobase + PCL812_AD_HI) << 8) |
948 inb(dev->iobase + PCL812_AD_LO)) & mask);
949
950 /* Set up next channel. Added by abbotti 2010-01-20, but untested. */
951 next_chan = s->async->cur_chan + 1;
952 if (next_chan >= devpriv->ai_n_chan)
953 next_chan = 0;
954 if (devpriv->ai_chanlist[s->async->cur_chan] !=
955 devpriv->ai_chanlist[next_chan])
956 setup_range_channel(dev, s, devpriv->ai_chanlist[next_chan], 0);
957
958 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
959
960 s->async->cur_chan = next_chan;
961 if (next_chan == 0) { /* one scan done */
962 devpriv->ai_act_scan++;
963 if (!(devpriv->ai_neverending))
964 /* all data sampled */
965 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
966 pcl812_ai_cancel(dev, s);
967 s->async->events |= COMEDI_CB_EOA;
968 }
969 }
970
971 comedi_event(dev, s);
972 return IRQ_HANDLED;
973 }
974
975 /*
976 ==============================================================================
977 */
978 static void transfer_from_dma_buf(struct comedi_device *dev,
979 struct comedi_subdevice *s, short *ptr,
980 unsigned int bufptr, unsigned int len)
981 {
982 unsigned int i;
983
984 s->async->events = 0;
985 for (i = len; i; i--) {
986 /* get one sample */
987 comedi_buf_put(s->async, ptr[bufptr++]);
988
989 s->async->cur_chan++;
990 if (s->async->cur_chan >= devpriv->ai_n_chan) {
991 s->async->cur_chan = 0;
992 devpriv->ai_act_scan++;
993 if (!devpriv->ai_neverending)
994 /* all data sampled */
995 if (devpriv->ai_act_scan >= devpriv->ai_scans) {
996 pcl812_ai_cancel(dev, s);
997 s->async->events |= COMEDI_CB_EOA;
998 break;
999 }
1000 }
1001 }
1002
1003 comedi_event(dev, s);
1004 }
1005
1006 /*
1007 ==============================================================================
1008 */
1009 static irqreturn_t interrupt_pcl812_ai_dma(int irq, void *d)
1010 {
1011 struct comedi_device *dev = d;
1012 struct comedi_subdevice *s = dev->subdevices + 0;
1013 unsigned long dma_flags;
1014 int len, bufptr;
1015 short *ptr;
1016
1017 #ifdef PCL812_EXTDEBUG
1018 printk(KERN_DEBUG "pcl812 EDBG: BGN: interrupt_pcl812_ai_dma(...)\n");
1019 #endif
1020 ptr = (short *)devpriv->dmabuf[devpriv->next_dma_buf];
1021 len = (devpriv->dmabytestomove[devpriv->next_dma_buf] >> 1) -
1022 devpriv->ai_poll_ptr;
1023
1024 devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
1025 disable_dma(devpriv->dma);
1026 set_dma_mode(devpriv->dma, DMA_MODE_READ);
1027 dma_flags = claim_dma_lock();
1028 set_dma_addr(devpriv->dma, devpriv->hwdmaptr[devpriv->next_dma_buf]);
1029 if (devpriv->ai_eos) {
1030 set_dma_count(devpriv->dma,
1031 devpriv->dmabytestomove[devpriv->next_dma_buf]);
1032 } else {
1033 if (devpriv->dma_runs_to_end) {
1034 set_dma_count(devpriv->dma,
1035 devpriv->dmabytestomove[devpriv->
1036 next_dma_buf]);
1037 } else {
1038 set_dma_count(devpriv->dma, devpriv->last_dma_run);
1039 }
1040 devpriv->dma_runs_to_end--;
1041 }
1042 release_dma_lock(dma_flags);
1043 enable_dma(devpriv->dma);
1044
1045 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
1046
1047 bufptr = devpriv->ai_poll_ptr;
1048 devpriv->ai_poll_ptr = 0;
1049
1050 transfer_from_dma_buf(dev, s, ptr, bufptr, len);
1051
1052 #ifdef PCL812_EXTDEBUG
1053 printk(KERN_DEBUG "pcl812 EDBG: END: interrupt_pcl812_ai_dma(...)\n");
1054 #endif
1055 return IRQ_HANDLED;
1056 }
1057
1058 /*
1059 ==============================================================================
1060 */
1061 static irqreturn_t interrupt_pcl812(int irq, void *d)
1062 {
1063 struct comedi_device *dev = d;
1064
1065 if (!dev->attached) {
1066 comedi_error(dev, "spurious interrupt");
1067 return IRQ_HANDLED;
1068 }
1069 if (devpriv->ai_dma)
1070 return interrupt_pcl812_ai_dma(irq, d);
1071 else
1072 return interrupt_pcl812_ai_int(irq, d);
1073 }
1074
1075 /*
1076 ==============================================================================
1077 */
1078 static int pcl812_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
1079 {
1080 unsigned long flags;
1081 unsigned int top1, top2, i;
1082
1083 if (!devpriv->ai_dma)
1084 return 0; /* poll is valid only for DMA transfer */
1085
1086 spin_lock_irqsave(&dev->spinlock, flags);
1087
1088 for (i = 0; i < 10; i++) {
1089 /* where is now DMA */
1090 top1 = get_dma_residue(devpriv->ai_dma);
1091 top2 = get_dma_residue(devpriv->ai_dma);
1092 if (top1 == top2)
1093 break;
1094 }
1095
1096 if (top1 != top2) {
1097 spin_unlock_irqrestore(&dev->spinlock, flags);
1098 return 0;
1099 }
1100 /* where is now DMA in buffer */
1101 top1 = devpriv->dmabytestomove[1 - devpriv->next_dma_buf] - top1;
1102 top1 >>= 1; /* sample position */
1103 top2 = top1 - devpriv->ai_poll_ptr;
1104 if (top2 < 1) { /* no new samples */
1105 spin_unlock_irqrestore(&dev->spinlock, flags);
1106 return 0;
1107 }
1108
1109 transfer_from_dma_buf(dev, s,
1110 (void *)devpriv->dmabuf[1 -
1111 devpriv->next_dma_buf],
1112 devpriv->ai_poll_ptr, top2);
1113
1114 devpriv->ai_poll_ptr = top1; /* new buffer position */
1115
1116 spin_unlock_irqrestore(&dev->spinlock, flags);
1117
1118 return s->async->buf_write_count - s->async->buf_read_count;
1119 }
1120
1121 /*
1122 ==============================================================================
1123 */
1124 static void setup_range_channel(struct comedi_device *dev,
1125 struct comedi_subdevice *s,
1126 unsigned int rangechan, char wait)
1127 {
1128 unsigned char chan_reg = CR_CHAN(rangechan); /* normal board */
1129 /* gain index */
1130 unsigned char gain_reg = CR_RANGE(rangechan) +
1131 devpriv->range_correction;
1132
1133 if ((chan_reg == devpriv->old_chan_reg)
1134 && (gain_reg == devpriv->old_gain_reg))
1135 return; /* we can return, no change */
1136
1137 devpriv->old_chan_reg = chan_reg;
1138 devpriv->old_gain_reg = gain_reg;
1139
1140 if (devpriv->use_MPC) {
1141 if (devpriv->use_diff) {
1142 chan_reg = chan_reg | 0x30; /* DIFF inputs */
1143 } else {
1144 if (chan_reg & 0x80)
1145 /* SE inputs 8-15 */
1146 chan_reg = chan_reg | 0x20;
1147 else
1148 /* SE inputs 0-7 */
1149 chan_reg = chan_reg | 0x10;
1150 }
1151 }
1152
1153 outb(chan_reg, dev->iobase + PCL812_MUX); /* select channel */
1154 outb(gain_reg, dev->iobase + PCL812_GAIN); /* select gain */
1155
1156
1157 if (wait)
1158 /*
1159 * XXX this depends on selected range and can be very long for
1160 * some high gain ranges!
1161 */
1162 udelay(devpriv->max_812_ai_mode0_rangewait);
1163 }
1164
1165 /*
1166 ==============================================================================
1167 */
1168 static void start_pacer(struct comedi_device *dev, int mode,
1169 unsigned int divisor1, unsigned int divisor2)
1170 {
1171 #ifdef PCL812_EXTDEBUG
1172 printk(KERN_DEBUG "pcl812 EDBG: BGN: start_pacer(%d,%u,%u)\n", mode,
1173 divisor1, divisor2);
1174 #endif
1175 outb(0xb4, dev->iobase + PCL812_CTRCTL);
1176 outb(0x74, dev->iobase + PCL812_CTRCTL);
1177 udelay(1);
1178
1179 if (mode == 1) {
1180 outb(divisor2 & 0xff, dev->iobase + PCL812_CTR2);
1181 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL812_CTR2);
1182 outb(divisor1 & 0xff, dev->iobase + PCL812_CTR1);
1183 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL812_CTR1);
1184 }
1185 #ifdef PCL812_EXTDEBUG
1186 printk(KERN_DEBUG "pcl812 EDBG: END: start_pacer(...)\n");
1187 #endif
1188 }
1189
1190 /*
1191 ==============================================================================
1192 */
1193 static void free_resources(struct comedi_device *dev)
1194 {
1195 const struct pcl812_board *board = comedi_board(dev);
1196
1197 if (dev->private) {
1198 if (devpriv->dmabuf[0])
1199 free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1200 if (devpriv->dmabuf[1])
1201 free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1202 if (devpriv->dma)
1203 free_dma(devpriv->dma);
1204 }
1205 if (dev->irq)
1206 free_irq(dev->irq, dev);
1207 if (dev->iobase)
1208 release_region(dev->iobase, board->io_range);
1209 }
1210
1211 /*
1212 ==============================================================================
1213 */
1214 static int pcl812_ai_cancel(struct comedi_device *dev,
1215 struct comedi_subdevice *s)
1216 {
1217 #ifdef PCL812_EXTDEBUG
1218 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_ai_cancel(...)\n");
1219 #endif
1220 if (devpriv->ai_dma)
1221 disable_dma(devpriv->dma);
1222 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
1223 /* Stop A/D */
1224 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
1225 start_pacer(dev, -1, 0, 0); /* stop 8254 */
1226 outb(0, dev->iobase + PCL812_CLRINT); /* clear INT request */
1227 #ifdef PCL812_EXTDEBUG
1228 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_ai_cancel(...)\n");
1229 #endif
1230 return 0;
1231 }
1232
1233 /*
1234 ==============================================================================
1235 */
1236 static void pcl812_reset(struct comedi_device *dev)
1237 {
1238 const struct pcl812_board *board = comedi_board(dev);
1239
1240 #ifdef PCL812_EXTDEBUG
1241 printk(KERN_DEBUG "pcl812 EDBG: BGN: pcl812_reset(...)\n");
1242 #endif
1243 outb(0, dev->iobase + PCL812_MUX);
1244 outb(0 + devpriv->range_correction, dev->iobase + PCL812_GAIN);
1245 devpriv->old_chan_reg = -1; /* invalidate chain/gain memory */
1246 devpriv->old_gain_reg = -1;
1247
1248 switch (board->board_type) {
1249 case boardPCL812PG:
1250 case boardPCL812:
1251 case boardACL8112:
1252 case boardACL8216:
1253 outb(0, dev->iobase + PCL812_DA2_LO);
1254 outb(0, dev->iobase + PCL812_DA2_HI);
1255 case boardA821:
1256 outb(0, dev->iobase + PCL812_DA1_LO);
1257 outb(0, dev->iobase + PCL812_DA1_HI);
1258 start_pacer(dev, -1, 0, 0); /* stop 8254 */
1259 outb(0, dev->iobase + PCL812_DO_HI);
1260 outb(0, dev->iobase + PCL812_DO_LO);
1261 outb(devpriv->mode_reg_int | 0, dev->iobase + PCL812_MODE);
1262 outb(0, dev->iobase + PCL812_CLRINT);
1263 break;
1264 case boardPCL813B:
1265 case boardPCL813:
1266 case boardISO813:
1267 case boardACL8113:
1268 udelay(5);
1269 break;
1270 }
1271 udelay(5);
1272 #ifdef PCL812_EXTDEBUG
1273 printk(KERN_DEBUG "pcl812 EDBG: END: pcl812_reset(...)\n");
1274 #endif
1275 }
1276
1277 static int pcl812_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1278 {
1279 const struct pcl812_board *board = comedi_board(dev);
1280 int ret, subdev;
1281 unsigned long iobase;
1282 unsigned int irq;
1283 unsigned int dma;
1284 unsigned long pages;
1285 struct comedi_subdevice *s;
1286 int n_subdevices;
1287
1288 iobase = it->options[0];
1289 printk(KERN_INFO "comedi%d: pcl812: board=%s, ioport=0x%03lx",
1290 dev->minor, board->name, iobase);
1291
1292 if (!request_region(iobase, board->io_range, "pcl812")) {
1293 printk("I/O port conflict\n");
1294 return -EIO;
1295 }
1296 dev->iobase = iobase;
1297
1298 ret = alloc_private(dev, sizeof(struct pcl812_private));
1299 if (ret < 0) {
1300 free_resources(dev);
1301 return ret; /* Can't alloc mem */
1302 }
1303
1304 dev->board_name = board->name;
1305
1306 irq = 0;
1307 if (board->IRQbits != 0) { /* board support IRQ */
1308 irq = it->options[1];
1309 if (irq) { /* we want to use IRQ */
1310 if (((1 << irq) & board->IRQbits) == 0) {
1311 printk
1312 (", IRQ %u is out of allowed range, "
1313 "DISABLING IT", irq);
1314 irq = 0; /* Bad IRQ */
1315 } else {
1316 if (request_irq
1317 (irq, interrupt_pcl812, 0, "pcl812", dev)) {
1318 printk
1319 (", unable to allocate IRQ %u, "
1320 "DISABLING IT", irq);
1321 irq = 0; /* Can't use IRQ */
1322 } else {
1323 printk(KERN_INFO ", irq=%u", irq);
1324 }
1325 }
1326 }
1327 }
1328
1329 dev->irq = irq;
1330
1331 dma = 0;
1332 devpriv->dma = dma;
1333 if (!dev->irq)
1334 goto no_dma; /* if we haven't IRQ, we can't use DMA */
1335 if (board->DMAbits != 0) { /* board support DMA */
1336 dma = it->options[2];
1337 if (((1 << dma) & board->DMAbits) == 0) {
1338 printk(", DMA is out of allowed range, FAIL!\n");
1339 return -EINVAL; /* Bad DMA */
1340 }
1341 ret = request_dma(dma, "pcl812");
1342 if (ret) {
1343 printk(KERN_ERR ", unable to allocate DMA %u, FAIL!\n",
1344 dma);
1345 return -EBUSY; /* DMA isn't free */
1346 }
1347 devpriv->dma = dma;
1348 printk(KERN_INFO ", dma=%u", dma);
1349 pages = 1; /* we want 8KB */
1350 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1351 if (!devpriv->dmabuf[0]) {
1352 printk(", unable to allocate DMA buffer, FAIL!\n");
1353 /*
1354 * maybe experiment with try_to_free_pages()
1355 * will help ....
1356 */
1357 free_resources(dev);
1358 return -EBUSY; /* no buffer :-( */
1359 }
1360 devpriv->dmapages[0] = pages;
1361 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1362 devpriv->hwdmasize[0] = PAGE_SIZE * (1 << pages);
1363 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1364 if (!devpriv->dmabuf[1]) {
1365 printk(KERN_ERR ", unable to allocate DMA buffer, FAIL!\n");
1366 free_resources(dev);
1367 return -EBUSY;
1368 }
1369 devpriv->dmapages[1] = pages;
1370 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1371 devpriv->hwdmasize[1] = PAGE_SIZE * (1 << pages);
1372 }
1373 no_dma:
1374
1375 n_subdevices = 0;
1376 if (board->n_aichan > 0)
1377 n_subdevices++;
1378 if (board->n_aochan > 0)
1379 n_subdevices++;
1380 if (board->n_dichan > 0)
1381 n_subdevices++;
1382 if (board->n_dochan > 0)
1383 n_subdevices++;
1384
1385 ret = comedi_alloc_subdevices(dev, n_subdevices);
1386 if (ret) {
1387 free_resources(dev);
1388 return ret;
1389 }
1390
1391 subdev = 0;
1392
1393 /* analog input */
1394 if (board->n_aichan > 0) {
1395 s = dev->subdevices + subdev;
1396 s->type = COMEDI_SUBD_AI;
1397 s->subdev_flags = SDF_READABLE;
1398 switch (board->board_type) {
1399 case boardA821:
1400 if (it->options[2] == 1) {
1401 s->n_chan = board->n_aichan_diff;
1402 s->subdev_flags |= SDF_DIFF;
1403 devpriv->use_diff = 1;
1404 } else {
1405 s->n_chan = board->n_aichan;
1406 s->subdev_flags |= SDF_GROUND;
1407 }
1408 break;
1409 case boardACL8112:
1410 case boardACL8216:
1411 if (it->options[4] == 1) {
1412 s->n_chan = board->n_aichan_diff;
1413 s->subdev_flags |= SDF_DIFF;
1414 devpriv->use_diff = 1;
1415 } else {
1416 s->n_chan = board->n_aichan;
1417 s->subdev_flags |= SDF_GROUND;
1418 }
1419 break;
1420 default:
1421 s->n_chan = board->n_aichan;
1422 s->subdev_flags |= SDF_GROUND;
1423 break;
1424 }
1425 s->maxdata = board->ai_maxdata;
1426 s->len_chanlist = MAX_CHANLIST_LEN;
1427 s->range_table = board->rangelist_ai;
1428 if (board->board_type == boardACL8216)
1429 s->insn_read = acl8216_ai_insn_read;
1430 else
1431 s->insn_read = pcl812_ai_insn_read;
1432
1433 devpriv->use_MPC = board->haveMPC508;
1434 s->cancel = pcl812_ai_cancel;
1435 if (dev->irq) {
1436 dev->read_subdev = s;
1437 s->subdev_flags |= SDF_CMD_READ;
1438 s->do_cmdtest = pcl812_ai_cmdtest;
1439 s->do_cmd = pcl812_ai_cmd;
1440 s->poll = pcl812_ai_poll;
1441 }
1442 switch (board->board_type) {
1443 case boardPCL812PG:
1444 if (it->options[4] == 1)
1445 s->range_table = &range_pcl812pg2_ai;
1446 break;
1447 case boardPCL812:
1448 switch (it->options[4]) {
1449 case 0:
1450 s->range_table = &range_bipolar10;
1451 break;
1452 case 1:
1453 s->range_table = &range_bipolar5;
1454 break;
1455 case 2:
1456 s->range_table = &range_bipolar2_5;
1457 break;
1458 case 3:
1459 s->range_table = &range812_bipolar1_25;
1460 break;
1461 case 4:
1462 s->range_table = &range812_bipolar0_625;
1463 break;
1464 case 5:
1465 s->range_table = &range812_bipolar0_3125;
1466 break;
1467 default:
1468 s->range_table = &range_bipolar10;
1469 break;
1470 printk
1471 (", incorrect range number %d, changing "
1472 "to 0 (+/-10V)", it->options[4]);
1473 break;
1474 }
1475 break;
1476 break;
1477 case boardPCL813B:
1478 if (it->options[1] == 1)
1479 s->range_table = &range_pcl813b2_ai;
1480 break;
1481 case boardISO813:
1482 switch (it->options[1]) {
1483 case 0:
1484 s->range_table = &range_iso813_1_ai;
1485 break;
1486 case 1:
1487 s->range_table = &range_iso813_1_2_ai;
1488 break;
1489 case 2:
1490 s->range_table = &range_iso813_2_ai;
1491 devpriv->range_correction = 1;
1492 break;
1493 case 3:
1494 s->range_table = &range_iso813_2_2_ai;
1495 devpriv->range_correction = 1;
1496 break;
1497 default:
1498 s->range_table = &range_iso813_1_ai;
1499 break;
1500 printk
1501 (", incorrect range number %d, "
1502 "changing to 0 ", it->options[1]);
1503 break;
1504 }
1505 break;
1506 case boardACL8113:
1507 switch (it->options[1]) {
1508 case 0:
1509 s->range_table = &range_acl8113_1_ai;
1510 break;
1511 case 1:
1512 s->range_table = &range_acl8113_1_2_ai;
1513 break;
1514 case 2:
1515 s->range_table = &range_acl8113_2_ai;
1516 devpriv->range_correction = 1;
1517 break;
1518 case 3:
1519 s->range_table = &range_acl8113_2_2_ai;
1520 devpriv->range_correction = 1;
1521 break;
1522 default:
1523 s->range_table = &range_acl8113_1_ai;
1524 break;
1525 printk
1526 (", incorrect range number %d, "
1527 "changing to 0 ", it->options[1]);
1528 break;
1529 }
1530 break;
1531 }
1532 subdev++;
1533 }
1534
1535 /* analog output */
1536 if (board->n_aochan > 0) {
1537 s = dev->subdevices + subdev;
1538 s->type = COMEDI_SUBD_AO;
1539 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1540 s->n_chan = board->n_aochan;
1541 s->maxdata = 0xfff;
1542 s->len_chanlist = 1;
1543 s->range_table = board->rangelist_ao;
1544 s->insn_read = pcl812_ao_insn_read;
1545 s->insn_write = pcl812_ao_insn_write;
1546 switch (board->board_type) {
1547 case boardA821:
1548 if (it->options[3] == 1)
1549 s->range_table = &range_unipolar10;
1550 break;
1551 case boardPCL812:
1552 case boardACL8112:
1553 case boardPCL812PG:
1554 case boardACL8216:
1555 if (it->options[5] == 1)
1556 s->range_table = &range_unipolar10;
1557 if (it->options[5] == 2)
1558 s->range_table = &range_unknown;
1559 break;
1560 }
1561 subdev++;
1562 }
1563
1564 /* digital input */
1565 if (board->n_dichan > 0) {
1566 s = dev->subdevices + subdev;
1567 s->type = COMEDI_SUBD_DI;
1568 s->subdev_flags = SDF_READABLE;
1569 s->n_chan = board->n_dichan;
1570 s->maxdata = 1;
1571 s->len_chanlist = board->n_dichan;
1572 s->range_table = &range_digital;
1573 s->insn_bits = pcl812_di_insn_bits;
1574 subdev++;
1575 }
1576
1577 /* digital output */
1578 if (board->n_dochan > 0) {
1579 s = dev->subdevices + subdev;
1580 s->type = COMEDI_SUBD_DO;
1581 s->subdev_flags = SDF_WRITABLE;
1582 s->n_chan = board->n_dochan;
1583 s->maxdata = 1;
1584 s->len_chanlist = board->n_dochan;
1585 s->range_table = &range_digital;
1586 s->insn_bits = pcl812_do_insn_bits;
1587 subdev++;
1588 }
1589
1590 switch (board->board_type) {
1591 case boardACL8216:
1592 devpriv->ai_is16b = 1;
1593 case boardPCL812PG:
1594 case boardPCL812:
1595 case boardACL8112:
1596 devpriv->max_812_ai_mode0_rangewait = 1;
1597 if (it->options[3] > 0)
1598 /* we use external trigger */
1599 devpriv->use_ext_trg = 1;
1600 case boardA821:
1601 devpriv->max_812_ai_mode0_rangewait = 1;
1602 devpriv->mode_reg_int = (irq << 4) & 0xf0;
1603 break;
1604 case boardPCL813B:
1605 case boardPCL813:
1606 case boardISO813:
1607 case boardACL8113:
1608 /* maybe there must by greatest timeout */
1609 devpriv->max_812_ai_mode0_rangewait = 5;
1610 break;
1611 }
1612
1613 printk(KERN_INFO "\n");
1614 devpriv->valid = 1;
1615
1616 pcl812_reset(dev);
1617
1618 return 0;
1619 }
1620
1621 static void pcl812_detach(struct comedi_device *dev)
1622 {
1623 free_resources(dev);
1624 }
1625
1626 static const struct pcl812_board boardtypes[] = {
1627 {"pcl812", boardPCL812, 16, 0, 2, 16, 16, 0x0fff,
1628 33000, 500, &range_bipolar10, &range_unipolar5,
1629 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1630 {"pcl812pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
1631 33000, 500, &range_pcl812pg_ai, &range_unipolar5,
1632 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1633 {"acl8112pg", boardPCL812PG, 16, 0, 2, 16, 16, 0x0fff,
1634 10000, 500, &range_pcl812pg_ai, &range_unipolar5,
1635 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1636 {"acl8112dg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1637 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
1638 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1639 {"acl8112hg", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1640 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
1641 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1642 {"a821pgl", boardA821, 16, 8, 1, 16, 16, 0x0fff,
1643 10000, 500, &range_pcl813b_ai, &range_unipolar5,
1644 0x000c, 0x00, PCLx1x_IORANGE, 0},
1645 {"a821pglnda", boardA821, 16, 8, 0, 0, 0, 0x0fff,
1646 10000, 500, &range_pcl813b_ai, NULL,
1647 0x000c, 0x00, PCLx1x_IORANGE, 0},
1648 {"a821pgh", boardA821, 16, 8, 1, 16, 16, 0x0fff,
1649 10000, 500, &range_a821pgh_ai, &range_unipolar5,
1650 0x000c, 0x00, PCLx1x_IORANGE, 0},
1651 {"a822pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1652 10000, 500, &range_acl8112dg_ai, &range_unipolar5,
1653 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1654 {"a822pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1655 10000, 500, &range_acl8112hg_ai, &range_unipolar5,
1656 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1657 {"a823pgl", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1658 8000, 500, &range_acl8112dg_ai, &range_unipolar5,
1659 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1660 {"a823pgh", boardACL8112, 16, 8, 2, 16, 16, 0x0fff,
1661 8000, 500, &range_acl8112hg_ai, &range_unipolar5,
1662 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1663 {"pcl813", boardPCL813, 32, 0, 0, 0, 0, 0x0fff,
1664 0, 0, &range_pcl813b_ai, NULL,
1665 0x0000, 0x00, PCLx1x_IORANGE, 0},
1666 {"pcl813b", boardPCL813B, 32, 0, 0, 0, 0, 0x0fff,
1667 0, 0, &range_pcl813b_ai, NULL,
1668 0x0000, 0x00, PCLx1x_IORANGE, 0},
1669 {"acl8113", boardACL8113, 32, 0, 0, 0, 0, 0x0fff,
1670 0, 0, &range_acl8113_1_ai, NULL,
1671 0x0000, 0x00, PCLx1x_IORANGE, 0},
1672 {"iso813", boardISO813, 32, 0, 0, 0, 0, 0x0fff,
1673 0, 0, &range_iso813_1_ai, NULL,
1674 0x0000, 0x00, PCLx1x_IORANGE, 0},
1675 {"acl8216", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
1676 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
1677 0xdcfc, 0x0a, PCLx1x_IORANGE, 1},
1678 {"a826pg", boardACL8216, 16, 8, 2, 16, 16, 0xffff,
1679 10000, 500, &range_pcl813b2_ai, &range_unipolar5,
1680 0xdcfc, 0x0a, PCLx1x_IORANGE, 0},
1681 };
1682
1683 static struct comedi_driver pcl812_driver = {
1684 .driver_name = "pcl812",
1685 .module = THIS_MODULE,
1686 .attach = pcl812_attach,
1687 .detach = pcl812_detach,
1688 .board_name = &boardtypes[0].name,
1689 .num_names = ARRAY_SIZE(boardtypes),
1690 .offset = sizeof(struct pcl812_board),
1691 };
1692 module_comedi_driver(pcl812_driver);
1693
1694 MODULE_AUTHOR("Comedi http://www.comedi.org");
1695 MODULE_DESCRIPTION("Comedi low-level driver");
1696 MODULE_LICENSE("GPL");
This page took 0.091029 seconds and 5 git commands to generate.