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