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