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