Staging: comedi: jr3_pci: Use struct device from pci_dev for firmware loading.
[linux-2.6] / drivers / staging / comedi / drivers / pcl818.c
1 /*
2    comedi/drivers/pcl818.c
3
4    Author:  Michal Dobes <dobes@tesnet.cz>
5
6    hardware driver for Advantech cards:
7     card:   PCL-818L, PCL-818H, PCL-818HD, PCL-818HG, PCL-818, PCL-718
8     driver: pcl818l,  pcl818h,  pcl818hd,  pcl818hg,  pcl818,  pcl718
9 */
10 /*
11 Driver: pcl818
12 Description: Advantech PCL-818 cards, PCL-718
13 Author: Michal Dobes <dobes@tesnet.cz>
14 Devices: [Advantech] PCL-818L (pcl818l), PCL-818H (pcl818h),
15   PCL-818HD (pcl818hd), PCL-818HG (pcl818hg), PCL-818 (pcl818),
16   PCL-718 (pcl718)
17 Status: works
18
19 All cards have 16 SE/8 DIFF ADCs, one or two DACs, 16 DI and 16 DO.
20 Differences are only at maximal sample speed, range list and FIFO
21 support.
22 The driver support AI mode 0, 1, 3 other subdevices (AO, DI, DO) support
23 only mode 0. If DMA/FIFO/INT are disabled then AI support only mode 0.
24 PCL-818HD and PCL-818HG support 1kword FIFO. Driver support this FIFO
25 but this code is untested.
26 A word or two about DMA. Driver support DMA operations at two ways:
27 1) DMA uses two buffers and after one is filled then is generated
28    INT and DMA restart with second buffer. With this mode I'm unable run
29    more that 80Ksamples/secs without data dropouts on K6/233.
30 2) DMA uses one buffer and run in autoinit mode and the data are
31    from DMA buffer moved on the fly with 2kHz interrupts from RTC.
32    This mode is used if the interrupt 8 is available for allocation.
33    If not, then first DMA mode is used. With this I can run at
34    full speed one card (100ksamples/secs) or two cards with
35    60ksamples/secs each (more is problem on account of ISA limitations).
36    To use this mode you must have compiled  kernel with disabled
37    "Enhanced Real Time Clock Support".
38    Maybe you can have problems if you use xntpd or similar.
39    If you've data dropouts with DMA mode 2 then:
40     a) disable IDE DMA
41     b) switch text mode console to fb.
42
43    Options for PCL-818L:
44     [0] - IO Base
45     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
46     [2] - DMA   (0=disable, 1, 3)
47     [3] - 0, 10=10MHz clock for 8254
48               1= 1MHz clock for 8254
49     [4] - 0,  5=A/D input  -5V.. +5V
50           1, 10=A/D input -10V..+10V
51     [5] - 0,  5=D/A output 0-5V  (internal reference -5V)
52           1, 10=D/A output 0-10V (internal reference -10V)
53           2    =D/A output unknow (external reference)
54
55    Options for PCL-818, PCL-818H:
56     [0] - IO Base
57     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
58     [2] - DMA   (0=disable, 1, 3)
59     [3] - 0, 10=10MHz clock for 8254
60               1= 1MHz clock for 8254
61     [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
62           1, 10=D/A output 0-10V (internal reference -10V)
63           2    =D/A output unknow (external reference)
64
65    Options for PCL-818HD, PCL-818HG:
66     [0] - IO Base
67     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
68     [2] - DMA/FIFO  (-1=use FIFO, 0=disable both FIFO and DMA,
69                       1=use DMA ch 1, 3=use DMA ch 3)
70     [3] - 0, 10=10MHz clock for 8254
71               1= 1MHz clock for 8254
72     [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
73           1, 10=D/A output 0-10V (internal reference -10V)
74           2    =D/A output unknow (external reference)
75
76    Options for PCL-718:
77     [0] - IO Base
78     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
79     [2] - DMA   (0=disable, 1, 3)
80     [3] - 0, 10=10MHz clock for 8254
81               1= 1MHz clock for 8254
82     [4] -     0=A/D Range is +/-10V
83               1=             +/-5V
84               2=             +/-2.5V
85               3=             +/-1V
86               4=             +/-0.5V
87               5=             user defined bipolar
88               6=             0-10V
89               7=             0-5V
90               8=             0-2V
91               9=             0-1V
92              10=             user defined unipolar
93     [5] - 0,  5=D/A outputs 0-5V  (internal reference -5V)
94           1, 10=D/A outputs 0-10V (internal reference -10V)
95               2=D/A outputs unknow (external reference)
96     [6] - 0, 60=max  60kHz A/D sampling
97           1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
98
99 */
100
101 #include "../comedidev.h"
102
103 #include <linux/ioport.h>
104 #include <linux/mc146818rtc.h>
105 #include <linux/delay.h>
106 #include <asm/dma.h>
107
108 #include "8253.h"
109
110 /* #define PCL818_MODE13_AO 1 */
111
112 /* boards constants */
113
114 #define boardPCL818L 0
115 #define boardPCL818H 1
116 #define boardPCL818HD 2
117 #define boardPCL818HG 3
118 #define boardPCL818 4
119 #define boardPCL718 5
120
121 /* IO space len */
122 #define PCLx1x_RANGE 16
123 /* IO space len if we use FIFO */
124 #define PCLx1xFIFO_RANGE 32
125
126 /* W: clear INT request */
127 #define PCL818_CLRINT 8
128 /* R: return status byte */
129 #define PCL818_STATUS 8
130 /* R: A/D high byte W: A/D range control */
131 #define PCL818_RANGE 1
132 /* R: next mux scan channel W: mux scan channel & range control pointer */
133 #define PCL818_MUX 2
134 /* R/W: operation control register */
135 #define PCL818_CONTROL 9
136 /* W: counter enable */
137 #define PCL818_CNTENABLE 10
138
139 /* R: low byte of A/D W: soft A/D trigger */
140 #define PCL818_AD_LO 0
141 /* R: high byte of A/D W: A/D range control */
142 #define PCL818_AD_HI 1
143 /* W: D/A low&high byte */
144 #define PCL818_DA_LO 4
145 #define PCL818_DA_HI 5
146 /* R: low&high byte of DI */
147 #define PCL818_DI_LO 3
148 #define PCL818_DI_HI 11
149 /* W: low&high byte of DO */
150 #define PCL818_DO_LO 3
151 #define PCL818_DO_HI 11
152 /* W: PCL718 second D/A */
153 #define PCL718_DA2_LO 6
154 #define PCL718_DA2_HI 7
155 /* counters */
156 #define PCL818_CTR0 12
157 #define PCL818_CTR1 13
158 #define PCL818_CTR2 14
159 /* W: counter control */
160 #define PCL818_CTRCTL 15
161
162 /* W: fifo enable/disable */
163 #define PCL818_FI_ENABLE 6
164 /* W: fifo interrupt clear */
165 #define PCL818_FI_INTCLR 20
166 /* W: fifo interrupt clear */
167 #define PCL818_FI_FLUSH 25
168 /* R: fifo status */
169 #define PCL818_FI_STATUS 25
170 /* R: one record from FIFO */
171 #define PCL818_FI_DATALO 23
172 #define PCL818_FI_DATAHI 23
173
174 /* type of interrupt handler */
175 #define INT_TYPE_AI1_INT 1
176 #define INT_TYPE_AI1_DMA 2
177 #define INT_TYPE_AI1_FIFO 3
178 #define INT_TYPE_AI3_INT 4
179 #define INT_TYPE_AI3_DMA 5
180 #define INT_TYPE_AI3_FIFO 6
181 #ifdef PCL818_MODE13_AO
182 #define INT_TYPE_AO1_INT 7
183 #define INT_TYPE_AO3_INT 8
184 #endif
185
186 #ifdef unused
187 /* RTC stuff... */
188 #define INT_TYPE_AI1_DMA_RTC 9
189 #define INT_TYPE_AI3_DMA_RTC 10
190
191 #define RTC_IRQ         8
192 #define RTC_IO_EXTENT   0x10
193 #endif
194
195 #define MAGIC_DMA_WORD 0x5a5a
196
197 static const 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)
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         if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
824                 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
825                                                 devpriv->ai_act_scan > 0)) &&
826                                 (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
827                                  devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
828                         /* The cleanup from ai_cancel() has been delayed
829                            until now because the card doesn't seem to like
830                            being reprogrammed while a DMA transfer is in
831                            progress.
832                          */
833                         struct comedi_subdevice *s = dev->subdevices + 0;
834                         devpriv->ai_act_scan = 0;
835                         devpriv->neverending_ai = 0;
836                         pcl818_ai_cancel(dev, s);
837                 }
838
839                 outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
840
841                 return IRQ_HANDLED;
842         }
843
844         switch (devpriv->ai_mode) {
845         case INT_TYPE_AI1_DMA:
846         case INT_TYPE_AI3_DMA:
847                 return interrupt_pcl818_ai_mode13_dma(irq, d);
848         case INT_TYPE_AI1_INT:
849         case INT_TYPE_AI3_INT:
850                 return interrupt_pcl818_ai_mode13_int(irq, d);
851         case INT_TYPE_AI1_FIFO:
852         case INT_TYPE_AI3_FIFO:
853                 return interrupt_pcl818_ai_mode13_fifo(irq, d);
854 #ifdef PCL818_MODE13_AO
855         case INT_TYPE_AO1_INT:
856         case INT_TYPE_AO3_INT:
857                 return interrupt_pcl818_ao_mode13_int(irq, d);
858 #endif
859         default:
860                 break;
861         }
862
863         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
864
865         if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
866                 || (!devpriv->ai_mode)) {
867                 comedi_error(dev, "bad IRQ!");
868                 return IRQ_NONE;
869         }
870
871         comedi_error(dev, "IRQ from unknow source!");
872         return IRQ_NONE;
873 }
874
875 /*
876 ==============================================================================
877    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
878 */
879 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device * dev,
880         struct comedi_subdevice * s)
881 {
882         unsigned int flags;
883         unsigned int bytes;
884
885         rt_printk("mode13dma_int, mode: %d\n", mode);
886         disable_dma(devpriv->dma);      /*  disable dma */
887         bytes = devpriv->hwdmasize[0];
888         if (!devpriv->neverending_ai) {
889                 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /*  how many */
890                 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];       /*  how many DMA pages we must fiil */
891                 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];  /* on last dma transfer must be moved */
892                 devpriv->dma_runs_to_end--;
893                 if (devpriv->dma_runs_to_end >= 0)
894                         bytes = devpriv->hwdmasize[0];
895         }
896
897         devpriv->next_dma_buf = 0;
898         set_dma_mode(devpriv->dma, DMA_MODE_READ);
899         flags = claim_dma_lock();
900         clear_dma_ff(devpriv->dma);
901         set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
902         set_dma_count(devpriv->dma, bytes);
903         release_dma_lock(flags);
904         enable_dma(devpriv->dma);
905
906         if (mode == 1) {
907                 devpriv->ai_mode = INT_TYPE_AI1_DMA;
908                 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ+DMA */
909         } else {
910                 devpriv->ai_mode = INT_TYPE_AI3_DMA;
911                 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ+DMA */
912         };
913 }
914
915 #ifdef unused
916 /*
917 ==============================================================================
918    ANALOG INPUT MODE 1 or 3 DMA rtc, 818 cards
919 */
920 static void pcl818_ai_mode13dma_rtc(int mode, struct comedi_device * dev,
921         struct comedi_subdevice * s)
922 {
923         unsigned int flags;
924         short *pole;
925
926         set_dma_mode(devpriv->dma, DMA_MODE_READ | DMA_AUTOINIT);
927         flags = claim_dma_lock();
928         clear_dma_ff(devpriv->dma);
929         set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
930         set_dma_count(devpriv->dma, devpriv->hwdmasize[0]);
931         release_dma_lock(flags);
932         enable_dma(devpriv->dma);
933         devpriv->last_top_dma = 0;      /* devpriv->hwdmasize[0]; */
934         pole = (short *) devpriv->dmabuf[0];
935         devpriv->dmasamplsize = devpriv->hwdmasize[0] / 2;
936         pole[devpriv->dmasamplsize - 1] = MAGIC_DMA_WORD;
937 #ifdef unused
938         devpriv->rtc_freq = rtc_setfreq_irq(2048);
939         devpriv->rtc_irq_timer.expires =
940                 jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100;
941         devpriv->rtc_irq_timer.data = (unsigned long)dev;
942         devpriv->rtc_irq_timer.function = rtc_dropped_irq;
943
944         add_timer(&devpriv->rtc_irq_timer);
945 #endif
946
947         if (mode == 1) {
948                 devpriv->int818_mode = INT_TYPE_AI1_DMA_RTC;
949                 outb(0x07 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+DMA */
950         } else {
951                 devpriv->int818_mode = INT_TYPE_AI3_DMA_RTC;
952                 outb(0x06 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+DMA */
953         };
954 }
955 #endif
956
957 /*
958 ==============================================================================
959    ANALOG INPUT MODE 1 or 3, 818 cards
960 */
961 static int pcl818_ai_cmd_mode(int mode, struct comedi_device * dev,
962         struct comedi_subdevice * s)
963 {
964         struct comedi_cmd *cmd = &s->async->cmd;
965         int divisor1, divisor2;
966         unsigned int seglen;
967
968         rt_printk("pcl818_ai_cmd_mode()\n");
969         if ((!dev->irq) && (!devpriv->dma_rtc)) {
970                 comedi_error(dev, "IRQ not defined!");
971                 return -EINVAL;
972         }
973
974         if (devpriv->irq_blocked)
975                 return -EBUSY;
976
977         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
978
979         seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
980                 devpriv->ai_n_chan);
981         if (seglen < 1)
982                 return -EINVAL;
983         setup_channel_list(dev, s, devpriv->ai_chanlist,
984                 devpriv->ai_n_chan, seglen);
985
986         comedi_udelay(1);
987
988         devpriv->ai_act_scan = devpriv->ai_scans;
989         devpriv->ai_act_chan = 0;
990         devpriv->irq_blocked = 1;
991         devpriv->irq_was_now_closed = 0;
992         devpriv->neverending_ai = 0;
993         devpriv->act_chanlist_pos = 0;
994         devpriv->dma_runs_to_end = 0;
995
996         if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
997                 devpriv->neverending_ai = 1;    /* well, user want neverending */
998
999         if (mode == 1) {
1000                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1001                         &divisor2, &cmd->convert_arg, TRIG_ROUND_NEAREST);
1002                 if (divisor1 == 1) {    /* PCL718/818 crash if any divisor is set to 1 */
1003                         divisor1 = 2;
1004                         divisor2 /= 2;
1005                 }
1006                 if (divisor2 == 1) {
1007                         divisor2 = 2;
1008                         divisor1 /= 2;
1009                 }
1010         }
1011
1012         outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
1013
1014         switch (devpriv->dma) {
1015         case 1:         /*  DMA */
1016         case 3:
1017                 if (devpriv->dma_rtc == 0) {
1018                         pcl818_ai_mode13dma_int(mode, dev, s);
1019                 }
1020 #ifdef unused
1021                 else {
1022                         pcl818_ai_mode13dma_rtc(mode, dev, s);
1023                 }
1024 #else
1025                 else {
1026                         return -EINVAL;
1027                 }
1028 #endif
1029                 break;
1030         case 0:
1031                 if (!devpriv->usefifo) {
1032                         /* IRQ */
1033                         /* rt_printk("IRQ\n"); */
1034                         if (mode == 1) {
1035                                 devpriv->ai_mode = INT_TYPE_AI1_INT;
1036                                 /* Pacer+IRQ */
1037                                 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1038                         } else {
1039                                 devpriv->ai_mode = INT_TYPE_AI3_INT;
1040                                 /* Ext trig+IRQ */
1041                                 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);
1042                         }
1043                 } else {
1044                         /* FIFO */
1045                         /* enable FIFO */
1046                         outb(1, dev->iobase + PCL818_FI_ENABLE);
1047                         if (mode == 1) {
1048                                 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
1049                                 /* Pacer */
1050                                 outb(0x03, dev->iobase + PCL818_CONTROL);
1051                         } else {
1052                                 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
1053                                 outb(0x02, dev->iobase + PCL818_CONTROL);
1054                         }
1055                 }
1056         }
1057
1058         start_pacer(dev, mode, divisor1, divisor2);
1059
1060 #ifdef unused
1061         switch (devpriv->ai_mode) {
1062         case INT_TYPE_AI1_DMA_RTC:
1063         case INT_TYPE_AI3_DMA_RTC:
1064                 set_rtc_irq_bit(1);     /* start RTC */
1065                 break;
1066         }
1067 #endif
1068         rt_printk("pcl818_ai_cmd_mode() end\n");
1069         return 0;
1070 }
1071
1072 #ifdef unused
1073 /*
1074 ==============================================================================
1075    ANALOG OUTPUT MODE 1 or 3, 818 cards
1076 */
1077 #ifdef PCL818_MODE13_AO
1078 static int pcl818_ao_mode13(int mode, struct comedi_device * dev, struct comedi_subdevice * s,
1079         comedi_trig * it)
1080 {
1081         int divisor1, divisor2;
1082
1083         if (!dev->irq) {
1084                 comedi_error(dev, "IRQ not defined!");
1085                 return -EINVAL;
1086         }
1087
1088         if (devpriv->irq_blocked)
1089                 return -EBUSY;
1090
1091         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
1092
1093         devpriv->int13_act_scan = it->n;
1094         devpriv->int13_act_chan = 0;
1095         devpriv->irq_blocked = 1;
1096         devpriv->irq_was_now_closed = 0;
1097         devpriv->neverending_ai = 0;
1098         devpriv->act_chanlist_pos = 0;
1099
1100         if (mode == 1) {
1101                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1102                         &divisor2, &it->trigvar, TRIG_ROUND_NEAREST);
1103                 if (divisor1 == 1) {    /* PCL818 crash if any divisor is set to 1 */
1104                         divisor1 = 2;
1105                         divisor2 /= 2;
1106                 }
1107                 if (divisor2 == 1) {
1108                         divisor2 = 2;
1109                         divisor1 /= 2;
1110                 }
1111         }
1112
1113         outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
1114         if (mode == 1) {
1115                 devpriv->int818_mode = INT_TYPE_AO1_INT;
1116                 outb(0x83 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ */
1117         } else {
1118                 devpriv->int818_mode = INT_TYPE_AO3_INT;
1119                 outb(0x82 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ */
1120         };
1121
1122         start_pacer(dev, mode, divisor1, divisor2);
1123
1124         return 0;
1125 }
1126
1127 /*
1128 ==============================================================================
1129    ANALOG OUTPUT MODE 1, 818 cards
1130 */
1131 static int pcl818_ao_mode1(struct comedi_device * dev, struct comedi_subdevice * s,
1132         comedi_trig * it)
1133 {
1134         return pcl818_ao_mode13(1, dev, s, it);
1135 }
1136
1137 /*
1138 ==============================================================================
1139    ANALOG OUTPUT MODE 3, 818 cards
1140 */
1141 static int pcl818_ao_mode3(struct comedi_device * dev, struct comedi_subdevice * s,
1142         comedi_trig * it)
1143 {
1144         return pcl818_ao_mode13(3, dev, s, it);
1145 }
1146 #endif
1147 #endif
1148
1149 /*
1150 ==============================================================================
1151  Start/stop pacer onboard pacer
1152 */
1153 static void start_pacer(struct comedi_device * dev, int mode, unsigned int divisor1,
1154         unsigned int divisor2)
1155 {
1156         outb(0xb4, dev->iobase + PCL818_CTRCTL);
1157         outb(0x74, dev->iobase + PCL818_CTRCTL);
1158         comedi_udelay(1);
1159
1160         if (mode == 1) {
1161                 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
1162                 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
1163                 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
1164                 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
1165         }
1166 }
1167
1168 /*
1169 ==============================================================================
1170  Check if channel list from user is builded correctly
1171  If it's ok, then program scan/gain logic
1172 */
1173 static int check_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1174         unsigned int *chanlist, unsigned int n_chan)
1175 {
1176         unsigned int chansegment[16];
1177         unsigned int i, nowmustbechan, seglen, segpos;
1178
1179         /* correct channel and range number check itself comedi/range.c */
1180         if (n_chan < 1) {
1181                 comedi_error(dev, "range/channel list is empty!");
1182                 return 0;
1183         }
1184
1185         if (n_chan > 1) {
1186                 /*  first channel is everytime ok */
1187                 chansegment[0] = chanlist[0];
1188                 /*  build part of chanlist */
1189                 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
1190
1191                         /* rt_printk("%d. %d * %d\n",i,
1192                          * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
1193
1194                         /* we detect loop, this must by finish */
1195
1196                         if (chanlist[0] == chanlist[i])
1197                                 break;
1198                         nowmustbechan =
1199                                 (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
1200                         if (nowmustbechan != CR_CHAN(chanlist[i])) {    /*  channel list isn't continous :-( */
1201                                 rt_printk
1202                                         ("comedi%d: pcl818: channel list must be continous! chanlist[%i]=%d but must be %d or %d!\n",
1203                                         dev->minor, i, CR_CHAN(chanlist[i]),
1204                                         nowmustbechan, CR_CHAN(chanlist[0]));
1205                                 return 0;
1206                         }
1207                         /*  well, this is next correct channel in list */
1208                         chansegment[i] = chanlist[i];
1209                 }
1210
1211                 /*  check whole chanlist */
1212                 for (i = 0, segpos = 0; i < n_chan; i++) {
1213                         /* 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])); */
1214                         if (chanlist[i] != chansegment[i % seglen]) {
1215                                 rt_printk
1216                                         ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
1217                                         dev->minor, i, CR_CHAN(chansegment[i]),
1218                                         CR_RANGE(chansegment[i]),
1219                                         CR_AREF(chansegment[i]),
1220                                         CR_CHAN(chanlist[i % seglen]),
1221                                         CR_RANGE(chanlist[i % seglen]),
1222                                         CR_AREF(chansegment[i % seglen]));
1223                                 return 0;       /*  chan/gain list is strange */
1224                         }
1225                 }
1226         } else {
1227                 seglen = 1;
1228         }
1229         rt_printk("check_channel_list: seglen %d\n", seglen);
1230         return seglen;
1231 }
1232
1233 static void setup_channel_list(struct comedi_device * dev, struct comedi_subdevice * s,
1234         unsigned int *chanlist, unsigned int n_chan, unsigned int seglen)
1235 {
1236         int i;
1237
1238         devpriv->act_chanlist_len = seglen;
1239         devpriv->act_chanlist_pos = 0;
1240
1241         for (i = 0; i < seglen; i++) {  /*  store range list to card */
1242                 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
1243                 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);       /* select channel */
1244                 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);        /* select gain */
1245         }
1246
1247         comedi_udelay(1);
1248
1249         /* select channel interval to scan */
1250         outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
1251                                 1] << 4), dev->iobase + PCL818_MUX);
1252 }
1253
1254 /*
1255 ==============================================================================
1256  Check if board is switched to SE (1) or DIFF(0) mode
1257 */
1258 static int check_single_ended(unsigned int port)
1259 {
1260         if (inb(port + PCL818_STATUS) & 0x20) {
1261                 return 1;
1262         } else {
1263                 return 0;
1264         }
1265 }
1266
1267 /*
1268 ==============================================================================
1269 */
1270 static int ai_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1271         struct comedi_cmd * cmd)
1272 {
1273         int err = 0;
1274         int tmp, divisor1, divisor2;
1275
1276         /* step 1: make sure trigger sources are trivially valid */
1277
1278         tmp = cmd->start_src;
1279         cmd->start_src &= TRIG_NOW;
1280         if (!cmd->start_src || tmp != cmd->start_src)
1281                 err++;
1282
1283         tmp = cmd->scan_begin_src;
1284         cmd->scan_begin_src &= TRIG_FOLLOW;
1285         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1286                 err++;
1287
1288         tmp = cmd->convert_src;
1289         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1290         if (!cmd->convert_src || tmp != cmd->convert_src)
1291                 err++;
1292
1293         tmp = cmd->scan_end_src;
1294         cmd->scan_end_src &= TRIG_COUNT;
1295         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1296                 err++;
1297
1298         tmp = cmd->stop_src;
1299         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1300         if (!cmd->stop_src || tmp != cmd->stop_src)
1301                 err++;
1302
1303         if (err) {
1304                 return 1;
1305         }
1306
1307         /* step 2: make sure trigger sources are unique and mutually compatible */
1308
1309         if (cmd->start_src != TRIG_NOW) {
1310                 cmd->start_src = TRIG_NOW;
1311                 err++;
1312         }
1313         if (cmd->scan_begin_src != TRIG_FOLLOW) {
1314                 cmd->scan_begin_src = TRIG_FOLLOW;
1315                 err++;
1316         }
1317         if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1318                 err++;
1319
1320         if (cmd->scan_end_src != TRIG_COUNT) {
1321                 cmd->scan_end_src = TRIG_COUNT;
1322                 err++;
1323         }
1324
1325         if (cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_COUNT)
1326                 err++;
1327
1328         if (err) {
1329                 return 2;
1330         }
1331
1332         /* step 3: make sure arguments are trivially compatible */
1333
1334         if (cmd->start_arg != 0) {
1335                 cmd->start_arg = 0;
1336                 err++;
1337         }
1338
1339         if (cmd->scan_begin_arg != 0) {
1340                 cmd->scan_begin_arg = 0;
1341                 err++;
1342         }
1343
1344         if (cmd->convert_src == TRIG_TIMER) {
1345                 if (cmd->convert_arg < this_board->ns_min) {
1346                         cmd->convert_arg = this_board->ns_min;
1347                         err++;
1348                 }
1349         } else {                /* TRIG_EXT */
1350                 if (cmd->convert_arg != 0) {
1351                         cmd->convert_arg = 0;
1352                         err++;
1353                 }
1354         }
1355
1356         if (!cmd->chanlist_len) {
1357                 cmd->chanlist_len = 1;
1358                 err++;
1359         }
1360         if (cmd->chanlist_len > s->n_chan) {
1361                 cmd->chanlist_len = s->n_chan;
1362                 err++;
1363         }
1364         if (cmd->scan_end_arg != cmd->chanlist_len) {
1365                 cmd->scan_end_arg = cmd->chanlist_len;
1366                 err++;
1367         }
1368         if (cmd->stop_src == TRIG_COUNT) {
1369                 if (!cmd->stop_arg) {
1370                         cmd->stop_arg = 1;
1371                         err++;
1372                 }
1373         } else {                /* TRIG_NONE */
1374                 if (cmd->stop_arg != 0) {
1375                         cmd->stop_arg = 0;
1376                         err++;
1377                 }
1378         }
1379
1380         if (err) {
1381                 return 3;
1382         }
1383
1384         /* step 4: fix up any arguments */
1385
1386         if (cmd->convert_src == TRIG_TIMER) {
1387                 tmp = cmd->convert_arg;
1388                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1389                         &divisor2, &cmd->convert_arg,
1390                         cmd->flags & TRIG_ROUND_MASK);
1391                 if (cmd->convert_arg < this_board->ns_min)
1392                         cmd->convert_arg = this_board->ns_min;
1393                 if (tmp != cmd->convert_arg)
1394                         err++;
1395         }
1396
1397         if (err) {
1398                 return 4;
1399         }
1400
1401         /* step 5: complain about special chanlist considerations */
1402
1403         if (cmd->chanlist) {
1404                 if (!check_channel_list(dev, s, cmd->chanlist,
1405                                 cmd->chanlist_len))
1406                         return 5;       /*  incorrect channels list */
1407         }
1408
1409         return 0;
1410 }
1411
1412 /*
1413 ==============================================================================
1414 */
1415 static int ai_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
1416 {
1417         struct comedi_cmd *cmd = &s->async->cmd;
1418         int retval;
1419
1420         rt_printk("pcl818_ai_cmd()\n");
1421         devpriv->ai_n_chan = cmd->chanlist_len;
1422         devpriv->ai_chanlist = cmd->chanlist;
1423         devpriv->ai_flags = cmd->flags;
1424         devpriv->ai_data_len = s->async->prealloc_bufsz;
1425         devpriv->ai_data = s->async->prealloc_buf;
1426         devpriv->ai_timer1 = 0;
1427         devpriv->ai_timer2 = 0;
1428
1429         if (cmd->stop_src == TRIG_COUNT) {
1430                 devpriv->ai_scans = cmd->stop_arg;
1431         } else {
1432                 devpriv->ai_scans = 0;
1433         }
1434
1435         if (cmd->scan_begin_src == TRIG_FOLLOW) {       /*  mode 1, 3 */
1436                 if (cmd->convert_src == TRIG_TIMER) {   /*  mode 1 */
1437                         devpriv->ai_timer1 = cmd->convert_arg;
1438                         retval = pcl818_ai_cmd_mode(1, dev, s);
1439                         rt_printk("pcl818_ai_cmd() end\n");
1440                         return retval;
1441                 }
1442                 if (cmd->convert_src == TRIG_EXT) {     /*  mode 3 */
1443                         return pcl818_ai_cmd_mode(3, dev, s);
1444                 }
1445         }
1446
1447         return -1;
1448 }
1449
1450 /*
1451 ==============================================================================
1452  cancel any mode 1-4 AI
1453 */
1454 static int pcl818_ai_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1455 {
1456         if (devpriv->irq_blocked > 0) {
1457                 rt_printk("pcl818_ai_cancel()\n");
1458                 devpriv->irq_was_now_closed = 1;
1459
1460                 switch (devpriv->ai_mode) {
1461 #ifdef unused
1462                 case INT_TYPE_AI1_DMA_RTC:
1463                 case INT_TYPE_AI3_DMA_RTC:
1464                         set_rtc_irq_bit(0);     /*  stop RTC */
1465                         del_timer(&devpriv->rtc_irq_timer);
1466 #endif
1467                 case INT_TYPE_AI1_DMA:
1468                 case INT_TYPE_AI3_DMA:
1469                         if (devpriv->neverending_ai ||
1470                                         (!devpriv->neverending_ai &&
1471                                          devpriv->ai_act_scan > 0)) {
1472                                 /* wait for running dma transfer to end, do cleanup in interrupt */
1473                                 goto end;
1474                         }
1475                         disable_dma(devpriv->dma);
1476                 case INT_TYPE_AI1_INT:
1477                 case INT_TYPE_AI3_INT:
1478                 case INT_TYPE_AI1_FIFO:
1479                 case INT_TYPE_AI3_FIFO:
1480 #ifdef PCL818_MODE13_AO
1481                 case INT_TYPE_AO1_INT:
1482                 case INT_TYPE_AO3_INT:
1483 #endif
1484                         outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);   /* Stop A/D */
1485                         comedi_udelay(1);
1486                         start_pacer(dev, -1, 0, 0);
1487                         outb(0, dev->iobase + PCL818_AD_LO);
1488                         inb(dev->iobase + PCL818_AD_LO);
1489                         inb(dev->iobase + PCL818_AD_HI);
1490                         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
1491                         outb(0, dev->iobase + PCL818_CONTROL);  /* Stop A/D */
1492                         if (devpriv->usefifo) { /*  FIFO shutdown */
1493                                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1494                                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1495                                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1496                         }
1497                         devpriv->irq_blocked = 0;
1498                         devpriv->last_int_sub = s;
1499                         devpriv->neverending_ai = 0;
1500                         devpriv->ai_mode = 0;
1501                         devpriv->irq_was_now_closed = 0;
1502                         break;
1503                 }
1504         }
1505
1506       end:
1507         rt_printk("pcl818_ai_cancel() end\n");
1508         return 0;
1509 }
1510
1511 /*
1512 ==============================================================================
1513  chech for PCL818
1514 */
1515 static int pcl818_check(unsigned long iobase)
1516 {
1517         outb(0x00, iobase + PCL818_MUX);
1518         comedi_udelay(1);
1519         if (inb(iobase + PCL818_MUX) != 0x00)
1520                 return 1;       /* there isn't card */
1521         outb(0x55, iobase + PCL818_MUX);
1522         comedi_udelay(1);
1523         if (inb(iobase + PCL818_MUX) != 0x55)
1524                 return 1;       /* there isn't card */
1525         outb(0x00, iobase + PCL818_MUX);
1526         comedi_udelay(1);
1527         outb(0x18, iobase + PCL818_CONTROL);
1528         comedi_udelay(1);
1529         if (inb(iobase + PCL818_CONTROL) != 0x18)
1530                 return 1;       /* there isn't card */
1531         return 0;               /*  ok, card exist */
1532 }
1533
1534 /*
1535 ==============================================================================
1536  reset whole PCL-818 cards
1537 */
1538 static void pcl818_reset(struct comedi_device * dev)
1539 {
1540         if (devpriv->usefifo) { /*  FIFO shutdown */
1541                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1542                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1543                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1544         }
1545         outb(0, dev->iobase + PCL818_DA_LO);    /*  DAC=0V */
1546         outb(0, dev->iobase + PCL818_DA_HI);
1547         comedi_udelay(1);
1548         outb(0, dev->iobase + PCL818_DO_HI);    /*  DO=$0000 */
1549         outb(0, dev->iobase + PCL818_DO_LO);
1550         comedi_udelay(1);
1551         outb(0, dev->iobase + PCL818_CONTROL);
1552         outb(0, dev->iobase + PCL818_CNTENABLE);
1553         outb(0, dev->iobase + PCL818_MUX);
1554         outb(0, dev->iobase + PCL818_CLRINT);
1555         outb(0xb0, dev->iobase + PCL818_CTRCTL);        /* Stop pacer */
1556         outb(0x70, dev->iobase + PCL818_CTRCTL);
1557         outb(0x30, dev->iobase + PCL818_CTRCTL);
1558         if (this_board->is_818) {
1559                 outb(0, dev->iobase + PCL818_RANGE);
1560         } else {
1561                 outb(0, dev->iobase + PCL718_DA2_LO);
1562                 outb(0, dev->iobase + PCL718_DA2_HI);
1563         }
1564 }
1565
1566 #ifdef unused
1567 /*
1568 ==============================================================================
1569   Enable(1)/disable(0) periodic interrupts from RTC
1570 */
1571 static int set_rtc_irq_bit(unsigned char bit)
1572 {
1573         unsigned char val;
1574         unsigned long flags;
1575
1576         if (bit == 1) {
1577                 RTC_timer_lock++;
1578                 if (RTC_timer_lock > 1)
1579                         return 0;
1580         } else {
1581                 RTC_timer_lock--;
1582                 if (RTC_timer_lock < 0)
1583                         RTC_timer_lock = 0;
1584                 if (RTC_timer_lock > 0)
1585                         return 0;
1586         }
1587
1588         save_flags(flags);
1589         cli();
1590         val = CMOS_READ(RTC_CONTROL);
1591         if (bit) {
1592                 val |= RTC_PIE;
1593         } else {
1594                 val &= ~RTC_PIE;
1595         }
1596         CMOS_WRITE(val, RTC_CONTROL);
1597         CMOS_READ(RTC_INTR_FLAGS);
1598         restore_flags(flags);
1599         return 0;
1600 }
1601
1602 /*
1603 ==============================================================================
1604   Restart RTC if something stop it (xntpd every 11 mins or large IDE transfers)
1605 */
1606 static void rtc_dropped_irq(unsigned long data)
1607 {
1608         struct comedi_device *dev = (void *)data;
1609         unsigned long flags, tmp;
1610
1611         switch (devpriv->int818_mode) {
1612         case INT_TYPE_AI1_DMA_RTC:
1613         case INT_TYPE_AI3_DMA_RTC:
1614                 mod_timer(&devpriv->rtc_irq_timer,
1615                         jiffies + HZ / devpriv->rtc_freq + 2 * HZ / 100);
1616                 save_flags(flags);
1617                 cli();
1618                 tmp = (CMOS_READ(RTC_INTR_FLAGS) & 0xF0);       /* restart */
1619                 restore_flags(flags);
1620                 break;
1621         };
1622 }
1623
1624 /*
1625 ==============================================================================
1626   Set frequency of interrupts from RTC
1627 */
1628 static int rtc_setfreq_irq(int freq)
1629 {
1630         int tmp = 0;
1631         int rtc_freq;
1632         unsigned char val;
1633         unsigned long flags;
1634
1635         if (freq < 2)
1636                 freq = 2;
1637         if (freq > 8192)
1638                 freq = 8192;
1639
1640         while (freq > (1 << tmp))
1641                 tmp++;
1642
1643         rtc_freq = 1 << tmp;
1644
1645         save_flags(flags);
1646         cli();
1647         val = CMOS_READ(RTC_FREQ_SELECT) & 0xf0;
1648         val |= (16 - tmp);
1649         CMOS_WRITE(val, RTC_FREQ_SELECT);
1650         restore_flags(flags);
1651         return rtc_freq;
1652 }
1653 #endif
1654
1655 /*
1656 ==============================================================================
1657   Free any resources that we have claimed
1658 */
1659 static void free_resources(struct comedi_device * dev)
1660 {
1661         /* rt_printk("free_resource()\n"); */
1662         if (dev->private) {
1663                 pcl818_ai_cancel(dev, devpriv->sub_ai);
1664                 pcl818_reset(dev);
1665                 if (devpriv->dma)
1666                         free_dma(devpriv->dma);
1667                 if (devpriv->dmabuf[0])
1668                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1669                 if (devpriv->dmabuf[1])
1670                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1671 #ifdef unused
1672                 if (devpriv->rtc_irq)
1673                         comedi_free_irq(devpriv->rtc_irq, dev);
1674                 if ((devpriv->dma_rtc) && (RTC_lock == 1)) {
1675                         if (devpriv->rtc_iobase)
1676                                 release_region(devpriv->rtc_iobase,
1677                                         devpriv->rtc_iosize);
1678                 }
1679                 if (devpriv->dma_rtc)
1680                         RTC_lock--;
1681 #endif
1682         }
1683
1684         if (dev->irq)
1685                 free_irq(dev->irq, dev);
1686         if (dev->iobase)
1687                 release_region(dev->iobase, devpriv->io_range);
1688         /* rt_printk("free_resource() end\n"); */
1689 }
1690
1691 /*
1692 ==============================================================================
1693
1694    Initialization
1695
1696 */
1697 static int pcl818_attach(struct comedi_device * dev, struct comedi_devconfig * it)
1698 {
1699         int ret;
1700         unsigned long iobase;
1701         unsigned int irq;
1702         int dma;
1703         unsigned long pages;
1704         struct comedi_subdevice *s;
1705
1706         if ((ret = alloc_private(dev, sizeof(struct pcl818_private))) < 0)
1707                 return ret;     /* Can't alloc mem */
1708
1709         /* claim our I/O space */
1710         iobase = it->options[0];
1711         printk("comedi%d: pcl818:  board=%s, ioport=0x%03lx",
1712                 dev->minor, this_board->name, iobase);
1713         devpriv->io_range = this_board->io_range;
1714         if ((this_board->fifo) && (it->options[2] == -1)) {     /*  we've board with FIFO and we want to use FIFO */
1715                 devpriv->io_range = PCLx1xFIFO_RANGE;
1716                 devpriv->usefifo = 1;
1717         }
1718         if (!request_region(iobase, devpriv->io_range, "pcl818")) {
1719                 rt_printk("I/O port conflict\n");
1720                 return -EIO;
1721         }
1722
1723         dev->iobase = iobase;
1724
1725         if (pcl818_check(iobase)) {
1726                 rt_printk(", I can't detect board. FAIL!\n");
1727                 return -EIO;
1728         }
1729
1730         /* set up some name stuff */
1731         dev->board_name = this_board->name;
1732         /* grab our IRQ */
1733         irq = 0;
1734         if (this_board->IRQbits != 0) { /* board support IRQ */
1735                 irq = it->options[1];
1736                 if (irq) {      /* we want to use IRQ */
1737                         if (((1 << irq) & this_board->IRQbits) == 0) {
1738                                 rt_printk
1739                                         (", IRQ %u is out of allowed range, DISABLING IT",
1740                                         irq);
1741                                 irq = 0;        /* Bad IRQ */
1742                         } else {
1743                                 if (comedi_request_irq(irq, interrupt_pcl818, 0,
1744                                                 "pcl818", dev)) {
1745                                         rt_printk
1746                                                 (", unable to allocate IRQ %u, DISABLING IT",
1747                                                 irq);
1748                                         irq = 0;        /* Can't use IRQ */
1749                                 } else {
1750                                         rt_printk(", irq=%u", irq);
1751                                 }
1752                         }
1753                 }
1754         }
1755
1756         dev->irq = irq;
1757         if (irq) {
1758                 devpriv->irq_free = 1;
1759         } /* 1=we have allocated irq */
1760         else {
1761                 devpriv->irq_free = 0;
1762         }
1763         devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1764         devpriv->ai_mode = 0;   /* mode of irq */
1765
1766 #ifdef unused
1767         /* grab RTC for DMA operations */
1768         devpriv->dma_rtc = 0;
1769         if (it->options[2] > 0) {       /*  we want to use DMA */
1770                 if (RTC_lock == 0) {
1771                         if (!request_region(RTC_PORT(0), RTC_IO_EXTENT,
1772                                         "pcl818 (RTC)"))
1773                                 goto no_rtc;
1774                 }
1775                 devpriv->rtc_iobase = RTC_PORT(0);
1776                 devpriv->rtc_iosize = RTC_IO_EXTENT;
1777                 RTC_lock++;
1778                 if (!comedi_request_irq(RTC_IRQ,
1779                                 interrupt_pcl818_ai_mode13_dma_rtc, 0,
1780                                 "pcl818 DMA (RTC)", dev)) {
1781                         devpriv->dma_rtc = 1;
1782                         devpriv->rtc_irq = RTC_IRQ;
1783                         rt_printk(", dma_irq=%u", devpriv->rtc_irq);
1784                 } else {
1785                         RTC_lock--;
1786                         if (RTC_lock == 0) {
1787                                 if (devpriv->rtc_iobase)
1788                                         release_region(devpriv->rtc_iobase,
1789                                                 devpriv->rtc_iosize);
1790                         }
1791                         devpriv->rtc_iobase = 0;
1792                         devpriv->rtc_iosize = 0;
1793                 }
1794         }
1795
1796       no_rtc:
1797 #endif
1798         /* grab our DMA */
1799         dma = 0;
1800         devpriv->dma = dma;
1801         if ((devpriv->irq_free == 0) && (devpriv->dma_rtc == 0))
1802                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1803         if (this_board->DMAbits != 0) { /* board support DMA */
1804                 dma = it->options[2];
1805                 if (dma < 1)
1806                         goto no_dma;    /* DMA disabled */
1807                 if (((1 << dma) & this_board->DMAbits) == 0) {
1808                         rt_printk(", DMA is out of allowed range, FAIL!\n");
1809                         return -EINVAL; /* Bad DMA */
1810                 }
1811                 ret = request_dma(dma, "pcl818");
1812                 if (ret) {
1813                         rt_printk(", unable to allocate DMA %u, FAIL!\n", dma);
1814                         return -EBUSY;  /* DMA isn't free */
1815                 }
1816                 devpriv->dma = dma;
1817                 rt_printk(", dma=%u", dma);
1818                 pages = 2;      /* we need 16KB */
1819                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1820                 if (!devpriv->dmabuf[0]) {
1821                         rt_printk(", unable to allocate DMA buffer, FAIL!\n");
1822                         /* maybe experiment with try_to_free_pages() will help .... */
1823                         return -EBUSY;  /* no buffer :-( */
1824                 }
1825                 devpriv->dmapages[0] = pages;
1826                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1827                 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1828                 /* rt_printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1829                 if (devpriv->dma_rtc == 0) {    /*  we must do duble buff :-( */
1830                         devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1831                         if (!devpriv->dmabuf[1]) {
1832                                 rt_printk
1833                                         (", unable to allocate DMA buffer, FAIL!\n");
1834                                 return -EBUSY;
1835                         }
1836                         devpriv->dmapages[1] = pages;
1837                         devpriv->hwdmaptr[1] =
1838                                 virt_to_bus((void *)devpriv->dmabuf[1]);
1839                         devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1840                 }
1841         }
1842
1843       no_dma:
1844
1845         if ((ret = alloc_subdevices(dev, 4)) < 0)
1846                 return ret;
1847
1848         s = dev->subdevices + 0;
1849         if (!this_board->n_aichan_se) {
1850                 s->type = COMEDI_SUBD_UNUSED;
1851         } else {
1852                 s->type = COMEDI_SUBD_AI;
1853                 devpriv->sub_ai = s;
1854                 s->subdev_flags = SDF_READABLE;
1855                 if (check_single_ended(dev->iobase)) {
1856                         s->n_chan = this_board->n_aichan_se;
1857                         s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1858                         printk(", %dchans S.E. DAC", s->n_chan);
1859                 } else {
1860                         s->n_chan = this_board->n_aichan_diff;
1861                         s->subdev_flags |= SDF_DIFF;
1862                         printk(", %dchans DIFF DAC", s->n_chan);
1863                 }
1864                 s->maxdata = this_board->ai_maxdata;
1865                 s->len_chanlist = s->n_chan;
1866                 s->range_table = this_board->ai_range_type;
1867                 s->cancel = pcl818_ai_cancel;
1868                 s->insn_read = pcl818_ai_insn_read;
1869                 if ((irq) || (devpriv->dma_rtc)) {
1870                         dev->read_subdev = s;
1871                         s->subdev_flags |= SDF_CMD_READ;
1872                         s->do_cmdtest = ai_cmdtest;
1873                         s->do_cmd = ai_cmd;
1874                 }
1875                 if (this_board->is_818) {
1876                         if ((it->options[4] == 1) || (it->options[4] == 10))
1877                                 s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1878                 } else {
1879                         switch (it->options[4]) {
1880                         case 0:
1881                                 s->range_table = &range_bipolar10;
1882                                 break;
1883                         case 1:
1884                                 s->range_table = &range_bipolar5;
1885                                 break;
1886                         case 2:
1887                                 s->range_table = &range_bipolar2_5;
1888                                 break;
1889                         case 3:
1890                                 s->range_table = &range718_bipolar1;
1891                                 break;
1892                         case 4:
1893                                 s->range_table = &range718_bipolar0_5;
1894                                 break;
1895                         case 6:
1896                                 s->range_table = &range_unipolar10;
1897                                 break;
1898                         case 7:
1899                                 s->range_table = &range_unipolar5;
1900                                 break;
1901                         case 8:
1902                                 s->range_table = &range718_unipolar2;
1903                                 break;
1904                         case 9:
1905                                 s->range_table = &range718_unipolar1;
1906                                 break;
1907                         default:
1908                                 s->range_table = &range_unknown;
1909                                 break;
1910                         }
1911                 }
1912         }
1913
1914         s = dev->subdevices + 1;
1915         if (!this_board->n_aochan) {
1916                 s->type = COMEDI_SUBD_UNUSED;
1917         } else {
1918                 s->type = COMEDI_SUBD_AO;
1919                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1920                 s->n_chan = this_board->n_aochan;
1921                 s->maxdata = this_board->ao_maxdata;
1922                 s->len_chanlist = this_board->n_aochan;
1923                 s->range_table = this_board->ao_range_type;
1924                 s->insn_read = pcl818_ao_insn_read;
1925                 s->insn_write = pcl818_ao_insn_write;
1926 #ifdef unused
1927 #ifdef PCL818_MODE13_AO
1928                 if (irq) {
1929                         s->trig[1] = pcl818_ao_mode1;
1930                         s->trig[3] = pcl818_ao_mode3;
1931                 }
1932 #endif
1933 #endif
1934                 if (this_board->is_818) {
1935                         if ((it->options[4] == 1) || (it->options[4] == 10))
1936                                 s->range_table = &range_unipolar10;
1937                         if (it->options[4] == 2)
1938                                 s->range_table = &range_unknown;
1939                 } else {
1940                         if ((it->options[5] == 1) || (it->options[5] == 10))
1941                                 s->range_table = &range_unipolar10;
1942                         if (it->options[5] == 2)
1943                                 s->range_table = &range_unknown;
1944                 }
1945         }
1946
1947         s = dev->subdevices + 2;
1948         if (!this_board->n_dichan) {
1949                 s->type = COMEDI_SUBD_UNUSED;
1950         } else {
1951                 s->type = COMEDI_SUBD_DI;
1952                 s->subdev_flags = SDF_READABLE;
1953                 s->n_chan = this_board->n_dichan;
1954                 s->maxdata = 1;
1955                 s->len_chanlist = this_board->n_dichan;
1956                 s->range_table = &range_digital;
1957                 s->insn_bits = pcl818_di_insn_bits;
1958         }
1959
1960         s = dev->subdevices + 3;
1961         if (!this_board->n_dochan) {
1962                 s->type = COMEDI_SUBD_UNUSED;
1963         } else {
1964                 s->type = COMEDI_SUBD_DO;
1965                 s->subdev_flags = SDF_WRITABLE;
1966                 s->n_chan = this_board->n_dochan;
1967                 s->maxdata = 1;
1968                 s->len_chanlist = this_board->n_dochan;
1969                 s->range_table = &range_digital;
1970                 s->insn_bits = pcl818_do_insn_bits;
1971         }
1972
1973         /* select 1/10MHz oscilator */
1974         if ((it->options[3] == 0) || (it->options[3] == 10)) {
1975                 devpriv->i8253_osc_base = 100;
1976         } else {
1977                 devpriv->i8253_osc_base = 1000;
1978         }
1979
1980         /* max sampling speed */
1981         devpriv->ns_min = this_board->ns_min;
1982
1983         if (!this_board->is_818) {
1984                 if ((it->options[6] == 1) || (it->options[6] == 100))
1985                         devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
1986         }
1987
1988         pcl818_reset(dev);
1989
1990         rt_printk("\n");
1991
1992         return 0;
1993 }
1994
1995 /*
1996 ==============================================================================
1997   Removes device
1998  */
1999 static int pcl818_detach(struct comedi_device * dev)
2000 {
2001         /*   rt_printk("comedi%d: pcl818: remove\n", dev->minor); */
2002         free_resources(dev);
2003         return 0;
2004 }