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