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