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