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