cd76da66575d2cbfdc551a039ac3749dd03d53e5
[cascardo/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 int irq;
1598         int dma;
1599         unsigned long pages;
1600         struct comedi_subdevice *s;
1601
1602         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1603         if (!devpriv)
1604                 return -ENOMEM;
1605         dev->private = devpriv;
1606
1607         devpriv->io_range = board->io_range;
1608         if ((board->fifo) && (it->options[2] == -1)) {
1609                 /*  we've board with FIFO and we want to use FIFO */
1610                 devpriv->io_range = PCLx1xFIFO_RANGE;
1611                 devpriv->usefifo = 1;
1612         }
1613         ret = comedi_request_region(dev, it->options[0], devpriv->io_range);
1614         if (ret)
1615                 return ret;
1616
1617         if (pcl818_check(dev->iobase)) {
1618                 comedi_error(dev, "I can't detect board. FAIL!\n");
1619                 return -EIO;
1620         }
1621
1622         /* grab our IRQ */
1623         irq = 0;
1624         if (board->IRQbits != 0) {      /* board support IRQ */
1625                 irq = it->options[1];
1626                 if (irq) {      /* we want to use IRQ */
1627                         if (((1 << irq) & board->IRQbits) == 0) {
1628                                 printk
1629                                     (", IRQ %u is out of allowed range, DISABLING IT",
1630                                      irq);
1631                                 irq = 0;        /* Bad IRQ */
1632                         } else {
1633                                 if (request_irq(irq, interrupt_pcl818, 0,
1634                                                 dev->board_name, dev)) {
1635                                         printk
1636                                             (", unable to allocate IRQ %u, DISABLING IT",
1637                                              irq);
1638                                         irq = 0;        /* Can't use IRQ */
1639                                 } else {
1640                                         printk(KERN_DEBUG "irq=%u", irq);
1641                                 }
1642                         }
1643                 }
1644         }
1645
1646         dev->irq = irq;
1647         if (irq)
1648                 devpriv->irq_free = 1;   /* 1=we have allocated irq */
1649         else
1650                 devpriv->irq_free = 0;
1651
1652         devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1653         devpriv->ai_mode = 0;   /* mode of irq */
1654
1655 #ifdef unused
1656         /* grab RTC for DMA operations */
1657         devpriv->dma_rtc = 0;
1658         if (it->options[2] > 0) {       /*  we want to use DMA */
1659                 if (RTC_lock == 0) {
1660                         ret = __comedi_request_resource(dev, RTC_PORT(0),
1661                                                         RTC_IO_EXTENT);
1662                         if (ret)
1663                                 goto no_rtc;
1664                 }
1665                 devpriv->rtc_iobase = RTC_PORT(0);
1666                 devpriv->rtc_iosize = RTC_IO_EXTENT;
1667                 RTC_lock++;
1668                 if (!request_irq(RTC_IRQ, interrupt_pcl818_ai_mode13_dma_rtc, 0,
1669                                  "pcl818 DMA (RTC)", dev)) {
1670                         devpriv->dma_rtc = 1;
1671                         devpriv->rtc_irq = RTC_IRQ;
1672                         printk(KERN_DEBUG "dma_irq=%u", devpriv->rtc_irq);
1673                 } else {
1674                         RTC_lock--;
1675                         if (RTC_lock == 0) {
1676                                 if (devpriv->rtc_iobase)
1677                                         release_region(devpriv->rtc_iobase,
1678                                                        devpriv->rtc_iosize);
1679                         }
1680                         devpriv->rtc_iobase = 0;
1681                         devpriv->rtc_iosize = 0;
1682                 }
1683         }
1684
1685 no_rtc:
1686 #endif
1687         /* grab our DMA */
1688         dma = 0;
1689         devpriv->dma = dma;
1690         if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1691                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1692         if (board->DMAbits != 0) {      /* board support DMA */
1693                 dma = it->options[2];
1694                 if (dma < 1)
1695                         goto no_dma;    /* DMA disabled */
1696                 if (((1 << dma) & board->DMAbits) == 0) {
1697                         printk(KERN_ERR "DMA is out of allowed range, FAIL!\n");
1698                         return -EINVAL; /* Bad DMA */
1699                 }
1700                 ret = request_dma(dma, dev->board_name);
1701                 if (ret)
1702                         return -EBUSY;  /* DMA isn't free */
1703                 devpriv->dma = dma;
1704                 pages = 2;      /* we need 16KB */
1705                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1706                 if (!devpriv->dmabuf[0])
1707                         /* maybe experiment with try_to_free_pages() will help .... */
1708                         return -EBUSY;  /* no buffer :-( */
1709                 devpriv->dmapages[0] = pages;
1710                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1711                 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1712                 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1713                 if (devpriv->dma_rtc == 0) {    /*  we must do duble buff :-( */
1714                         devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1715                         if (!devpriv->dmabuf[1])
1716                                 return -EBUSY;
1717                         devpriv->dmapages[1] = pages;
1718                         devpriv->hwdmaptr[1] =
1719                             virt_to_bus((void *)devpriv->dmabuf[1]);
1720                         devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1721                 }
1722         }
1723
1724 no_dma:
1725
1726         ret = comedi_alloc_subdevices(dev, 4);
1727         if (ret)
1728                 return ret;
1729
1730         s = &dev->subdevices[0];
1731         if (!board->n_aichan_se) {
1732                 s->type = COMEDI_SUBD_UNUSED;
1733         } else {
1734                 s->type = COMEDI_SUBD_AI;
1735                 devpriv->sub_ai = s;
1736                 s->subdev_flags = SDF_READABLE;
1737                 if (check_single_ended(dev->iobase)) {
1738                         s->n_chan = board->n_aichan_se;
1739                         s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1740                         printk(", %dchans S.E. DAC", s->n_chan);
1741                 } else {
1742                         s->n_chan = board->n_aichan_diff;
1743                         s->subdev_flags |= SDF_DIFF;
1744                         printk(", %dchans DIFF DAC", s->n_chan);
1745                 }
1746                 s->maxdata = board->ai_maxdata;
1747                 s->len_chanlist = s->n_chan;
1748                 s->range_table = board->ai_range_type;
1749                 s->cancel = pcl818_ai_cancel;
1750                 s->insn_read = pcl818_ai_insn_read;
1751                 if ((irq) || (devpriv->dma_rtc)) {
1752                         dev->read_subdev = s;
1753                         s->subdev_flags |= SDF_CMD_READ;
1754                         s->do_cmdtest = ai_cmdtest;
1755                         s->do_cmd = ai_cmd;
1756                 }
1757                 if (board->is_818) {
1758                         if ((it->options[4] == 1) || (it->options[4] == 10))
1759                                 s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1760                 } else {
1761                         switch (it->options[4]) {
1762                         case 0:
1763                                 s->range_table = &range_bipolar10;
1764                                 break;
1765                         case 1:
1766                                 s->range_table = &range_bipolar5;
1767                                 break;
1768                         case 2:
1769                                 s->range_table = &range_bipolar2_5;
1770                                 break;
1771                         case 3:
1772                                 s->range_table = &range718_bipolar1;
1773                                 break;
1774                         case 4:
1775                                 s->range_table = &range718_bipolar0_5;
1776                                 break;
1777                         case 6:
1778                                 s->range_table = &range_unipolar10;
1779                                 break;
1780                         case 7:
1781                                 s->range_table = &range_unipolar5;
1782                                 break;
1783                         case 8:
1784                                 s->range_table = &range718_unipolar2;
1785                                 break;
1786                         case 9:
1787                                 s->range_table = &range718_unipolar1;
1788                                 break;
1789                         default:
1790                                 s->range_table = &range_unknown;
1791                                 break;
1792                         }
1793                 }
1794         }
1795
1796         s = &dev->subdevices[1];
1797         if (!board->n_aochan) {
1798                 s->type = COMEDI_SUBD_UNUSED;
1799         } else {
1800                 s->type = COMEDI_SUBD_AO;
1801                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1802                 s->n_chan = board->n_aochan;
1803                 s->maxdata = board->ao_maxdata;
1804                 s->len_chanlist = board->n_aochan;
1805                 s->range_table = board->ao_range_type;
1806                 s->insn_read = pcl818_ao_insn_read;
1807                 s->insn_write = pcl818_ao_insn_write;
1808 #ifdef unused
1809 #ifdef PCL818_MODE13_AO
1810                 if (irq) {
1811                         s->trig[1] = pcl818_ao_mode1;
1812                         s->trig[3] = pcl818_ao_mode3;
1813                 }
1814 #endif
1815 #endif
1816                 if (board->is_818) {
1817                         if ((it->options[4] == 1) || (it->options[4] == 10))
1818                                 s->range_table = &range_unipolar10;
1819                         if (it->options[4] == 2)
1820                                 s->range_table = &range_unknown;
1821                 } else {
1822                         if ((it->options[5] == 1) || (it->options[5] == 10))
1823                                 s->range_table = &range_unipolar10;
1824                         if (it->options[5] == 2)
1825                                 s->range_table = &range_unknown;
1826                 }
1827         }
1828
1829         s = &dev->subdevices[2];
1830         if (!board->n_dichan) {
1831                 s->type = COMEDI_SUBD_UNUSED;
1832         } else {
1833                 s->type = COMEDI_SUBD_DI;
1834                 s->subdev_flags = SDF_READABLE;
1835                 s->n_chan = board->n_dichan;
1836                 s->maxdata = 1;
1837                 s->len_chanlist = board->n_dichan;
1838                 s->range_table = &range_digital;
1839                 s->insn_bits = pcl818_di_insn_bits;
1840         }
1841
1842         s = &dev->subdevices[3];
1843         if (!board->n_dochan) {
1844                 s->type = COMEDI_SUBD_UNUSED;
1845         } else {
1846                 s->type = COMEDI_SUBD_DO;
1847                 s->subdev_flags = SDF_WRITABLE;
1848                 s->n_chan = board->n_dochan;
1849                 s->maxdata = 1;
1850                 s->len_chanlist = board->n_dochan;
1851                 s->range_table = &range_digital;
1852                 s->insn_bits = pcl818_do_insn_bits;
1853         }
1854
1855         /* select 1/10MHz oscilator */
1856         if ((it->options[3] == 0) || (it->options[3] == 10))
1857                 devpriv->i8253_osc_base = 100;
1858         else
1859                 devpriv->i8253_osc_base = 1000;
1860
1861         /* max sampling speed */
1862         devpriv->ns_min = board->ns_min;
1863
1864         if (!board->is_818) {
1865                 if ((it->options[6] == 1) || (it->options[6] == 100))
1866                         devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
1867         }
1868
1869         pcl818_reset(dev);
1870
1871         printk("\n");
1872
1873         return 0;
1874 }
1875
1876 static void pcl818_detach(struct comedi_device *dev)
1877 {
1878         struct pcl818_private *devpriv = dev->private;
1879
1880         if (devpriv) {
1881                 pcl818_ai_cancel(dev, devpriv->sub_ai);
1882                 pcl818_reset(dev);
1883                 if (devpriv->dma)
1884                         free_dma(devpriv->dma);
1885                 if (devpriv->dmabuf[0])
1886                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1887                 if (devpriv->dmabuf[1])
1888                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1889 #ifdef unused
1890                 if (devpriv->rtc_irq)
1891                         free_irq(devpriv->rtc_irq, dev);
1892                 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1893                         if (devpriv->rtc_iobase)
1894                                 release_region(devpriv->rtc_iobase,
1895                                                devpriv->rtc_iosize);
1896                 }
1897                 if (devpriv->dma_rtc)
1898                         RTC_lock--;
1899 #endif
1900         }
1901         if (dev->irq)
1902                 free_irq(dev->irq, dev);
1903         comedi_legacy_detach(dev);
1904 }
1905
1906 static const struct pcl818_board boardtypes[] = {
1907         {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
1908          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1909          0x0a, 0xfff, 0xfff, 0, 1},
1910         {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1911          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1912          0x0a, 0xfff, 0xfff, 0, 1},
1913         {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1914          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1915          0x0a, 0xfff, 0xfff, 1, 1},
1916         {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
1917          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1918          0x0a, 0xfff, 0xfff, 1, 1},
1919         {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
1920          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1921          0x0a, 0xfff, 0xfff, 0, 1},
1922         {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
1923          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1924          0x0a, 0xfff, 0xfff, 0, 0},
1925         /* pcm3718 */
1926         {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
1927          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1928          0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
1929 };
1930
1931 static struct comedi_driver pcl818_driver = {
1932         .driver_name    = "pcl818",
1933         .module         = THIS_MODULE,
1934         .attach         = pcl818_attach,
1935         .detach         = pcl818_detach,
1936         .board_name     = &boardtypes[0].name,
1937         .num_names      = ARRAY_SIZE(boardtypes),
1938         .offset         = sizeof(struct pcl818_board),
1939 };
1940 module_comedi_driver(pcl818_driver);
1941
1942 MODULE_AUTHOR("Comedi http://www.comedi.org");
1943 MODULE_DESCRIPTION("Comedi low-level driver");
1944 MODULE_LICENSE("GPL");