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