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