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