4f195dbccba40d917ce76f2f1d8ead699da8ece0
[platform/kernel/linux-rpi.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 <linux/module.h>
102 #include <linux/gfp.h>
103 #include <linux/delay.h>
104 #include <linux/io.h>
105 #include <linux/interrupt.h>
106 #include <asm/dma.h>
107
108 #include "../comedidev.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 /* W: clear INT request */
125 #define PCL818_CLRINT 8
126 /* R: return status byte */
127 #define PCL818_STATUS 8
128 /* R: A/D high byte W: A/D range control */
129 #define PCL818_RANGE 1
130 /* R: next mux scan channel W: mux scan channel & range control pointer */
131 #define PCL818_MUX 2
132 /* R/W: operation control register */
133 #define PCL818_CONTROL 9
134 /* W: counter enable */
135 #define PCL818_CNTENABLE 10
136
137 /* R: low byte of A/D W: soft A/D trigger */
138 #define PCL818_AD_LO 0
139 /* R: high byte of A/D W: A/D range control */
140 #define PCL818_AD_HI 1
141 /* W: D/A low&high byte */
142 #define PCL818_DA_LO 4
143 #define PCL818_DA_HI 5
144 /* R: low&high byte of DI */
145 #define PCL818_DI_LO 3
146 #define PCL818_DI_HI 11
147 /* W: low&high byte of DO */
148 #define PCL818_DO_LO 3
149 #define PCL818_DO_HI 11
150 /* W: PCL718 second D/A */
151 #define PCL718_DA2_LO 6
152 #define PCL718_DA2_HI 7
153 /* counters */
154 #define PCL818_CTR0 12
155 #define PCL818_CTR1 13
156 #define PCL818_CTR2 14
157 /* W: counter control */
158 #define PCL818_CTRCTL 15
159
160 /* W: fifo enable/disable */
161 #define PCL818_FI_ENABLE 6
162 /* W: fifo interrupt clear */
163 #define PCL818_FI_INTCLR 20
164 /* W: fifo interrupt clear */
165 #define PCL818_FI_FLUSH 25
166 /* R: fifo status */
167 #define PCL818_FI_STATUS 25
168 /* R: one record from FIFO */
169 #define PCL818_FI_DATALO 23
170 #define PCL818_FI_DATAHI 23
171
172 /* type of interrupt handler */
173 #define INT_TYPE_AI1_INT 1
174 #define INT_TYPE_AI1_DMA 2
175 #define INT_TYPE_AI1_FIFO 3
176 #define INT_TYPE_AI3_INT 4
177 #define INT_TYPE_AI3_DMA 5
178 #define INT_TYPE_AI3_FIFO 6
179 #ifdef PCL818_MODE13_AO
180 #define INT_TYPE_AO1_INT 7
181 #define INT_TYPE_AO3_INT 8
182 #endif
183
184 #define MAGIC_DMA_WORD 0x5a5a
185
186 static const struct comedi_lrange range_pcl818h_ai = {
187         9, {
188                 BIP_RANGE(5),
189                 BIP_RANGE(2.5),
190                 BIP_RANGE(1.25),
191                 BIP_RANGE(0.625),
192                 UNI_RANGE(10),
193                 UNI_RANGE(5),
194                 UNI_RANGE(2.5),
195                 UNI_RANGE(1.25),
196                 BIP_RANGE(10)
197         }
198 };
199
200 static const struct comedi_lrange range_pcl818hg_ai = {
201         10, {
202                 BIP_RANGE(5),
203                 BIP_RANGE(0.5),
204                 BIP_RANGE(0.05),
205                 BIP_RANGE(0.005),
206                 UNI_RANGE(10),
207                 UNI_RANGE(1),
208                 UNI_RANGE(0.1),
209                 UNI_RANGE(0.01),
210                 BIP_RANGE(10),
211                 BIP_RANGE(1),
212                 BIP_RANGE(0.1),
213                 BIP_RANGE(0.01)
214         }
215 };
216
217 static const struct comedi_lrange range_pcl818l_l_ai = {
218         4, {
219                 BIP_RANGE(5),
220                 BIP_RANGE(2.5),
221                 BIP_RANGE(1.25),
222                 BIP_RANGE(0.625)
223         }
224 };
225
226 static const struct comedi_lrange range_pcl818l_h_ai = {
227         4, {
228                 BIP_RANGE(10),
229                 BIP_RANGE(5),
230                 BIP_RANGE(2.5),
231                 BIP_RANGE(1.25)
232         }
233 };
234
235 static const struct comedi_lrange range718_bipolar1 = {
236         1, {
237                 BIP_RANGE(1)
238         }
239 };
240
241 static const struct comedi_lrange range718_bipolar0_5 = {
242         1, {
243                 BIP_RANGE(0.5)
244         }
245 };
246
247 static const struct comedi_lrange range718_unipolar2 = {
248         1, {
249                 UNI_RANGE(2)
250         }
251 };
252
253 static const struct comedi_lrange range718_unipolar1 = {
254         1, {
255                 BIP_RANGE(1)
256         }
257 };
258
259 struct pcl818_board {
260         const char *name;
261         int n_ranges;
262         int n_aichan_se;
263         int n_aichan_diff;
264         unsigned int ns_min;
265         int n_aochan;
266         int n_dichan;
267         int n_dochan;
268         const struct comedi_lrange *ai_range_type;
269         const struct comedi_lrange *ao_range_type;
270         unsigned int IRQbits;
271         unsigned int DMAbits;
272         int ai_maxdata;
273         int ao_maxdata;
274         unsigned int has_fifo:1;
275         int is_818;
276 };
277
278 static const struct pcl818_board boardtypes[] = {
279         {
280                 .name           = "pcl818l",
281                 .n_ranges       = 4,
282                 .n_aichan_se    = 16,
283                 .n_aichan_diff  = 8,
284                 .ns_min         = 25000,
285                 .n_aochan       = 1,
286                 .n_dichan       = 16,
287                 .n_dochan       = 16,
288                 .ai_range_type  = &range_pcl818l_l_ai,
289                 .ao_range_type  = &range_unipolar5,
290                 .IRQbits        = 0x00fc,
291                 .DMAbits        = 0x0a,
292                 .ai_maxdata     = 0xfff,
293                 .ao_maxdata     = 0xfff,
294                 .is_818         = 1,
295         }, {
296                 .name           = "pcl818h",
297                 .n_ranges       = 9,
298                 .n_aichan_se    = 16,
299                 .n_aichan_diff  = 8,
300                 .ns_min         = 10000,
301                 .n_aochan       = 1,
302                 .n_dichan       = 16,
303                 .n_dochan       = 16,
304                 .ai_range_type  = &range_pcl818h_ai,
305                 .ao_range_type  = &range_unipolar5,
306                 .IRQbits        = 0x00fc,
307                 .DMAbits        = 0x0a,
308                 .ai_maxdata     = 0xfff,
309                 .ao_maxdata     = 0xfff,
310                 .is_818         = 1,
311         }, {
312                 .name           = "pcl818hd",
313                 .n_ranges       = 9,
314                 .n_aichan_se    = 16,
315                 .n_aichan_diff  = 8,
316                 .ns_min         = 10000,
317                 .n_aochan       = 1,
318                 .n_dichan       = 16,
319                 .n_dochan       = 16,
320                 .ai_range_type  = &range_pcl818h_ai,
321                 .ao_range_type  = &range_unipolar5,
322                 .IRQbits        = 0x00fc,
323                 .DMAbits        = 0x0a,
324                 .ai_maxdata     = 0xfff,
325                 .ao_maxdata     = 0xfff,
326                 .has_fifo       = 1,
327                 .is_818         = 1,
328         }, {
329                 .name           = "pcl818hg",
330                 .n_ranges       = 12,
331                 .n_aichan_se    = 16,
332                 .n_aichan_diff  = 8,
333                 .ns_min         = 10000,
334                 .n_aochan       = 1,
335                 .n_dichan       = 16,
336                 .n_dochan       = 16,
337                 .ai_range_type  = &range_pcl818hg_ai,
338                 .ao_range_type  = &range_unipolar5,
339                 .IRQbits        = 0x00fc,
340                 .DMAbits        = 0x0a,
341                 .ai_maxdata     = 0xfff,
342                 .ao_maxdata     = 0xfff,
343                 .has_fifo       = 1,
344                 .is_818         = 1,
345         }, {
346                 .name           = "pcl818",
347                 .n_ranges       = 9,
348                 .n_aichan_se    = 16,
349                 .n_aichan_diff  = 8,
350                 .ns_min         = 10000,
351                 .n_aochan       = 2,
352                 .n_dichan       = 16,
353                 .n_dochan       = 16,
354                 .ai_range_type  = &range_pcl818h_ai,
355                 .ao_range_type  = &range_unipolar5,
356                 .IRQbits        = 0x00fc,
357                 .DMAbits        = 0x0a,
358                 .ai_maxdata     = 0xfff,
359                 .ao_maxdata     = 0xfff,
360                 .is_818         = 1,
361         }, {
362                 .name           = "pcl718",
363                 .n_ranges       = 1,
364                 .n_aichan_se    = 16,
365                 .n_aichan_diff  = 8,
366                 .ns_min         = 16000,
367                 .n_aochan       = 2,
368                 .n_dichan       = 16,
369                 .n_dochan       = 16,
370                 .ai_range_type  = &range_unipolar5,
371                 .ao_range_type  = &range_unipolar5,
372                 .IRQbits        = 0x00fc,
373                 .DMAbits        = 0x0a,
374                 .ai_maxdata     = 0xfff,
375                 .ao_maxdata     = 0xfff,
376         }, {
377                 .name           = "pcm3718",
378                 .n_ranges       = 9,
379                 .n_aichan_se    = 16,
380                 .n_aichan_diff  = 8,
381                 .ns_min         = 10000,
382                 .n_dichan       = 16,
383                 .n_dochan       = 16,
384                 .ai_range_type  = &range_pcl818h_ai,
385                 .ao_range_type  = &range_unipolar5,
386                 .IRQbits        = 0x00fc,
387                 .DMAbits        = 0x0a,
388                 .ai_maxdata     = 0xfff,
389                 .ao_maxdata     = 0xfff,
390                 .is_818         = 1,
391         },
392 };
393
394 struct pcl818_private {
395
396         unsigned int dma;       /*  used DMA, 0=don't use DMA */
397         unsigned long dmabuf[2];        /*  pointers to begin of DMA buffers */
398         unsigned int dmapages[2];       /*  len of DMA buffers in PAGE_SIZEs */
399         unsigned int hwdmaptr[2];       /*  hardware address of DMA buffers */
400         unsigned int hwdmasize[2];      /*  len of DMA buffers in Bytes */
401         int next_dma_buf;       /*  which DMA buffer will be used next round */
402         long dma_runs_to_end;   /*  how many we must permorm DMA transfer to end of record */
403         unsigned long last_dma_run;     /*  how many bytes we must transfer on last DMA page */
404         unsigned char neverending_ai;   /*  if=1, then we do neverending record (you must use cancel()) */
405         unsigned int ns_min;    /*  manimal allowed delay between samples (in us) for actual card */
406         int i8253_osc_base;     /*  1/frequency of on board oscilator in ns */
407         int irq_blocked;        /*  1=IRQ now uses any subdev */
408         int irq_was_now_closed; /*  when IRQ finish, there's stored int818_mode for last interrupt */
409         int ai_mode;            /*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
410         struct comedi_subdevice *last_int_sub;  /*  ptr to subdevice which now finish */
411         int ai_act_scan;        /*  how many scans we finished */
412         int ai_act_chan;        /*  actual position in actual scan */
413         unsigned int act_chanlist[16];  /*  MUX setting for actual AI operations */
414         unsigned int act_chanlist_len;  /*  how long is actual MUX list */
415         unsigned int act_chanlist_pos;  /*  actual position in MUX list */
416         unsigned int ai_scans;  /*  len of scanlist */
417         unsigned int ai_n_chan; /*  how many channels is measured */
418         unsigned int *ai_chanlist;      /*  actaul chanlist */
419         unsigned int ai_flags;  /*  flaglist */
420         unsigned int ai_data_len;       /*  len of data buffer */
421         unsigned int ai_timer1; /*  timers */
422         unsigned int ai_timer2;
423         unsigned char usefifo;  /*  1=use fifo */
424         unsigned int ao_readback[2];
425 };
426
427 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,      /*  used for gain list programming */
428         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
429 };
430
431 /*
432 ==============================================================================
433 */
434 static void setup_channel_list(struct comedi_device *dev,
435                                struct comedi_subdevice *s,
436                                unsigned int *chanlist, unsigned int n_chan,
437                                unsigned int seglen);
438 static int check_channel_list(struct comedi_device *dev,
439                               struct comedi_subdevice *s,
440                               unsigned int *chanlist, unsigned int n_chan);
441
442 static int pcl818_ai_cancel(struct comedi_device *dev,
443                             struct comedi_subdevice *s);
444 static void start_pacer(struct comedi_device *dev, int mode,
445                         unsigned int divisor1, unsigned int divisor2);
446
447 static int pcl818_ai_eoc(struct comedi_device *dev,
448                          struct comedi_subdevice *s,
449                          struct comedi_insn *insn,
450                          unsigned long context)
451 {
452         unsigned int status;
453
454         status = inb(dev->iobase + PCL818_STATUS);
455         if (status & 0x10)
456                 return 0;
457         return -EBUSY;
458 }
459
460 static int pcl818_ai_insn_read(struct comedi_device *dev,
461                                struct comedi_subdevice *s,
462                                struct comedi_insn *insn, unsigned int *data)
463 {
464         int ret;
465         int n;
466
467         /* software trigger, DMA and INT off */
468         outb(0, dev->iobase + PCL818_CONTROL);
469
470         /* select channel */
471         outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
472
473         /* select gain */
474         outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
475
476         for (n = 0; n < insn->n; n++) {
477
478                 /* clear INT (conversion end) flag */
479                 outb(0, dev->iobase + PCL818_CLRINT);
480
481                 /* start conversion */
482                 outb(0, dev->iobase + PCL818_AD_LO);
483
484                 ret = comedi_timeout(dev, s, insn, pcl818_ai_eoc, 0);
485                 if (ret) {
486                         /* clear INT (conversion end) flag */
487                         outb(0, dev->iobase + PCL818_CLRINT);
488                         return ret;
489                 }
490
491                 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
492                            (inb(dev->iobase + PCL818_AD_LO) >> 4));
493         }
494
495         return n;
496 }
497
498 /*
499 ==============================================================================
500    ANALOG OUTPUT MODE0, 818 cards
501    only one sample per call is supported
502 */
503 static int pcl818_ao_insn_read(struct comedi_device *dev,
504                                struct comedi_subdevice *s,
505                                struct comedi_insn *insn, unsigned int *data)
506 {
507         struct pcl818_private *devpriv = dev->private;
508         int n;
509         int chan = CR_CHAN(insn->chanspec);
510
511         for (n = 0; n < insn->n; n++)
512                 data[n] = devpriv->ao_readback[chan];
513
514         return n;
515 }
516
517 static int pcl818_ao_insn_write(struct comedi_device *dev,
518                                 struct comedi_subdevice *s,
519                                 struct comedi_insn *insn, unsigned int *data)
520 {
521         struct pcl818_private *devpriv = dev->private;
522         int n;
523         int chan = CR_CHAN(insn->chanspec);
524
525         for (n = 0; n < insn->n; n++) {
526                 devpriv->ao_readback[chan] = data[n];
527                 outb((data[n] & 0x000f) << 4, dev->iobase +
528                      (chan ? PCL718_DA2_LO : PCL818_DA_LO));
529                 outb((data[n] & 0x0ff0) >> 4, dev->iobase +
530                      (chan ? PCL718_DA2_HI : PCL818_DA_HI));
531         }
532
533         return n;
534 }
535
536 /*
537 ==============================================================================
538    DIGITAL INPUT MODE0, 818 cards
539
540    only one sample per call is supported
541 */
542 static int pcl818_di_insn_bits(struct comedi_device *dev,
543                                struct comedi_subdevice *s,
544                                struct comedi_insn *insn, unsigned int *data)
545 {
546         data[1] = inb(dev->iobase + PCL818_DI_LO) |
547             (inb(dev->iobase + PCL818_DI_HI) << 8);
548
549         return insn->n;
550 }
551
552 static int pcl818_do_insn_bits(struct comedi_device *dev,
553                                struct comedi_subdevice *s,
554                                struct comedi_insn *insn,
555                                unsigned int *data)
556 {
557         if (comedi_dio_update_state(s, data)) {
558                 outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
559                 outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
560         }
561
562         data[1] = s->state;
563
564         return insn->n;
565 }
566
567 /*
568 ==============================================================================
569    analog input interrupt mode 1 & 3, 818 cards
570    one sample per interrupt version
571 */
572 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
573 {
574         struct comedi_device *dev = d;
575         struct pcl818_private *devpriv = dev->private;
576         struct comedi_subdevice *s = dev->read_subdev;
577         unsigned char low;
578         int timeout = 50;       /* wait max 50us */
579
580         while (timeout--) {
581                 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
582                         goto conv_finish;
583                 udelay(1);
584         }
585         outb(0, dev->iobase + PCL818_STATUS);   /* clear INT request */
586         comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
587         pcl818_ai_cancel(dev, s);
588         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
589         comedi_event(dev, s);
590         return IRQ_HANDLED;
591
592 conv_finish:
593         low = inb(dev->iobase + PCL818_AD_LO);
594         comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));        /*  get one sample */
595         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
596
597         if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
598                 dev_dbg(dev->class_dev,
599                         "A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
600                         (low & 0xf),
601                         devpriv->act_chanlist[devpriv->act_chanlist_pos]);
602                 pcl818_ai_cancel(dev, s);
603                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
604                 comedi_event(dev, s);
605                 return IRQ_HANDLED;
606         }
607         devpriv->act_chanlist_pos++;
608         if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
609                 devpriv->act_chanlist_pos = 0;
610
611         s->async->cur_chan++;
612         if (s->async->cur_chan >= devpriv->ai_n_chan) {
613                 s->async->cur_chan = 0;
614                 devpriv->ai_act_scan--;
615         }
616
617         if (!devpriv->neverending_ai) {
618                 if (devpriv->ai_act_scan == 0) {        /* all data sampled */
619                         pcl818_ai_cancel(dev, s);
620                         s->async->events |= COMEDI_CB_EOA;
621                 }
622         }
623         comedi_event(dev, s);
624         return IRQ_HANDLED;
625 }
626
627 /*
628 ==============================================================================
629    analog input dma mode 1 & 3, 818 cards
630 */
631 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
632 {
633         struct comedi_device *dev = d;
634         struct pcl818_private *devpriv = dev->private;
635         struct comedi_subdevice *s = dev->read_subdev;
636         int i, len, bufptr;
637         unsigned long flags;
638         unsigned short *ptr;
639
640         disable_dma(devpriv->dma);
641         devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
642         if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {       /*  switch dma bufs */
643                 set_dma_mode(devpriv->dma, DMA_MODE_READ);
644                 flags = claim_dma_lock();
645                 set_dma_addr(devpriv->dma,
646                              devpriv->hwdmaptr[devpriv->next_dma_buf]);
647                 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
648                         set_dma_count(devpriv->dma,
649                                       devpriv->hwdmasize[devpriv->
650                                                          next_dma_buf]);
651                 } else {
652                         set_dma_count(devpriv->dma, devpriv->last_dma_run);
653                 }
654                 release_dma_lock(flags);
655                 enable_dma(devpriv->dma);
656         }
657
658         devpriv->dma_runs_to_end--;
659         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
660         ptr = (unsigned short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
661
662         len = devpriv->hwdmasize[0] >> 1;
663         bufptr = 0;
664
665         for (i = 0; i < len; i++) {
666                 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
667                         dev_dbg(dev->class_dev,
668                                 "A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
669                                 (ptr[bufptr] & 0xf),
670                                 devpriv->act_chanlist[devpriv->act_chanlist_pos],
671                                 devpriv->act_chanlist_pos);
672                         pcl818_ai_cancel(dev, s);
673                         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
674                         comedi_event(dev, s);
675                         return IRQ_HANDLED;
676                 }
677
678                 comedi_buf_put(s->async, ptr[bufptr++] >> 4);   /*  get one sample */
679
680                 devpriv->act_chanlist_pos++;
681                 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
682                         devpriv->act_chanlist_pos = 0;
683
684                 s->async->cur_chan++;
685                 if (s->async->cur_chan >= devpriv->ai_n_chan) {
686                         s->async->cur_chan = 0;
687                         devpriv->ai_act_scan--;
688                 }
689
690                 if (!devpriv->neverending_ai)
691                         if (devpriv->ai_act_scan == 0) {        /* all data sampled */
692                                 pcl818_ai_cancel(dev, s);
693                                 s->async->events |= COMEDI_CB_EOA;
694                                 comedi_event(dev, s);
695                                 return IRQ_HANDLED;
696                         }
697         }
698
699         if (len > 0)
700                 comedi_event(dev, s);
701         return IRQ_HANDLED;
702 }
703
704 /*
705 ==============================================================================
706    analog input interrupt mode 1 & 3, 818HD/HG cards
707 */
708 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
709 {
710         struct comedi_device *dev = d;
711         struct pcl818_private *devpriv = dev->private;
712         struct comedi_subdevice *s = dev->read_subdev;
713         int i, len;
714         unsigned char lo;
715
716         outb(0, dev->iobase + PCL818_FI_INTCLR);        /*  clear fifo int request */
717
718         lo = inb(dev->iobase + PCL818_FI_STATUS);
719
720         if (lo & 4) {
721                 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
722                 pcl818_ai_cancel(dev, s);
723                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
724                 comedi_event(dev, s);
725                 return IRQ_HANDLED;
726         }
727
728         if (lo & 1) {
729                 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
730                 pcl818_ai_cancel(dev, s);
731                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
732                 comedi_event(dev, s);
733                 return IRQ_HANDLED;
734         }
735
736         if (lo & 2)
737                 len = 512;
738         else
739                 len = 0;
740
741         for (i = 0; i < len; i++) {
742                 lo = inb(dev->iobase + PCL818_FI_DATALO);
743                 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {   /*  dropout! */
744                         dev_dbg(dev->class_dev,
745                                 "A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
746                                 (lo & 0xf),
747                                 devpriv->act_chanlist[devpriv->act_chanlist_pos]);
748                         pcl818_ai_cancel(dev, s);
749                         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
750                         comedi_event(dev, s);
751                         return IRQ_HANDLED;
752                 }
753
754                 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));       /*  get one sample */
755
756                 devpriv->act_chanlist_pos++;
757                 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
758                         devpriv->act_chanlist_pos = 0;
759
760                 s->async->cur_chan++;
761                 if (s->async->cur_chan >= devpriv->ai_n_chan) {
762                         s->async->cur_chan = 0;
763                         devpriv->ai_act_scan--;
764                 }
765
766                 if (!devpriv->neverending_ai)
767                         if (devpriv->ai_act_scan == 0) {        /* all data sampled */
768                                 pcl818_ai_cancel(dev, s);
769                                 s->async->events |= COMEDI_CB_EOA;
770                                 comedi_event(dev, s);
771                                 return IRQ_HANDLED;
772                         }
773         }
774
775         if (len > 0)
776                 comedi_event(dev, s);
777         return IRQ_HANDLED;
778 }
779
780 /*
781 ==============================================================================
782     INT procedure
783 */
784 static irqreturn_t interrupt_pcl818(int irq, void *d)
785 {
786         struct comedi_device *dev = d;
787         struct pcl818_private *devpriv = dev->private;
788
789         if (!dev->attached) {
790                 comedi_error(dev, "premature interrupt");
791                 return IRQ_HANDLED;
792         }
793
794         if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
795                 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
796                                                  devpriv->ai_act_scan > 0)) &&
797                     (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
798                      devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
799                         /* The cleanup from ai_cancel() has been delayed
800                            until now because the card doesn't seem to like
801                            being reprogrammed while a DMA transfer is in
802                            progress.
803                          */
804                         devpriv->ai_act_scan = 0;
805                         devpriv->neverending_ai = 0;
806                         pcl818_ai_cancel(dev, dev->read_subdev);
807                 }
808
809                 outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
810
811                 return IRQ_HANDLED;
812         }
813
814         switch (devpriv->ai_mode) {
815         case INT_TYPE_AI1_DMA:
816         case INT_TYPE_AI3_DMA:
817                 return interrupt_pcl818_ai_mode13_dma(irq, d);
818         case INT_TYPE_AI1_INT:
819         case INT_TYPE_AI3_INT:
820                 return interrupt_pcl818_ai_mode13_int(irq, d);
821         case INT_TYPE_AI1_FIFO:
822         case INT_TYPE_AI3_FIFO:
823                 return interrupt_pcl818_ai_mode13_fifo(irq, d);
824 #ifdef PCL818_MODE13_AO
825         case INT_TYPE_AO1_INT:
826         case INT_TYPE_AO3_INT:
827                 return interrupt_pcl818_ao_mode13_int(irq, d);
828 #endif
829         default:
830                 break;
831         }
832
833         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
834
835         if (!devpriv->irq_blocked || !devpriv->ai_mode) {
836                 comedi_error(dev, "bad IRQ!");
837                 return IRQ_NONE;
838         }
839
840         comedi_error(dev, "IRQ from unknown source!");
841         return IRQ_NONE;
842 }
843
844 /*
845 ==============================================================================
846    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
847 */
848 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
849                                     struct comedi_subdevice *s)
850 {
851         struct pcl818_private *devpriv = dev->private;
852         unsigned int flags;
853         unsigned int bytes;
854
855         disable_dma(devpriv->dma);      /*  disable dma */
856         bytes = devpriv->hwdmasize[0];
857         if (!devpriv->neverending_ai) {
858                 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /*  how many */
859                 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];       /*  how many DMA pages we must fiil */
860                 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];  /* on last dma transfer must be moved */
861                 devpriv->dma_runs_to_end--;
862                 if (devpriv->dma_runs_to_end >= 0)
863                         bytes = devpriv->hwdmasize[0];
864         }
865
866         devpriv->next_dma_buf = 0;
867         set_dma_mode(devpriv->dma, DMA_MODE_READ);
868         flags = claim_dma_lock();
869         clear_dma_ff(devpriv->dma);
870         set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
871         set_dma_count(devpriv->dma, bytes);
872         release_dma_lock(flags);
873         enable_dma(devpriv->dma);
874
875         if (mode == 1) {
876                 devpriv->ai_mode = INT_TYPE_AI1_DMA;
877                 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ+DMA */
878         } else {
879                 devpriv->ai_mode = INT_TYPE_AI3_DMA;
880                 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ+DMA */
881         }
882 }
883
884 /*
885 ==============================================================================
886    ANALOG INPUT MODE 1 or 3, 818 cards
887 */
888 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
889                               struct comedi_subdevice *s)
890 {
891         struct pcl818_private *devpriv = dev->private;
892         struct comedi_cmd *cmd = &s->async->cmd;
893         int divisor1 = 0, divisor2 = 0;
894         unsigned int seglen;
895
896         if (devpriv->irq_blocked)
897                 return -EBUSY;
898
899         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
900
901         seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
902                                     devpriv->ai_n_chan);
903         if (seglen < 1)
904                 return -EINVAL;
905         setup_channel_list(dev, s, devpriv->ai_chanlist,
906                            devpriv->ai_n_chan, seglen);
907
908         udelay(1);
909
910         devpriv->ai_act_scan = devpriv->ai_scans;
911         devpriv->ai_act_chan = 0;
912         devpriv->irq_blocked = 1;
913         devpriv->irq_was_now_closed = 0;
914         devpriv->neverending_ai = 0;
915         devpriv->act_chanlist_pos = 0;
916         devpriv->dma_runs_to_end = 0;
917
918         if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
919                 devpriv->neverending_ai = 1;    /* well, user want neverending */
920
921         if (mode == 1) {
922                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
923                                           &divisor1, &divisor2,
924                                           &cmd->convert_arg,
925                                           TRIG_ROUND_NEAREST);
926                 if (divisor1 == 1) {    /* PCL718/818 crash if any divisor is set to 1 */
927                         divisor1 = 2;
928                         divisor2 /= 2;
929                 }
930                 if (divisor2 == 1) {
931                         divisor2 = 2;
932                         divisor1 /= 2;
933                 }
934         }
935
936         outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
937
938         switch (devpriv->dma) {
939         case 1:         /*  DMA */
940         case 3:
941                 pcl818_ai_mode13dma_int(mode, dev, s);
942                 break;
943         case 0:
944                 if (!devpriv->usefifo) {
945                         /* IRQ */
946                         if (mode == 1) {
947                                 devpriv->ai_mode = INT_TYPE_AI1_INT;
948                                 /* Pacer+IRQ */
949                                 outb(0x83 | (dev->irq << 4),
950                                      dev->iobase + PCL818_CONTROL);
951                         } else {
952                                 devpriv->ai_mode = INT_TYPE_AI3_INT;
953                                 /* Ext trig+IRQ */
954                                 outb(0x82 | (dev->irq << 4),
955                                      dev->iobase + PCL818_CONTROL);
956                         }
957                 } else {
958                         /* FIFO */
959                         /* enable FIFO */
960                         outb(1, dev->iobase + PCL818_FI_ENABLE);
961                         if (mode == 1) {
962                                 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
963                                 /* Pacer */
964                                 outb(0x03, dev->iobase + PCL818_CONTROL);
965                         } else {
966                                 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
967                                 outb(0x02, dev->iobase + PCL818_CONTROL);
968                         }
969                 }
970         }
971
972         start_pacer(dev, mode, divisor1, divisor2);
973
974         return 0;
975 }
976
977 /*
978 ==============================================================================
979  Start/stop pacer onboard pacer
980 */
981 static void start_pacer(struct comedi_device *dev, int mode,
982                         unsigned int divisor1, unsigned int divisor2)
983 {
984         outb(0xb4, dev->iobase + PCL818_CTRCTL);
985         outb(0x74, dev->iobase + PCL818_CTRCTL);
986         udelay(1);
987
988         if (mode == 1) {
989                 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
990                 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
991                 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
992                 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
993         }
994 }
995
996 /*
997 ==============================================================================
998  Check if channel list from user is builded correctly
999  If it's ok, then program scan/gain logic
1000 */
1001 static int check_channel_list(struct comedi_device *dev,
1002                               struct comedi_subdevice *s,
1003                               unsigned int *chanlist, unsigned int n_chan)
1004 {
1005         unsigned int chansegment[16];
1006         unsigned int i, nowmustbechan, seglen, segpos;
1007
1008         /* correct channel and range number check itself comedi/range.c */
1009         if (n_chan < 1) {
1010                 comedi_error(dev, "range/channel list is empty!");
1011                 return 0;
1012         }
1013
1014         if (n_chan > 1) {
1015                 /*  first channel is every time ok */
1016                 chansegment[0] = chanlist[0];
1017                 /*  build part of chanlist */
1018                 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1019                         /* we detect loop, this must by finish */
1020
1021                         if (chanlist[0] == chanlist[i])
1022                                 break;
1023                         nowmustbechan =
1024                             (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1025                         if (nowmustbechan != CR_CHAN(chanlist[i])) {    /*  channel list isn't continuous :-( */
1026                                 dev_dbg(dev->class_dev,
1027                                         "channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
1028                                         i, CR_CHAN(chanlist[i]), nowmustbechan,
1029                                         CR_CHAN(chanlist[0]));
1030                                 return 0;
1031                         }
1032                         /*  well, this is next correct channel in list */
1033                         chansegment[i] = chanlist[i];
1034                 }
1035
1036                 /*  check whole chanlist */
1037                 for (i = 0, segpos = 0; i < n_chan; i++) {
1038                         if (chanlist[i] != chansegment[i % seglen]) {
1039                                 dev_dbg(dev->class_dev,
1040                                         "bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1041                                         i, CR_CHAN(chansegment[i]),
1042                                         CR_RANGE(chansegment[i]),
1043                                         CR_AREF(chansegment[i]),
1044                                         CR_CHAN(chanlist[i % seglen]),
1045                                         CR_RANGE(chanlist[i % seglen]),
1046                                         CR_AREF(chansegment[i % seglen]));
1047                                 return 0;       /*  chan/gain list is strange */
1048                         }
1049                 }
1050         } else {
1051                 seglen = 1;
1052         }
1053         return seglen;
1054 }
1055
1056 static void setup_channel_list(struct comedi_device *dev,
1057                                struct comedi_subdevice *s,
1058                                unsigned int *chanlist, unsigned int n_chan,
1059                                unsigned int seglen)
1060 {
1061         struct pcl818_private *devpriv = dev->private;
1062         int i;
1063
1064         devpriv->act_chanlist_len = seglen;
1065         devpriv->act_chanlist_pos = 0;
1066
1067         for (i = 0; i < seglen; i++) {  /*  store range list to card */
1068                 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1069                 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);       /* select channel */
1070                 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);        /* select gain */
1071         }
1072
1073         udelay(1);
1074
1075         /* select channel interval to scan */
1076         outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1077                                                                1] << 4),
1078              dev->iobase + PCL818_MUX);
1079 }
1080
1081 /*
1082 ==============================================================================
1083  Check if board is switched to SE (1) or DIFF(0) mode
1084 */
1085 static int check_single_ended(unsigned int port)
1086 {
1087         if (inb(port + PCL818_STATUS) & 0x20)
1088                 return 1;
1089         return 0;
1090 }
1091
1092 /*
1093 ==============================================================================
1094 */
1095 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1096                       struct comedi_cmd *cmd)
1097 {
1098         const struct pcl818_board *board = comedi_board(dev);
1099         struct pcl818_private *devpriv = dev->private;
1100         int err = 0;
1101         int tmp, divisor1 = 0, divisor2 = 0;
1102
1103         /* Step 1 : check if triggers are trivially valid */
1104
1105         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
1106         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
1107         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
1108         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1109         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1110
1111         if (err)
1112                 return 1;
1113
1114         /* Step 2a : make sure trigger sources are unique */
1115
1116         err |= cfc_check_trigger_is_unique(cmd->convert_src);
1117         err |= cfc_check_trigger_is_unique(cmd->stop_src);
1118
1119         /* Step 2b : and mutually compatible */
1120
1121         if (err)
1122                 return 2;
1123
1124         /* Step 3: check if arguments are trivially valid */
1125
1126         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1127         err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1128
1129         if (cmd->convert_src == TRIG_TIMER)
1130                 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1131                                                  board->ns_min);
1132         else    /* TRIG_EXT */
1133                 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1134
1135         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1136
1137         if (cmd->stop_src == TRIG_COUNT)
1138                 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1139         else    /* TRIG_NONE */
1140                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1141
1142         if (err)
1143                 return 3;
1144
1145         /* step 4: fix up any arguments */
1146
1147         if (cmd->convert_src == TRIG_TIMER) {
1148                 tmp = cmd->convert_arg;
1149                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base,
1150                                           &divisor1, &divisor2,
1151                                           &cmd->convert_arg, cmd->flags);
1152                 if (cmd->convert_arg < board->ns_min)
1153                         cmd->convert_arg = board->ns_min;
1154                 if (tmp != cmd->convert_arg)
1155                         err++;
1156         }
1157
1158         if (err)
1159                 return 4;
1160
1161         /* step 5: complain about special chanlist considerations */
1162
1163         if (cmd->chanlist) {
1164                 if (!check_channel_list(dev, s, cmd->chanlist,
1165                                         cmd->chanlist_len))
1166                         return 5;       /*  incorrect channels list */
1167         }
1168
1169         return 0;
1170 }
1171
1172 /*
1173 ==============================================================================
1174 */
1175 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1176 {
1177         struct pcl818_private *devpriv = dev->private;
1178         struct comedi_cmd *cmd = &s->async->cmd;
1179         int retval;
1180
1181         devpriv->ai_n_chan = cmd->chanlist_len;
1182         devpriv->ai_chanlist = cmd->chanlist;
1183         devpriv->ai_flags = cmd->flags;
1184         devpriv->ai_data_len = s->async->prealloc_bufsz;
1185         devpriv->ai_timer1 = 0;
1186         devpriv->ai_timer2 = 0;
1187
1188         if (cmd->stop_src == TRIG_COUNT)
1189                 devpriv->ai_scans = cmd->stop_arg;
1190         else
1191                 devpriv->ai_scans = 0;
1192
1193         if (cmd->scan_begin_src == TRIG_FOLLOW) {       /*  mode 1, 3 */
1194                 if (cmd->convert_src == TRIG_TIMER) {   /*  mode 1 */
1195                         devpriv->ai_timer1 = cmd->convert_arg;
1196                         retval = pcl818_ai_cmd_mode(1, dev, s);
1197                         return retval;
1198                 }
1199                 if (cmd->convert_src == TRIG_EXT) {     /*  mode 3 */
1200                         return pcl818_ai_cmd_mode(3, dev, s);
1201                 }
1202         }
1203
1204         return -1;
1205 }
1206
1207 /*
1208 ==============================================================================
1209  cancel any mode 1-4 AI
1210 */
1211 static int pcl818_ai_cancel(struct comedi_device *dev,
1212                             struct comedi_subdevice *s)
1213 {
1214         struct pcl818_private *devpriv = dev->private;
1215
1216         if (devpriv->irq_blocked > 0) {
1217                 devpriv->irq_was_now_closed = 1;
1218
1219                 switch (devpriv->ai_mode) {
1220                 case INT_TYPE_AI1_DMA:
1221                 case INT_TYPE_AI3_DMA:
1222                         if (devpriv->neverending_ai ||
1223                             (!devpriv->neverending_ai &&
1224                              devpriv->ai_act_scan > 0)) {
1225                                 /* wait for running dma transfer to end, do cleanup in interrupt */
1226                                 goto end;
1227                         }
1228                         disable_dma(devpriv->dma);
1229                 case INT_TYPE_AI1_INT:
1230                 case INT_TYPE_AI3_INT:
1231                 case INT_TYPE_AI1_FIFO:
1232                 case INT_TYPE_AI3_FIFO:
1233 #ifdef PCL818_MODE13_AO
1234                 case INT_TYPE_AO1_INT:
1235                 case INT_TYPE_AO3_INT:
1236 #endif
1237                         outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);   /* Stop A/D */
1238                         udelay(1);
1239                         start_pacer(dev, -1, 0, 0);
1240                         outb(0, dev->iobase + PCL818_AD_LO);
1241                         inb(dev->iobase + PCL818_AD_LO);
1242                         inb(dev->iobase + PCL818_AD_HI);
1243                         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
1244                         outb(0, dev->iobase + PCL818_CONTROL);  /* Stop A/D */
1245                         if (devpriv->usefifo) { /*  FIFO shutdown */
1246                                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1247                                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1248                                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1249                         }
1250                         devpriv->irq_blocked = 0;
1251                         devpriv->last_int_sub = s;
1252                         devpriv->neverending_ai = 0;
1253                         devpriv->ai_mode = 0;
1254                         devpriv->irq_was_now_closed = 0;
1255                         break;
1256                 }
1257         }
1258
1259 end:
1260         return 0;
1261 }
1262
1263 /*
1264 ==============================================================================
1265  chech for PCL818
1266 */
1267 static int pcl818_check(unsigned long iobase)
1268 {
1269         outb(0x00, iobase + PCL818_MUX);
1270         udelay(1);
1271         if (inb(iobase + PCL818_MUX) != 0x00)
1272                 return 1;       /* there isn't card */
1273         outb(0x55, iobase + PCL818_MUX);
1274         udelay(1);
1275         if (inb(iobase + PCL818_MUX) != 0x55)
1276                 return 1;       /* there isn't card */
1277         outb(0x00, iobase + PCL818_MUX);
1278         udelay(1);
1279         outb(0x18, iobase + PCL818_CONTROL);
1280         udelay(1);
1281         if (inb(iobase + PCL818_CONTROL) != 0x18)
1282                 return 1;       /* there isn't card */
1283         return 0;               /*  ok, card exist */
1284 }
1285
1286 /*
1287 ==============================================================================
1288  reset whole PCL-818 cards
1289 */
1290 static void pcl818_reset(struct comedi_device *dev)
1291 {
1292         const struct pcl818_board *board = comedi_board(dev);
1293         struct pcl818_private *devpriv = dev->private;
1294
1295         if (devpriv->usefifo) { /*  FIFO shutdown */
1296                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1297                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1298                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1299         }
1300         outb(0, dev->iobase + PCL818_DA_LO);    /*  DAC=0V */
1301         outb(0, dev->iobase + PCL818_DA_HI);
1302         udelay(1);
1303         outb(0, dev->iobase + PCL818_DO_HI);    /*  DO=$0000 */
1304         outb(0, dev->iobase + PCL818_DO_LO);
1305         udelay(1);
1306         outb(0, dev->iobase + PCL818_CONTROL);
1307         outb(0, dev->iobase + PCL818_CNTENABLE);
1308         outb(0, dev->iobase + PCL818_MUX);
1309         outb(0, dev->iobase + PCL818_CLRINT);
1310         outb(0xb0, dev->iobase + PCL818_CTRCTL);        /* Stop pacer */
1311         outb(0x70, dev->iobase + PCL818_CTRCTL);
1312         outb(0x30, dev->iobase + PCL818_CTRCTL);
1313         if (board->is_818) {
1314                 outb(0, dev->iobase + PCL818_RANGE);
1315         } else {
1316                 outb(0, dev->iobase + PCL718_DA2_LO);
1317                 outb(0, dev->iobase + PCL718_DA2_HI);
1318         }
1319 }
1320
1321 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1322 {
1323         const struct pcl818_board *board = comedi_board(dev);
1324         struct pcl818_private *devpriv;
1325         int ret;
1326         int dma;
1327         unsigned long pages;
1328         struct comedi_subdevice *s;
1329
1330         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1331         if (!devpriv)
1332                 return -ENOMEM;
1333
1334         /* should we use the FIFO? */
1335         if (board->has_fifo && it->options[2] == -1)
1336                 devpriv->usefifo = 1;
1337
1338         ret = comedi_request_region(dev, it->options[0],
1339                                     devpriv->usefifo ? 0x20 : 0x10);
1340         if (ret)
1341                 return ret;
1342
1343         if (pcl818_check(dev->iobase)) {
1344                 comedi_error(dev, "I can't detect board. FAIL!\n");
1345                 return -EIO;
1346         }
1347
1348         if ((1 << it->options[1]) & board->IRQbits) {
1349                 ret = request_irq(it->options[1], interrupt_pcl818, 0,
1350                                   dev->board_name, dev);
1351                 if (ret == 0)
1352                         dev->irq = it->options[1];
1353         }
1354
1355         devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1356         devpriv->ai_mode = 0;   /* mode of irq */
1357
1358         /* grab our DMA */
1359         dma = 0;
1360         devpriv->dma = dma;
1361         if (!dev->irq)
1362                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1363         if (board->DMAbits != 0) {      /* board support DMA */
1364                 dma = it->options[2];
1365                 if (dma < 1)
1366                         goto no_dma;    /* DMA disabled */
1367                 if (((1 << dma) & board->DMAbits) == 0) {
1368                         dev_err(dev->class_dev,
1369                                 "DMA is out of allowed range, FAIL!\n");
1370                         return -EINVAL; /* Bad DMA */
1371                 }
1372                 ret = request_dma(dma, dev->board_name);
1373                 if (ret)
1374                         return -EBUSY;  /* DMA isn't free */
1375                 devpriv->dma = dma;
1376                 pages = 2;      /* we need 16KB */
1377                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1378                 if (!devpriv->dmabuf[0])
1379                         /* maybe experiment with try_to_free_pages() will help .... */
1380                         return -EBUSY;  /* no buffer :-( */
1381                 devpriv->dmapages[0] = pages;
1382                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1383                 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1384                 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1385                 if (!devpriv->dmabuf[1])
1386                         return -EBUSY;
1387                 devpriv->dmapages[1] = pages;
1388                 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1389                 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1390         }
1391
1392 no_dma:
1393
1394         ret = comedi_alloc_subdevices(dev, 4);
1395         if (ret)
1396                 return ret;
1397
1398         s = &dev->subdevices[0];
1399         if (!board->n_aichan_se) {
1400                 s->type = COMEDI_SUBD_UNUSED;
1401         } else {
1402                 s->type = COMEDI_SUBD_AI;
1403                 s->subdev_flags = SDF_READABLE;
1404                 if (check_single_ended(dev->iobase)) {
1405                         s->n_chan = board->n_aichan_se;
1406                         s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1407                 } else {
1408                         s->n_chan = board->n_aichan_diff;
1409                         s->subdev_flags |= SDF_DIFF;
1410                 }
1411                 s->maxdata = board->ai_maxdata;
1412                 s->range_table = board->ai_range_type;
1413                 s->insn_read = pcl818_ai_insn_read;
1414                 if (dev->irq) {
1415                         dev->read_subdev = s;
1416                         s->subdev_flags |= SDF_CMD_READ;
1417                         s->len_chanlist = s->n_chan;
1418                         s->do_cmdtest = ai_cmdtest;
1419                         s->do_cmd = ai_cmd;
1420                         s->cancel = pcl818_ai_cancel;
1421                 }
1422                 if (board->is_818) {
1423                         if ((it->options[4] == 1) || (it->options[4] == 10))
1424                                 s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1425                 } else {
1426                         switch (it->options[4]) {
1427                         case 0:
1428                                 s->range_table = &range_bipolar10;
1429                                 break;
1430                         case 1:
1431                                 s->range_table = &range_bipolar5;
1432                                 break;
1433                         case 2:
1434                                 s->range_table = &range_bipolar2_5;
1435                                 break;
1436                         case 3:
1437                                 s->range_table = &range718_bipolar1;
1438                                 break;
1439                         case 4:
1440                                 s->range_table = &range718_bipolar0_5;
1441                                 break;
1442                         case 6:
1443                                 s->range_table = &range_unipolar10;
1444                                 break;
1445                         case 7:
1446                                 s->range_table = &range_unipolar5;
1447                                 break;
1448                         case 8:
1449                                 s->range_table = &range718_unipolar2;
1450                                 break;
1451                         case 9:
1452                                 s->range_table = &range718_unipolar1;
1453                                 break;
1454                         default:
1455                                 s->range_table = &range_unknown;
1456                                 break;
1457                         }
1458                 }
1459         }
1460
1461         s = &dev->subdevices[1];
1462         if (!board->n_aochan) {
1463                 s->type = COMEDI_SUBD_UNUSED;
1464         } else {
1465                 s->type = COMEDI_SUBD_AO;
1466                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1467                 s->n_chan = board->n_aochan;
1468                 s->maxdata = board->ao_maxdata;
1469                 s->range_table = board->ao_range_type;
1470                 s->insn_read = pcl818_ao_insn_read;
1471                 s->insn_write = pcl818_ao_insn_write;
1472                 if (board->is_818) {
1473                         if ((it->options[4] == 1) || (it->options[4] == 10))
1474                                 s->range_table = &range_unipolar10;
1475                         if (it->options[4] == 2)
1476                                 s->range_table = &range_unknown;
1477                 } else {
1478                         if ((it->options[5] == 1) || (it->options[5] == 10))
1479                                 s->range_table = &range_unipolar10;
1480                         if (it->options[5] == 2)
1481                                 s->range_table = &range_unknown;
1482                 }
1483         }
1484
1485         s = &dev->subdevices[2];
1486         if (!board->n_dichan) {
1487                 s->type = COMEDI_SUBD_UNUSED;
1488         } else {
1489                 s->type = COMEDI_SUBD_DI;
1490                 s->subdev_flags = SDF_READABLE;
1491                 s->n_chan = board->n_dichan;
1492                 s->maxdata = 1;
1493                 s->range_table = &range_digital;
1494                 s->insn_bits = pcl818_di_insn_bits;
1495         }
1496
1497         s = &dev->subdevices[3];
1498         if (!board->n_dochan) {
1499                 s->type = COMEDI_SUBD_UNUSED;
1500         } else {
1501                 s->type = COMEDI_SUBD_DO;
1502                 s->subdev_flags = SDF_WRITABLE;
1503                 s->n_chan = board->n_dochan;
1504                 s->maxdata = 1;
1505                 s->range_table = &range_digital;
1506                 s->insn_bits = pcl818_do_insn_bits;
1507         }
1508
1509         /* select 1/10MHz oscilator */
1510         if ((it->options[3] == 0) || (it->options[3] == 10))
1511                 devpriv->i8253_osc_base = I8254_OSC_BASE_10MHZ;
1512         else
1513                 devpriv->i8253_osc_base = I8254_OSC_BASE_1MHZ;
1514
1515         /* max sampling speed */
1516         devpriv->ns_min = board->ns_min;
1517
1518         if (!board->is_818) {
1519                 if ((it->options[6] == 1) || (it->options[6] == 100))
1520                         devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
1521         }
1522
1523         pcl818_reset(dev);
1524
1525         return 0;
1526 }
1527
1528 static void pcl818_detach(struct comedi_device *dev)
1529 {
1530         struct pcl818_private *devpriv = dev->private;
1531
1532         if (devpriv) {
1533                 pcl818_ai_cancel(dev, dev->read_subdev);
1534                 pcl818_reset(dev);
1535                 if (devpriv->dma)
1536                         free_dma(devpriv->dma);
1537                 if (devpriv->dmabuf[0])
1538                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1539                 if (devpriv->dmabuf[1])
1540                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1541         }
1542         comedi_legacy_detach(dev);
1543 }
1544
1545 static struct comedi_driver pcl818_driver = {
1546         .driver_name    = "pcl818",
1547         .module         = THIS_MODULE,
1548         .attach         = pcl818_attach,
1549         .detach         = pcl818_detach,
1550         .board_name     = &boardtypes[0].name,
1551         .num_names      = ARRAY_SIZE(boardtypes),
1552         .offset         = sizeof(struct pcl818_board),
1553 };
1554 module_comedi_driver(pcl818_driver);
1555
1556 MODULE_AUTHOR("Comedi http://www.comedi.org");
1557 MODULE_DESCRIPTION("Comedi low-level driver");
1558 MODULE_LICENSE("GPL");