]> Pileus Git - ~andy/linux/blob - drivers/staging/comedi/drivers/pcl818.c
staging: comedi: remove inline alloc_private()
[~andy/linux] / 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                 }
1011 #ifdef unused
1012                 else {
1013                         pcl818_ai_mode13dma_rtc(mode, dev, s);
1014                 }
1015 #else
1016                 else {
1017                         return -EINVAL;
1018                 }
1019 #endif
1020                 break;
1021         case 0:
1022                 if (!devpriv->usefifo) {
1023                         /* IRQ */
1024                         /* printk("IRQ\n"); */
1025                         if (mode == 1) {
1026                                 devpriv->ai_mode = INT_TYPE_AI1_INT;
1027                                 /* Pacer+IRQ */
1028                                 outb(0x83 | (dev->irq << 4),
1029                                      dev->iobase + PCL818_CONTROL);
1030                         } else {
1031                                 devpriv->ai_mode = INT_TYPE_AI3_INT;
1032                                 /* Ext trig+IRQ */
1033                                 outb(0x82 | (dev->irq << 4),
1034                                      dev->iobase + PCL818_CONTROL);
1035                         }
1036                 } else {
1037                         /* FIFO */
1038                         /* enable FIFO */
1039                         outb(1, dev->iobase + PCL818_FI_ENABLE);
1040                         if (mode == 1) {
1041                                 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1042                                 /* Pacer */
1043                                 outb(0x03, dev->iobase + PCL818_CONTROL);
1044                         } else {
1045                                 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1046                                 outb(0x02, dev->iobase + PCL818_CONTROL);
1047                         }
1048                 }
1049         }
1050
1051         start_pacer(dev, mode, divisor1, divisor2);
1052
1053 #ifdef unused
1054         switch (devpriv->ai_mode) {
1055         case INT_TYPE_AI1_DMA_RTC:
1056         case INT_TYPE_AI3_DMA_RTC:
1057                 set_rtc_irq_bit(1);     /* start RTC */
1058                 break;
1059         }
1060 #endif
1061         dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode() end\n");
1062         return 0;
1063 }
1064
1065 #ifdef unused
1066 /*
1067 ==============================================================================
1068    ANALOG OUTPUT MODE 1 or 3, 818 cards
1069 */
1070 #ifdef PCL818_MODE13_AO
1071 static int pcl818_ao_mode13(int mode, struct comedi_device *dev,
1072                             struct comedi_subdevice *s, comedi_trig * it)
1073 {
1074         struct pcl818_private *devpriv = dev->private;
1075         int divisor1 = 0, divisor2 = 0;
1076
1077         if (!dev->irq) {
1078                 comedi_error(dev, "IRQ not defined!");
1079                 return -EINVAL;
1080         }
1081
1082         if (devpriv->irq_blocked)
1083                 return -EBUSY;
1084
1085         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
1086
1087         devpriv->int13_act_scan = it->n;
1088         devpriv->int13_act_chan = 0;
1089         devpriv->irq_blocked = 1;
1090         devpriv->irq_was_now_closed = 0;
1091         devpriv->neverending_ai = 0;
1092         devpriv->act_chanlist_pos = 0;
1093
1094         if (mode == 1) {
1095                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1096                                           &divisor2, &it->trigvar,
1097                                           TRIG_ROUND_NEAREST);
1098                 if (divisor1 == 1) {    /* PCL818 crash if any divisor is set to 1 */
1099                         divisor1 = 2;
1100                         divisor2 /= 2;
1101                 }
1102                 if (divisor2 == 1) {
1103                         divisor2 = 2;
1104                         divisor1 /= 2;
1105                 }
1106         }
1107
1108         outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
1109         if (mode == 1) {
1110                 devpriv->int818_mode = INT_TYPE_AO1_INT;
1111                 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ */
1112         } else {
1113                 devpriv->int818_mode = INT_TYPE_AO3_INT;
1114                 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ */
1115         };
1116
1117         start_pacer(dev, mode, divisor1, divisor2);
1118
1119         return 0;
1120 }
1121
1122 /*
1123 ==============================================================================
1124    ANALOG OUTPUT MODE 1, 818 cards
1125 */
1126 static int pcl818_ao_mode1(struct comedi_device *dev,
1127                            struct comedi_subdevice *s, comedi_trig * it)
1128 {
1129         return pcl818_ao_mode13(1, dev, s, it);
1130 }
1131
1132 /*
1133 ==============================================================================
1134    ANALOG OUTPUT MODE 3, 818 cards
1135 */
1136 static int pcl818_ao_mode3(struct comedi_device *dev,
1137                            struct comedi_subdevice *s, comedi_trig * it)
1138 {
1139         return pcl818_ao_mode13(3, dev, s, it);
1140 }
1141 #endif
1142 #endif
1143
1144 /*
1145 ==============================================================================
1146  Start/stop pacer onboard pacer
1147 */
1148 static void start_pacer(struct comedi_device *dev, int mode,
1149                         unsigned int divisor1, unsigned int divisor2)
1150 {
1151         outb(0xb4, dev->iobase + PCL818_CTRCTL);
1152         outb(0x74, dev->iobase + PCL818_CTRCTL);
1153         udelay(1);
1154
1155         if (mode == 1) {
1156                 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1157                 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1158                 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1159                 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1160         }
1161 }
1162
1163 /*
1164 ==============================================================================
1165  Check if channel list from user is builded correctly
1166  If it's ok, then program scan/gain logic
1167 */
1168 static int check_channel_list(struct comedi_device *dev,
1169                               struct comedi_subdevice *s,
1170                               unsigned int *chanlist, unsigned int n_chan)
1171 {
1172         unsigned int chansegment[16];
1173         unsigned int i, nowmustbechan, seglen, segpos;
1174
1175         /* correct channel and range number check itself comedi/range.c */
1176         if (n_chan < 1) {
1177                 comedi_error(dev, "range/channel list is empty!");
1178                 return 0;
1179         }
1180
1181         if (n_chan > 1) {
1182                 /*  first channel is every time ok */
1183                 chansegment[0] = chanlist[0];
1184                 /*  build part of chanlist */
1185                 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1186
1187                         /* printk("%d. %d * %d\n",i,
1188                          * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1189
1190                         /* we detect loop, this must by finish */
1191
1192                         if (chanlist[0] == chanlist[i])
1193                                 break;
1194                         nowmustbechan =
1195                             (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1196                         if (nowmustbechan != CR_CHAN(chanlist[i])) {    /*  channel list isn't continuous :-( */
1197                                 printk
1198                                     ("comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
1199                                      dev->minor, i, CR_CHAN(chanlist[i]),
1200                                      nowmustbechan, CR_CHAN(chanlist[0]));
1201                                 return 0;
1202                         }
1203                         /*  well, this is next correct channel in list */
1204                         chansegment[i] = chanlist[i];
1205                 }
1206
1207                 /*  check whole chanlist */
1208                 for (i = 0, segpos = 0; i < n_chan; i++) {
1209                         /* 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])); */
1210                         if (chanlist[i] != chansegment[i % seglen]) {
1211                                 printk
1212                                     ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1213                                      dev->minor, i, CR_CHAN(chansegment[i]),
1214                                      CR_RANGE(chansegment[i]),
1215                                      CR_AREF(chansegment[i]),
1216                                      CR_CHAN(chanlist[i % seglen]),
1217                                      CR_RANGE(chanlist[i % seglen]),
1218                                      CR_AREF(chansegment[i % seglen]));
1219                                 return 0;       /*  chan/gain list is strange */
1220                         }
1221                 }
1222         } else {
1223                 seglen = 1;
1224         }
1225         printk("check_channel_list: seglen %d\n", seglen);
1226         return seglen;
1227 }
1228
1229 static void setup_channel_list(struct comedi_device *dev,
1230                                struct comedi_subdevice *s,
1231                                unsigned int *chanlist, unsigned int n_chan,
1232                                unsigned int seglen)
1233 {
1234         struct pcl818_private *devpriv = dev->private;
1235         int i;
1236
1237         devpriv->act_chanlist_len = seglen;
1238         devpriv->act_chanlist_pos = 0;
1239
1240         for (i = 0; i < seglen; i++) {  /*  store range list to card */
1241                 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1242                 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);       /* select channel */
1243                 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);        /* select gain */
1244         }
1245
1246         udelay(1);
1247
1248         /* select channel interval to scan */
1249         outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1250                                                                1] << 4),
1251              dev->iobase + PCL818_MUX);
1252 }
1253
1254 /*
1255 ==============================================================================
1256  Check if board is switched to SE (1) or DIFF(0) mode
1257 */
1258 static int check_single_ended(unsigned int port)
1259 {
1260         if (inb(port + PCL818_STATUS) & 0x20)
1261                 return 1;
1262         return 0;
1263 }
1264
1265 /*
1266 ==============================================================================
1267 */
1268 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1269                       struct comedi_cmd *cmd)
1270 {
1271         const struct pcl818_board *board = comedi_board(dev);
1272         struct pcl818_private *devpriv = dev->private;
1273         int err = 0;
1274         int tmp, divisor1 = 0, divisor2 = 0;
1275
1276         /* Step 1 : check if triggers are trivially valid */
1277
1278         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
1279         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
1280         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
1281         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1282         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1283
1284         if (err)
1285                 return 1;
1286
1287         /* Step 2a : make sure trigger sources are unique */
1288
1289         err |= cfc_check_trigger_is_unique(cmd->convert_src);
1290         err |= cfc_check_trigger_is_unique(cmd->stop_src);
1291
1292         /* Step 2b : and mutually compatible */
1293
1294         if (err)
1295                 return 2;
1296
1297         /* step 3: make sure arguments are trivially compatible */
1298
1299         if (cmd->start_arg != 0) {
1300                 cmd->start_arg = 0;
1301                 err++;
1302         }
1303
1304         if (cmd->scan_begin_arg != 0) {
1305                 cmd->scan_begin_arg = 0;
1306                 err++;
1307         }
1308
1309         if (cmd->convert_src == TRIG_TIMER) {
1310                 if (cmd->convert_arg < board->ns_min) {
1311                         cmd->convert_arg = board->ns_min;
1312                         err++;
1313                 }
1314         } else {                /* TRIG_EXT */
1315                 if (cmd->convert_arg != 0) {
1316                         cmd->convert_arg = 0;
1317                         err++;
1318                 }
1319         }
1320
1321         if (cmd->scan_end_arg != cmd->chanlist_len) {
1322                 cmd->scan_end_arg = cmd->chanlist_len;
1323                 err++;
1324         }
1325         if (cmd->stop_src == TRIG_COUNT) {
1326                 if (!cmd->stop_arg) {
1327                         cmd->stop_arg = 1;
1328                         err++;
1329                 }
1330         } else {                /* TRIG_NONE */
1331                 if (cmd->stop_arg != 0) {
1332                         cmd->stop_arg = 0;
1333                         err++;
1334                 }
1335         }
1336
1337         if (err)
1338                 return 3;
1339
1340         /* step 4: fix up any arguments */
1341
1342         if (cmd->convert_src == TRIG_TIMER) {
1343                 tmp = cmd->convert_arg;
1344                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1345                                           &divisor2, &cmd->convert_arg,
1346                                           cmd->flags & TRIG_ROUND_MASK);
1347                 if (cmd->convert_arg < board->ns_min)
1348                         cmd->convert_arg = board->ns_min;
1349                 if (tmp != cmd->convert_arg)
1350                         err++;
1351         }
1352
1353         if (err)
1354                 return 4;
1355
1356         /* step 5: complain about special chanlist considerations */
1357
1358         if (cmd->chanlist) {
1359                 if (!check_channel_list(dev, s, cmd->chanlist,
1360                                         cmd->chanlist_len))
1361                         return 5;       /*  incorrect channels list */
1362         }
1363
1364         return 0;
1365 }
1366
1367 /*
1368 ==============================================================================
1369 */
1370 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1371 {
1372         struct pcl818_private *devpriv = dev->private;
1373         struct comedi_cmd *cmd = &s->async->cmd;
1374         int retval;
1375
1376         dev_dbg(dev->class_dev, "pcl818_ai_cmd()\n");
1377         devpriv->ai_n_chan = cmd->chanlist_len;
1378         devpriv->ai_chanlist = cmd->chanlist;
1379         devpriv->ai_flags = cmd->flags;
1380         devpriv->ai_data_len = s->async->prealloc_bufsz;
1381         devpriv->ai_data = s->async->prealloc_buf;
1382         devpriv->ai_timer1 = 0;
1383         devpriv->ai_timer2 = 0;
1384
1385         if (cmd->stop_src == TRIG_COUNT)
1386                 devpriv->ai_scans = cmd->stop_arg;
1387         else
1388                 devpriv->ai_scans = 0;
1389
1390         if (cmd->scan_begin_src == TRIG_FOLLOW) {       /*  mode 1, 3 */
1391                 if (cmd->convert_src == TRIG_TIMER) {   /*  mode 1 */
1392                         devpriv->ai_timer1 = cmd->convert_arg;
1393                         retval = pcl818_ai_cmd_mode(1, dev, s);
1394                         dev_dbg(dev->class_dev, "pcl818_ai_cmd() end\n");
1395                         return retval;
1396                 }
1397                 if (cmd->convert_src == TRIG_EXT) {     /*  mode 3 */
1398                         return pcl818_ai_cmd_mode(3, dev, s);
1399                 }
1400         }
1401
1402         return -1;
1403 }
1404
1405 /*
1406 ==============================================================================
1407  cancel any mode 1-4 AI
1408 */
1409 static int pcl818_ai_cancel(struct comedi_device *dev,
1410                             struct comedi_subdevice *s)
1411 {
1412         struct pcl818_private *devpriv = dev->private;
1413
1414         if (devpriv->irq_blocked > 0) {
1415                 dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n");
1416                 devpriv->irq_was_now_closed = 1;
1417
1418                 switch (devpriv->ai_mode) {
1419 #ifdef unused
1420                 case INT_TYPE_AI1_DMA_RTC:
1421                 case INT_TYPE_AI3_DMA_RTC:
1422                         set_rtc_irq_bit(0);     /*  stop RTC */
1423                         del_timer(&devpriv->rtc_irq_timer);
1424 #endif
1425                 case INT_TYPE_AI1_DMA:
1426                 case INT_TYPE_AI3_DMA:
1427                         if (devpriv->neverending_ai ||
1428                             (!devpriv->neverending_ai &&
1429                              devpriv->ai_act_scan > 0)) {
1430                                 /* wait for running dma transfer to end, do cleanup in interrupt */
1431                                 goto end;
1432                         }
1433                         disable_dma(devpriv->dma);
1434                 case INT_TYPE_AI1_INT:
1435                 case INT_TYPE_AI3_INT:
1436                 case INT_TYPE_AI1_FIFO:
1437                 case INT_TYPE_AI3_FIFO:
1438 #ifdef PCL818_MODE13_AO
1439                 case INT_TYPE_AO1_INT:
1440                 case INT_TYPE_AO3_INT:
1441 #endif
1442                         outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);   /* Stop A/D */
1443                         udelay(1);
1444                         start_pacer(dev, -1, 0, 0);
1445                         outb(0, dev->iobase + PCL818_AD_LO);
1446                         inb(dev->iobase + PCL818_AD_LO);
1447                         inb(dev->iobase + PCL818_AD_HI);
1448                         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
1449                         outb(0, dev->iobase + PCL818_CONTROL);  /* Stop A/D */
1450                         if (devpriv->usefifo) { /*  FIFO shutdown */
1451                                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1452                                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1453                                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1454                         }
1455                         devpriv->irq_blocked = 0;
1456                         devpriv->last_int_sub = s;
1457                         devpriv->neverending_ai = 0;
1458                         devpriv->ai_mode = 0;
1459                         devpriv->irq_was_now_closed = 0;
1460                         break;
1461                 }
1462         }
1463
1464 end:
1465         dev_dbg(dev->class_dev, "pcl818_ai_cancel() end\n");
1466         return 0;
1467 }
1468
1469 /*
1470 ==============================================================================
1471  chech for PCL818
1472 */
1473 static int pcl818_check(unsigned long iobase)
1474 {
1475         outb(0x00, iobase + PCL818_MUX);
1476         udelay(1);
1477         if (inb(iobase + PCL818_MUX) != 0x00)
1478                 return 1;       /* there isn't card */
1479         outb(0x55, iobase + PCL818_MUX);
1480         udelay(1);
1481         if (inb(iobase + PCL818_MUX) != 0x55)
1482                 return 1;       /* there isn't card */
1483         outb(0x00, iobase + PCL818_MUX);
1484         udelay(1);
1485         outb(0x18, iobase + PCL818_CONTROL);
1486         udelay(1);
1487         if (inb(iobase + PCL818_CONTROL) != 0x18)
1488                 return 1;       /* there isn't card */
1489         return 0;               /*  ok, card exist */
1490 }
1491
1492 /*
1493 ==============================================================================
1494  reset whole PCL-818 cards
1495 */
1496 static void pcl818_reset(struct comedi_device *dev)
1497 {
1498         const struct pcl818_board *board = comedi_board(dev);
1499         struct pcl818_private *devpriv = dev->private;
1500
1501         if (devpriv->usefifo) { /*  FIFO shutdown */
1502                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1503                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1504                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1505         }
1506         outb(0, dev->iobase + PCL818_DA_LO);    /*  DAC=0V */
1507         outb(0, dev->iobase + PCL818_DA_HI);
1508         udelay(1);
1509         outb(0, dev->iobase + PCL818_DO_HI);    /*  DO=$0000 */
1510         outb(0, dev->iobase + PCL818_DO_LO);
1511         udelay(1);
1512         outb(0, dev->iobase + PCL818_CONTROL);
1513         outb(0, dev->iobase + PCL818_CNTENABLE);
1514         outb(0, dev->iobase + PCL818_MUX);
1515         outb(0, dev->iobase + PCL818_CLRINT);
1516         outb(0xb0, dev->iobase + PCL818_CTRCTL);        /* Stop pacer */
1517         outb(0x70, dev->iobase + PCL818_CTRCTL);
1518         outb(0x30, dev->iobase + PCL818_CTRCTL);
1519         if (board->is_818) {
1520                 outb(0, dev->iobase + PCL818_RANGE);
1521         } else {
1522                 outb(0, dev->iobase + PCL718_DA2_LO);
1523                 outb(0, dev->iobase + PCL718_DA2_HI);
1524         }
1525 }
1526
1527 #ifdef unused
1528 /*
1529 ==============================================================================
1530   Enable(1)/disable(0) periodic interrupts from RTC
1531 */
1532 static int set_rtc_irq_bit(unsigned char bit)
1533 {
1534         unsigned char val;
1535         unsigned long flags;
1536
1537         if (bit == 1) {
1538                 RTC_timer_lock++;
1539                 if (RTC_timer_lock > 1)
1540                         return 0;
1541         } else {
1542                 RTC_timer_lock--;
1543                 if (RTC_timer_lock < 0)
1544                         RTC_timer_lock = 0;
1545                 if (RTC_timer_lock > 0)
1546                         return 0;
1547         }
1548
1549         save_flags(flags);
1550         cli();
1551         val = CMOS_READ(RTC_CONTROL);
1552         if (bit)
1553                 val |= RTC_PIE;
1554         else
1555                 val &= ~RTC_PIE;
1556
1557         CMOS_WRITE(val, RTC_CONTROL);
1558         CMOS_READ(RTC_INTR_FLAGS);
1559         restore_flags(flags);
1560         return 0;
1561 }
1562
1563 /*
1564 ==============================================================================
1565   Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1566 */
1567 static void rtc_dropped_irq(unsigned long data)
1568 {
1569         struct comedi_device *dev = (void *)data;
1570         struct pcl818_private *devpriv = dev->private;
1571         unsigned long flags, tmp;
1572
1573         switch (devpriv->int818_mode) {
1574         case INT_TYPE_AI1_DMA_RTC:
1575         case INT_TYPE_AI3_DMA_RTC:
1576                 mod_timer(&devpriv->rtc_irq_timer,
1577                           jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1578                 save_flags(flags);
1579                 cli();
1580                 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);       /* restart */
1581                 restore_flags(flags);
1582                 break;
1583         }
1584 }
1585
1586 /*
1587 ==============================================================================
1588   Set frequency of interrupts from RTC
1589 */
1590 static int rtc_setfreq_irq(int freq)
1591 {
1592         int tmp = 0;
1593         int rtc_freq;
1594         unsigned char val;
1595         unsigned long flags;
1596
1597         if (freq < 2)
1598                 freq = 2;
1599         if (freq > 8192)
1600                 freq = 8192;
1601
1602         while (freq > (1 << tmp))
1603                 tmp++;
1604
1605         rtc_freq = 1 << tmp;
1606
1607         save_flags(flags);
1608         cli();
1609         val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1610         val |= (16 - tmp);
1611         CMOS_WRITE(val, RTC_FREQ_SELECT);
1612         restore_flags(flags);
1613         return rtc_freq;
1614 }
1615 #endif
1616
1617 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1618 {
1619         const struct pcl818_board *board = comedi_board(dev);
1620         struct pcl818_private *devpriv;
1621         int ret;
1622         unsigned long iobase;
1623         unsigned int irq;
1624         int dma;
1625         unsigned long pages;
1626         struct comedi_subdevice *s;
1627
1628         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1629         if (!devpriv)
1630                 return -ENOMEM;
1631         dev->private = devpriv;
1632
1633         /* claim our I/O space */
1634         iobase = it->options[0];
1635         printk
1636             ("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1637              dev->minor, board->name, iobase);
1638         devpriv->io_range = board->io_range;
1639         if ((board->fifo) && (it->options[2] == -1)) {
1640                 /*  we've board with FIFO and we want to use FIFO */
1641                 devpriv->io_range = PCLx1xFIFO_RANGE;
1642                 devpriv->usefifo = 1;
1643         }
1644         if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1645                 comedi_error(dev, "I/O port conflict\n");
1646                 return -EIO;
1647         }
1648
1649         dev->iobase = iobase;
1650
1651         if (pcl818_check(iobase)) {
1652                 comedi_error(dev, "I can't detect board. FAIL!\n");
1653                 return -EIO;
1654         }
1655
1656         dev->board_name = board->name;
1657
1658         /* grab our IRQ */
1659         irq = 0;
1660         if (board->IRQbits != 0) {      /* board support IRQ */
1661                 irq = it->options[1];
1662                 if (irq) {      /* we want to use IRQ */
1663                         if (((1 << irq) & board->IRQbits) == 0) {
1664                                 printk
1665                                     (", IRQ %u is out of allowed range, DISABLING IT",
1666                                      irq);
1667                                 irq = 0;        /* Bad IRQ */
1668                         } else {
1669                                 if (request_irq
1670                                     (irq, interrupt_pcl818, 0, "pcl818", dev)) {
1671                                         printk
1672                                             (", unable to allocate IRQ %u, DISABLING IT",
1673                                              irq);
1674                                         irq = 0;        /* Can't use IRQ */
1675                                 } else {
1676                                         printk(KERN_DEBUG "irq=%u", irq);
1677                                 }
1678                         }
1679                 }
1680         }
1681
1682         dev->irq = irq;
1683         if (irq)
1684                 devpriv->irq_free = 1;   /* 1=we have allocated irq */
1685         else
1686                 devpriv->irq_free = 0;
1687
1688         devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1689         devpriv->ai_mode = 0;   /* mode of irq */
1690
1691 #ifdef unused
1692         /* grab RTC for DMA operations */
1693         devpriv->dma_rtc = 0;
1694         if (it->options[2] > 0) {       /*  we want to use DMA */
1695                 if (RTC_lock == 0) {
1696                         if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1697                                             "pcl818 (RTC)"))
1698                                 goto no_rtc;
1699                 }
1700                 devpriv->rtc_iobase = RTC_PORT(0);
1701                 devpriv->rtc_iosize = RTC_IO_EXTENT;
1702                 RTC_lock++;
1703                 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1704                                  "pcl818 DMA (RTC)", dev)) {
1705                         devpriv->dma_rtc = 1;
1706                         devpriv->rtc_irq = RTC_IRQ;
1707                         printk(KERN_DEBUG "dma_irq=%u", devpriv->rtc_irq);
1708                 } else {
1709                         RTC_lock--;
1710                         if (RTC_lock == 0) {
1711                                 if (devpriv->rtc_iobase)
1712                                         release_region(devpriv->rtc_iobase,
1713                                                        devpriv->rtc_iosize);
1714                         }
1715                         devpriv->rtc_iobase = 0;
1716                         devpriv->rtc_iosize = 0;
1717                 }
1718         }
1719
1720 no_rtc:
1721 #endif
1722         /* grab our DMA */
1723         dma = 0;
1724         devpriv->dma = dma;
1725         if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1726                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1727         if (board->DMAbits != 0) {      /* board support DMA */
1728                 dma = it->options[2];
1729                 if (dma < 1)
1730                         goto no_dma;    /* DMA disabled */
1731                 if (((1 << dma) & board->DMAbits) == 0) {
1732                         printk(KERN_ERR "DMA is out of allowed range, FAIL!\n");
1733                         return -EINVAL; /* Bad DMA */
1734                 }
1735                 ret = request_dma(dma, "pcl818");
1736                 if (ret)
1737                         return -EBUSY;  /* DMA isn't free */
1738                 devpriv->dma = dma;
1739                 pages = 2;      /* we need 16KB */
1740                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1741                 if (!devpriv->dmabuf[0])
1742                         /* maybe experiment with try_to_free_pages() will help .... */
1743                         return -EBUSY;  /* no buffer :-( */
1744                 devpriv->dmapages[0] = pages;
1745                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1746                 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1747                 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1748                 if (devpriv->dma_rtc == 0) {    /*  we must do duble buff :-( */
1749                         devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1750                         if (!devpriv->dmabuf[1])
1751                                 return -EBUSY;
1752                         devpriv->dmapages[1] = pages;
1753                         devpriv->hwdmaptr[1] =
1754                             virt_to_bus((void *)devpriv->dmabuf[1]);
1755                         devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1756                 }
1757         }
1758
1759 no_dma:
1760
1761         ret = comedi_alloc_subdevices(dev, 4);
1762         if (ret)
1763                 return ret;
1764
1765         s = &dev->subdevices[0];
1766         if (!board->n_aichan_se) {
1767                 s->type = COMEDI_SUBD_UNUSED;
1768         } else {
1769                 s->type = COMEDI_SUBD_AI;
1770                 devpriv->sub_ai = s;
1771                 s->subdev_flags = SDF_READABLE;
1772                 if (check_single_ended(dev->iobase)) {
1773                         s->n_chan = board->n_aichan_se;
1774                         s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1775                         printk(", %dchans S.E. DAC", s->n_chan);
1776                 } else {
1777                         s->n_chan = board->n_aichan_diff;
1778                         s->subdev_flags |= SDF_DIFF;
1779                         printk(", %dchans DIFF DAC", s->n_chan);
1780                 }
1781                 s->maxdata = board->ai_maxdata;
1782                 s->len_chanlist = s->n_chan;
1783                 s->range_table = board->ai_range_type;
1784                 s->cancel = pcl818_ai_cancel;
1785                 s->insn_read = pcl818_ai_insn_read;
1786                 if ((irq) || (devpriv->dma_rtc)) {
1787                         dev->read_subdev = s;
1788                         s->subdev_flags |= SDF_CMD_READ;
1789                         s->do_cmdtest = ai_cmdtest;
1790                         s->do_cmd = ai_cmd;
1791                 }
1792                 if (board->is_818) {
1793                         if ((it->options[4] == 1) || (it->options[4] == 10))
1794                                 s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1795                 } else {
1796                         switch (it->options[4]) {
1797                         case 0:
1798                                 s->range_table = &range_bipolar10;
1799                                 break;
1800                         case 1:
1801                                 s->range_table = &range_bipolar5;
1802                                 break;
1803                         case 2:
1804                                 s->range_table = &range_bipolar2_5;
1805                                 break;
1806                         case 3:
1807                                 s->range_table = &range718_bipolar1;
1808                                 break;
1809                         case 4:
1810                                 s->range_table = &range718_bipolar0_5;
1811                                 break;
1812                         case 6:
1813                                 s->range_table = &range_unipolar10;
1814                                 break;
1815                         case 7:
1816                                 s->range_table = &range_unipolar5;
1817                                 break;
1818                         case 8:
1819                                 s->range_table = &range718_unipolar2;
1820                                 break;
1821                         case 9:
1822                                 s->range_table = &range718_unipolar1;
1823                                 break;
1824                         default:
1825                                 s->range_table = &range_unknown;
1826                                 break;
1827                         }
1828                 }
1829         }
1830
1831         s = &dev->subdevices[1];
1832         if (!board->n_aochan) {
1833                 s->type = COMEDI_SUBD_UNUSED;
1834         } else {
1835                 s->type = COMEDI_SUBD_AO;
1836                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1837                 s->n_chan = board->n_aochan;
1838                 s->maxdata = board->ao_maxdata;
1839                 s->len_chanlist = board->n_aochan;
1840                 s->range_table = board->ao_range_type;
1841                 s->insn_read = pcl818_ao_insn_read;
1842                 s->insn_write = pcl818_ao_insn_write;
1843 #ifdef unused
1844 #ifdef PCL818_MODE13_AO
1845                 if (irq) {
1846                         s->trig[1] = pcl818_ao_mode1;
1847                         s->trig[3] = pcl818_ao_mode3;
1848                 }
1849 #endif
1850 #endif
1851                 if (board->is_818) {
1852                         if ((it->options[4] == 1) || (it->options[4] == 10))
1853                                 s->range_table = &range_unipolar10;
1854                         if (it->options[4] == 2)
1855                                 s->range_table = &range_unknown;
1856                 } else {
1857                         if ((it->options[5] == 1) || (it->options[5] == 10))
1858                                 s->range_table = &range_unipolar10;
1859                         if (it->options[5] == 2)
1860                                 s->range_table = &range_unknown;
1861                 }
1862         }
1863
1864         s = &dev->subdevices[2];
1865         if (!board->n_dichan) {
1866                 s->type = COMEDI_SUBD_UNUSED;
1867         } else {
1868                 s->type = COMEDI_SUBD_DI;
1869                 s->subdev_flags = SDF_READABLE;
1870                 s->n_chan = board->n_dichan;
1871                 s->maxdata = 1;
1872                 s->len_chanlist = board->n_dichan;
1873                 s->range_table = &range_digital;
1874                 s->insn_bits = pcl818_di_insn_bits;
1875         }
1876
1877         s = &dev->subdevices[3];
1878         if (!board->n_dochan) {
1879                 s->type = COMEDI_SUBD_UNUSED;
1880         } else {
1881                 s->type = COMEDI_SUBD_DO;
1882                 s->subdev_flags = SDF_WRITABLE;
1883                 s->n_chan = board->n_dochan;
1884                 s->maxdata = 1;
1885                 s->len_chanlist = board->n_dochan;
1886                 s->range_table = &range_digital;
1887                 s->insn_bits = pcl818_do_insn_bits;
1888         }
1889
1890         /* select 1/10MHz oscilator */
1891         if ((it->options[3] == 0) || (it->options[3] == 10))
1892                 devpriv->i8253_osc_base = 100;
1893         else
1894                 devpriv->i8253_osc_base = 1000;
1895
1896         /* max sampling speed */
1897         devpriv->ns_min = board->ns_min;
1898
1899         if (!board->is_818) {
1900                 if ((it->options[6] == 1) || (it->options[6] == 100))
1901                         devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
1902         }
1903
1904         pcl818_reset(dev);
1905
1906         printk("\n");
1907
1908         return 0;
1909 }
1910
1911 static void pcl818_detach(struct comedi_device *dev)
1912 {
1913         struct pcl818_private *devpriv = dev->private;
1914
1915         if (devpriv) {
1916                 pcl818_ai_cancel(dev, devpriv->sub_ai);
1917                 pcl818_reset(dev);
1918                 if (devpriv->dma)
1919                         free_dma(devpriv->dma);
1920                 if (devpriv->dmabuf[0])
1921                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1922                 if (devpriv->dmabuf[1])
1923                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1924 #ifdef unused
1925                 if (devpriv->rtc_irq)
1926                         free_irq(devpriv->rtc_irq, dev);
1927                 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1928                         if (devpriv->rtc_iobase)
1929                                 release_region(devpriv->rtc_iobase,
1930                                                devpriv->rtc_iosize);
1931                 }
1932                 if (devpriv->dma_rtc)
1933                         RTC_lock--;
1934 #endif
1935         }
1936         if (dev->irq)
1937                 free_irq(dev->irq, dev);
1938         if (dev->iobase)
1939                 release_region(dev->iobase, devpriv->io_range);
1940 }
1941
1942 static const struct pcl818_board boardtypes[] = {
1943         {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
1944          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1945          0x0a, 0xfff, 0xfff, 0, 1},
1946         {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1947          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1948          0x0a, 0xfff, 0xfff, 0, 1},
1949         {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1950          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1951          0x0a, 0xfff, 0xfff, 1, 1},
1952         {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
1953          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1954          0x0a, 0xfff, 0xfff, 1, 1},
1955         {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
1956          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1957          0x0a, 0xfff, 0xfff, 0, 1},
1958         {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
1959          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1960          0x0a, 0xfff, 0xfff, 0, 0},
1961         /* pcm3718 */
1962         {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
1963          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1964          0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
1965 };
1966
1967 static struct comedi_driver pcl818_driver = {
1968         .driver_name    = "pcl818",
1969         .module         = THIS_MODULE,
1970         .attach         = pcl818_attach,
1971         .detach         = pcl818_detach,
1972         .board_name     = &boardtypes[0].name,
1973         .num_names      = ARRAY_SIZE(boardtypes),
1974         .offset         = sizeof(struct pcl818_board),
1975 };
1976 module_comedi_driver(pcl818_driver);
1977
1978 MODULE_AUTHOR("Comedi http://www.comedi.org");
1979 MODULE_DESCRIPTION("Comedi low-level driver");
1980 MODULE_LICENSE("GPL");