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