Merge branch 'v4l_for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab...
[firefly-linux-kernel-4.4.55.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 unknown (external reference)
54
55    Options for PCL-818, PCL-818H:
56     [0] - IO Base
57     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
58     [2] - DMA   (0=disable, 1, 3)
59     [3] - 0, 10=10MHz clock for 8254
60               1= 1MHz clock for 8254
61     [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
62           1, 10=D/A output 0-10V (internal reference -10V)
63           2    =D/A output unknown (external reference)
64
65    Options for PCL-818HD, PCL-818HG:
66     [0] - IO Base
67     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
68     [2] - DMA/FIFO  (-1=use FIFO, 0=disable both FIFO and DMA,
69                       1=use DMA ch 1, 3=use DMA ch 3)
70     [3] - 0, 10=10MHz clock for 8254
71               1= 1MHz clock for 8254
72     [4] - 0,  5=D/A output 0-5V  (internal reference -5V)
73           1, 10=D/A output 0-10V (internal reference -10V)
74           2    =D/A output unknown (external reference)
75
76    Options for PCL-718:
77     [0] - IO Base
78     [1] - IRQ   (0=disable, 2, 3, 4, 5, 6, 7)
79     [2] - DMA   (0=disable, 1, 3)
80     [3] - 0, 10=10MHz clock for 8254
81               1= 1MHz clock for 8254
82     [4] -     0=A/D Range is +/-10V
83               1=             +/-5V
84               2=             +/-2.5V
85               3=             +/-1V
86               4=             +/-0.5V
87               5=             user defined bipolar
88               6=             0-10V
89               7=             0-5V
90               8=             0-2V
91               9=             0-1V
92              10=             user defined unipolar
93     [5] - 0,  5=D/A outputs 0-5V  (internal reference -5V)
94           1, 10=D/A outputs 0-10V (internal reference -10V)
95               2=D/A outputs unknown (external reference)
96     [6] - 0, 60=max  60kHz A/D sampling
97           1,100=max 100kHz A/D sampling (PCL-718 with Option 001 installed)
98
99 */
100
101 #include <linux/ioport.h>
102 #include <linux/gfp.h>
103 #include <linux/delay.h>
104 #include <linux/io.h>
105 #include <linux/interrupt.h>
106 #include <asm/dma.h>
107
108 #include "../comedidev.h"
109
110 #include "comedi_fc.h"
111 #include "8253.h"
112
113 /* #define PCL818_MODE13_AO 1 */
114
115 /* boards constants */
116
117 #define boardPCL818L 0
118 #define boardPCL818H 1
119 #define boardPCL818HD 2
120 #define boardPCL818HG 3
121 #define boardPCL818 4
122 #define boardPCL718 5
123
124 /* IO space len */
125 #define PCLx1x_RANGE 16
126 /* IO space len if we use FIFO */
127 #define PCLx1xFIFO_RANGE 32
128
129 /* W: clear INT request */
130 #define PCL818_CLRINT 8
131 /* R: return status byte */
132 #define PCL818_STATUS 8
133 /* R: A/D high byte W: A/D range control */
134 #define PCL818_RANGE 1
135 /* R: next mux scan channel W: mux scan channel & range control pointer */
136 #define PCL818_MUX 2
137 /* R/W: operation control register */
138 #define PCL818_CONTROL 9
139 /* W: counter enable */
140 #define PCL818_CNTENABLE 10
141
142 /* R: low byte of A/D W: soft A/D trigger */
143 #define PCL818_AD_LO 0
144 /* R: high byte of A/D W: A/D range control */
145 #define PCL818_AD_HI 1
146 /* W: D/A low&high byte */
147 #define PCL818_DA_LO 4
148 #define PCL818_DA_HI 5
149 /* R: low&high byte of DI */
150 #define PCL818_DI_LO 3
151 #define PCL818_DI_HI 11
152 /* W: low&high byte of DO */
153 #define PCL818_DO_LO 3
154 #define PCL818_DO_HI 11
155 /* W: PCL718 second D/A */
156 #define PCL718_DA2_LO 6
157 #define PCL718_DA2_HI 7
158 /* counters */
159 #define PCL818_CTR0 12
160 #define PCL818_CTR1 13
161 #define PCL818_CTR2 14
162 /* W: counter control */
163 #define PCL818_CTRCTL 15
164
165 /* W: fifo enable/disable */
166 #define PCL818_FI_ENABLE 6
167 /* W: fifo interrupt clear */
168 #define PCL818_FI_INTCLR 20
169 /* W: fifo interrupt clear */
170 #define PCL818_FI_FLUSH 25
171 /* R: fifo status */
172 #define PCL818_FI_STATUS 25
173 /* R: one record from FIFO */
174 #define PCL818_FI_DATALO 23
175 #define PCL818_FI_DATAHI 23
176
177 /* type of interrupt handler */
178 #define INT_TYPE_AI1_INT 1
179 #define INT_TYPE_AI1_DMA 2
180 #define INT_TYPE_AI1_FIFO 3
181 #define INT_TYPE_AI3_INT 4
182 #define INT_TYPE_AI3_DMA 5
183 #define INT_TYPE_AI3_FIFO 6
184 #ifdef PCL818_MODE13_AO
185 #define INT_TYPE_AO1_INT 7
186 #define INT_TYPE_AO3_INT 8
187 #endif
188
189 #define MAGIC_DMA_WORD 0x5a5a
190
191 static const struct comedi_lrange range_pcl818h_ai = { 9, {
192                                                            BIP_RANGE(5),
193                                                            BIP_RANGE(2.5),
194                                                            BIP_RANGE(1.25),
195                                                            BIP_RANGE(0.625),
196                                                            UNI_RANGE(10),
197                                                            UNI_RANGE(5),
198                                                            UNI_RANGE(2.5),
199                                                            UNI_RANGE(1.25),
200                                                            BIP_RANGE(10),
201                                                            }
202 };
203
204 static const struct comedi_lrange range_pcl818hg_ai = { 10, {
205                                                              BIP_RANGE(5),
206                                                              BIP_RANGE(0.5),
207                                                              BIP_RANGE(0.05),
208                                                              BIP_RANGE(0.005),
209                                                              UNI_RANGE(10),
210                                                              UNI_RANGE(1),
211                                                              UNI_RANGE(0.1),
212                                                              UNI_RANGE(0.01),
213                                                              BIP_RANGE(10),
214                                                              BIP_RANGE(1),
215                                                              BIP_RANGE(0.1),
216                                                              BIP_RANGE(0.01),
217                                                              }
218 };
219
220 static const struct comedi_lrange range_pcl818l_l_ai = { 4, {
221                                                              BIP_RANGE(5),
222                                                              BIP_RANGE(2.5),
223                                                              BIP_RANGE(1.25),
224                                                              BIP_RANGE(0.625),
225                                                              }
226 };
227
228 static const struct comedi_lrange range_pcl818l_h_ai = { 4, {
229                                                              BIP_RANGE(10),
230                                                              BIP_RANGE(5),
231                                                              BIP_RANGE(2.5),
232                                                              BIP_RANGE(1.25),
233                                                              }
234 };
235
236 static const struct comedi_lrange range718_bipolar1 = { 1, {BIP_RANGE(1),} };
237 static const struct comedi_lrange range718_bipolar0_5 = {
238         1, {BIP_RANGE(0.5),} };
239 static const struct comedi_lrange range718_unipolar2 = { 1, {UNI_RANGE(2),} };
240 static const struct comedi_lrange range718_unipolar1 = { 1, {BIP_RANGE(1),} };
241
242 struct pcl818_board {
243
244         const char *name;       /*  driver name */
245         int n_ranges;           /*  len of range list */
246         int n_aichan_se;        /*  num of A/D chans in single ended  mode */
247         int n_aichan_diff;      /*  num of A/D chans in diferencial mode */
248         unsigned int ns_min;    /*  minimal allowed delay between samples (in ns) */
249         int n_aochan;           /*  num of D/A chans */
250         int n_dichan;           /*  num of DI chans */
251         int n_dochan;           /*  num of DO chans */
252         const struct comedi_lrange *ai_range_type;      /*  default A/D rangelist */
253         const struct comedi_lrange *ao_range_type;      /*  default D/A rangelist */
254         unsigned int io_range;  /*  len of IO space */
255         unsigned int IRQbits;   /*  allowed interrupts */
256         unsigned int DMAbits;   /*  allowed DMA chans */
257         int ai_maxdata;         /*  maxdata for A/D */
258         int ao_maxdata;         /*  maxdata for D/A */
259         unsigned char fifo;     /*  1=board has FIFO */
260         int is_818;
261 };
262
263 struct pcl818_private {
264
265         unsigned int dma;       /*  used DMA, 0=don't use DMA */
266         unsigned int io_range;
267         unsigned long dmabuf[2];        /*  pointers to begin of DMA buffers */
268         unsigned int dmapages[2];       /*  len of DMA buffers in PAGE_SIZEs */
269         unsigned int hwdmaptr[2];       /*  hardware address of DMA buffers */
270         unsigned int hwdmasize[2];      /*  len of DMA buffers in Bytes */
271         int next_dma_buf;       /*  which DMA buffer will be used next round */
272         long dma_runs_to_end;   /*  how many we must permorm DMA transfer to end of record */
273         unsigned long last_dma_run;     /*  how many bytes we must transfer on last DMA page */
274         unsigned char neverending_ai;   /*  if=1, then we do neverending record (you must use cancel()) */
275         unsigned int ns_min;    /*  manimal allowed delay between samples (in us) for actual card */
276         int i8253_osc_base;     /*  1/frequency of on board oscilator in ns */
277         int irq_free;           /*  1=have allocated IRQ */
278         int irq_blocked;        /*  1=IRQ now uses any subdev */
279         int irq_was_now_closed; /*  when IRQ finish, there's stored int818_mode for last interrupt */
280         int ai_mode;            /*  who now uses IRQ - 1=AI1 int, 2=AI1 dma, 3=AI3 int, 4AI3 dma */
281         struct comedi_subdevice *last_int_sub;  /*  ptr to subdevice which now finish */
282         int ai_act_scan;        /*  how many scans we finished */
283         int ai_act_chan;        /*  actual position in actual scan */
284         unsigned int act_chanlist[16];  /*  MUX setting for actual AI operations */
285         unsigned int act_chanlist_len;  /*  how long is actual MUX list */
286         unsigned int act_chanlist_pos;  /*  actual position in MUX list */
287         unsigned int ai_scans;  /*  len of scanlist */
288         unsigned int ai_n_chan; /*  how many channels is measured */
289         unsigned int *ai_chanlist;      /*  actaul chanlist */
290         unsigned int ai_flags;  /*  flaglist */
291         unsigned int ai_data_len;       /*  len of data buffer */
292         short *ai_data;         /*  data buffer */
293         unsigned int ai_timer1; /*  timers */
294         unsigned int ai_timer2;
295         struct comedi_subdevice *sub_ai;        /*  ptr to AI subdevice */
296         unsigned char usefifo;  /*  1=use fifo */
297         unsigned int ao_readback[2];
298 };
299
300 static const unsigned int muxonechan[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,      /*  used for gain list programming */
301         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
302 };
303
304 /*
305 ==============================================================================
306 */
307 static void setup_channel_list(struct comedi_device *dev,
308                                struct comedi_subdevice *s,
309                                unsigned int *chanlist, unsigned int n_chan,
310                                unsigned int seglen);
311 static int check_channel_list(struct comedi_device *dev,
312                               struct comedi_subdevice *s,
313                               unsigned int *chanlist, unsigned int n_chan);
314
315 static int pcl818_ai_cancel(struct comedi_device *dev,
316                             struct comedi_subdevice *s);
317 static void start_pacer(struct comedi_device *dev, int mode,
318                         unsigned int divisor1, unsigned int divisor2);
319
320 /*
321 ==============================================================================
322    ANALOG INPUT MODE0, 818 cards, slow version
323 */
324 static int pcl818_ai_insn_read(struct comedi_device *dev,
325                                struct comedi_subdevice *s,
326                                struct comedi_insn *insn, unsigned int *data)
327 {
328         int n;
329         int timeout;
330
331         /* software trigger, DMA and INT off */
332         outb(0, dev->iobase + PCL818_CONTROL);
333
334         /* select channel */
335         outb(muxonechan[CR_CHAN(insn->chanspec)], dev->iobase + PCL818_MUX);
336
337         /* select gain */
338         outb(CR_RANGE(insn->chanspec), dev->iobase + PCL818_RANGE);
339
340         for (n = 0; n < insn->n; n++) {
341
342                 /* clear INT (conversion end) flag */
343                 outb(0, dev->iobase + PCL818_CLRINT);
344
345                 /* start conversion */
346                 outb(0, dev->iobase + PCL818_AD_LO);
347
348                 timeout = 100;
349                 while (timeout--) {
350                         if (inb(dev->iobase + PCL818_STATUS) & 0x10)
351                                 goto conv_finish;
352                         udelay(1);
353                 }
354                 comedi_error(dev, "A/D insn timeout");
355                 /* clear INT (conversion end) flag */
356                 outb(0, dev->iobase + PCL818_CLRINT);
357                 return -EIO;
358
359 conv_finish:
360                 data[n] = ((inb(dev->iobase + PCL818_AD_HI) << 4) |
361                            (inb(dev->iobase + PCL818_AD_LO) >> 4));
362         }
363
364         return n;
365 }
366
367 /*
368 ==============================================================================
369    ANALOG OUTPUT MODE0, 818 cards
370    only one sample per call is supported
371 */
372 static int pcl818_ao_insn_read(struct comedi_device *dev,
373                                struct comedi_subdevice *s,
374                                struct comedi_insn *insn, unsigned int *data)
375 {
376         struct pcl818_private *devpriv = dev->private;
377         int n;
378         int chan = CR_CHAN(insn->chanspec);
379
380         for (n = 0; n < insn->n; n++)
381                 data[n] = devpriv->ao_readback[chan];
382
383         return n;
384 }
385
386 static int pcl818_ao_insn_write(struct comedi_device *dev,
387                                 struct comedi_subdevice *s,
388                                 struct comedi_insn *insn, unsigned int *data)
389 {
390         struct pcl818_private *devpriv = dev->private;
391         int n;
392         int chan = CR_CHAN(insn->chanspec);
393
394         for (n = 0; n < insn->n; n++) {
395                 devpriv->ao_readback[chan] = data[n];
396                 outb((data[n] & 0x000f) << 4, dev->iobase +
397                      (chan ? PCL718_DA2_LO : PCL818_DA_LO));
398                 outb((data[n] & 0x0ff0) >> 4, dev->iobase +
399                      (chan ? PCL718_DA2_HI : PCL818_DA_HI));
400         }
401
402         return n;
403 }
404
405 /*
406 ==============================================================================
407    DIGITAL INPUT MODE0, 818 cards
408
409    only one sample per call is supported
410 */
411 static int pcl818_di_insn_bits(struct comedi_device *dev,
412                                struct comedi_subdevice *s,
413                                struct comedi_insn *insn, unsigned int *data)
414 {
415         data[1] = inb(dev->iobase + PCL818_DI_LO) |
416             (inb(dev->iobase + PCL818_DI_HI) << 8);
417
418         return insn->n;
419 }
420
421 /*
422 ==============================================================================
423    DIGITAL OUTPUT MODE0, 818 cards
424
425    only one sample per call is supported
426 */
427 static int pcl818_do_insn_bits(struct comedi_device *dev,
428                                struct comedi_subdevice *s,
429                                struct comedi_insn *insn, unsigned int *data)
430 {
431         s->state &= ~data[0];
432         s->state |= (data[0] & data[1]);
433
434         outb(s->state & 0xff, dev->iobase + PCL818_DO_LO);
435         outb((s->state >> 8), dev->iobase + PCL818_DO_HI);
436
437         data[1] = s->state;
438
439         return insn->n;
440 }
441
442 /*
443 ==============================================================================
444    analog input interrupt mode 1 & 3, 818 cards
445    one sample per interrupt version
446 */
447 static irqreturn_t interrupt_pcl818_ai_mode13_int(int irq, void *d)
448 {
449         struct comedi_device *dev = d;
450         struct pcl818_private *devpriv = dev->private;
451         struct comedi_subdevice *s = &dev->subdevices[0];
452         int low;
453         int timeout = 50;       /* wait max 50us */
454
455         while (timeout--) {
456                 if (inb(dev->iobase + PCL818_STATUS) & 0x10)
457                         goto conv_finish;
458                 udelay(1);
459         }
460         outb(0, dev->iobase + PCL818_STATUS);   /* clear INT request */
461         comedi_error(dev, "A/D mode1/3 IRQ without DRDY!");
462         pcl818_ai_cancel(dev, s);
463         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
464         comedi_event(dev, s);
465         return IRQ_HANDLED;
466
467 conv_finish:
468         low = inb(dev->iobase + PCL818_AD_LO);
469         comedi_buf_put(s->async, ((inb(dev->iobase + PCL818_AD_HI) << 4) | (low >> 4)));        /*  get one sample */
470         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
471
472         if ((low & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
473                 printk
474                     ("comedi: A/D mode1/3 IRQ - channel dropout %x!=%x !\n",
475                      (low & 0xf),
476                      devpriv->act_chanlist[devpriv->act_chanlist_pos]);
477                 pcl818_ai_cancel(dev, s);
478                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
479                 comedi_event(dev, s);
480                 return IRQ_HANDLED;
481         }
482         devpriv->act_chanlist_pos++;
483         if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
484                 devpriv->act_chanlist_pos = 0;
485
486         s->async->cur_chan++;
487         if (s->async->cur_chan >= devpriv->ai_n_chan) {
488                 /*  printk("E"); */
489                 s->async->cur_chan = 0;
490                 devpriv->ai_act_scan--;
491         }
492
493         if (!devpriv->neverending_ai) {
494                 if (devpriv->ai_act_scan == 0) {        /* all data sampled */
495                         pcl818_ai_cancel(dev, s);
496                         s->async->events |= COMEDI_CB_EOA;
497                 }
498         }
499         comedi_event(dev, s);
500         return IRQ_HANDLED;
501 }
502
503 /*
504 ==============================================================================
505    analog input dma mode 1 & 3, 818 cards
506 */
507 static irqreturn_t interrupt_pcl818_ai_mode13_dma(int irq, void *d)
508 {
509         struct comedi_device *dev = d;
510         struct pcl818_private *devpriv = dev->private;
511         struct comedi_subdevice *s = &dev->subdevices[0];
512         int i, len, bufptr;
513         unsigned long flags;
514         short *ptr;
515
516         disable_dma(devpriv->dma);
517         devpriv->next_dma_buf = 1 - devpriv->next_dma_buf;
518         if ((devpriv->dma_runs_to_end) > -1 || devpriv->neverending_ai) {       /*  switch dma bufs */
519                 set_dma_mode(devpriv->dma, DMA_MODE_READ);
520                 flags = claim_dma_lock();
521                 set_dma_addr(devpriv->dma,
522                              devpriv->hwdmaptr[devpriv->next_dma_buf]);
523                 if (devpriv->dma_runs_to_end || devpriv->neverending_ai) {
524                         set_dma_count(devpriv->dma,
525                                       devpriv->hwdmasize[devpriv->
526                                                          next_dma_buf]);
527                 } else {
528                         set_dma_count(devpriv->dma, devpriv->last_dma_run);
529                 }
530                 release_dma_lock(flags);
531                 enable_dma(devpriv->dma);
532         }
533         printk("comedi: A/D mode1/3 IRQ \n");
534
535         devpriv->dma_runs_to_end--;
536         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
537         ptr = (short *)devpriv->dmabuf[1 - devpriv->next_dma_buf];
538
539         len = devpriv->hwdmasize[0] >> 1;
540         bufptr = 0;
541
542         for (i = 0; i < len; i++) {
543                 if ((ptr[bufptr] & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {  /*  dropout! */
544                         printk
545                             ("comedi: A/D mode1/3 DMA - channel dropout %d(card)!=%d(chanlist) at %d !\n",
546                              (ptr[bufptr] & 0xf),
547                              devpriv->act_chanlist[devpriv->act_chanlist_pos],
548                              devpriv->act_chanlist_pos);
549                         pcl818_ai_cancel(dev, s);
550                         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
551                         comedi_event(dev, s);
552                         return IRQ_HANDLED;
553                 }
554
555                 comedi_buf_put(s->async, ptr[bufptr++] >> 4);   /*  get one sample */
556
557                 devpriv->act_chanlist_pos++;
558                 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
559                         devpriv->act_chanlist_pos = 0;
560
561                 s->async->cur_chan++;
562                 if (s->async->cur_chan >= devpriv->ai_n_chan) {
563                         s->async->cur_chan = 0;
564                         devpriv->ai_act_scan--;
565                 }
566
567                 if (!devpriv->neverending_ai)
568                         if (devpriv->ai_act_scan == 0) {        /* all data sampled */
569                                 pcl818_ai_cancel(dev, s);
570                                 s->async->events |= COMEDI_CB_EOA;
571                                 comedi_event(dev, s);
572                                 /*  printk("done int ai13 dma\n"); */
573                                 return IRQ_HANDLED;
574                         }
575         }
576
577         if (len > 0)
578                 comedi_event(dev, s);
579         return IRQ_HANDLED;
580 }
581
582 /*
583 ==============================================================================
584    analog input interrupt mode 1 & 3, 818HD/HG cards
585 */
586 static irqreturn_t interrupt_pcl818_ai_mode13_fifo(int irq, void *d)
587 {
588         struct comedi_device *dev = d;
589         struct pcl818_private *devpriv = dev->private;
590         struct comedi_subdevice *s = &dev->subdevices[0];
591         int i, len, lo;
592
593         outb(0, dev->iobase + PCL818_FI_INTCLR);        /*  clear fifo int request */
594
595         lo = inb(dev->iobase + PCL818_FI_STATUS);
596
597         if (lo & 4) {
598                 comedi_error(dev, "A/D mode1/3 FIFO overflow!");
599                 pcl818_ai_cancel(dev, s);
600                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
601                 comedi_event(dev, s);
602                 return IRQ_HANDLED;
603         }
604
605         if (lo & 1) {
606                 comedi_error(dev, "A/D mode1/3 FIFO interrupt without data!");
607                 pcl818_ai_cancel(dev, s);
608                 s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
609                 comedi_event(dev, s);
610                 return IRQ_HANDLED;
611         }
612
613         if (lo & 2)
614                 len = 512;
615         else
616                 len = 0;
617
618         for (i = 0; i < len; i++) {
619                 lo = inb(dev->iobase + PCL818_FI_DATALO);
620                 if ((lo & 0xf) != devpriv->act_chanlist[devpriv->act_chanlist_pos]) {   /*  dropout! */
621                         printk
622                             ("comedi: A/D mode1/3 FIFO - channel dropout %d!=%d !\n",
623                              (lo & 0xf),
624                              devpriv->act_chanlist[devpriv->act_chanlist_pos]);
625                         pcl818_ai_cancel(dev, s);
626                         s->async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR;
627                         comedi_event(dev, s);
628                         return IRQ_HANDLED;
629                 }
630
631                 comedi_buf_put(s->async, (lo >> 4) | (inb(dev->iobase + PCL818_FI_DATAHI) << 4));       /*  get one sample */
632
633                 devpriv->act_chanlist_pos++;
634                 if (devpriv->act_chanlist_pos >= devpriv->act_chanlist_len)
635                         devpriv->act_chanlist_pos = 0;
636
637                 s->async->cur_chan++;
638                 if (s->async->cur_chan >= devpriv->ai_n_chan) {
639                         s->async->cur_chan = 0;
640                         devpriv->ai_act_scan--;
641                 }
642
643                 if (!devpriv->neverending_ai)
644                         if (devpriv->ai_act_scan == 0) {        /* all data sampled */
645                                 pcl818_ai_cancel(dev, s);
646                                 s->async->events |= COMEDI_CB_EOA;
647                                 comedi_event(dev, s);
648                                 return IRQ_HANDLED;
649                         }
650         }
651
652         if (len > 0)
653                 comedi_event(dev, s);
654         return IRQ_HANDLED;
655 }
656
657 /*
658 ==============================================================================
659     INT procedure
660 */
661 static irqreturn_t interrupt_pcl818(int irq, void *d)
662 {
663         struct comedi_device *dev = d;
664         struct pcl818_private *devpriv = dev->private;
665
666         if (!dev->attached) {
667                 comedi_error(dev, "premature interrupt");
668                 return IRQ_HANDLED;
669         }
670         /* printk("I\n"); */
671
672         if (devpriv->irq_blocked && devpriv->irq_was_now_closed) {
673                 if ((devpriv->neverending_ai || (!devpriv->neverending_ai &&
674                                                  devpriv->ai_act_scan > 0)) &&
675                     (devpriv->ai_mode == INT_TYPE_AI1_DMA ||
676                      devpriv->ai_mode == INT_TYPE_AI3_DMA)) {
677                         /* The cleanup from ai_cancel() has been delayed
678                            until now because the card doesn't seem to like
679                            being reprogrammed while a DMA transfer is in
680                            progress.
681                          */
682                         struct comedi_subdevice *s = &dev->subdevices[0];
683                         devpriv->ai_act_scan = 0;
684                         devpriv->neverending_ai = 0;
685                         pcl818_ai_cancel(dev, s);
686                 }
687
688                 outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
689
690                 return IRQ_HANDLED;
691         }
692
693         switch (devpriv->ai_mode) {
694         case INT_TYPE_AI1_DMA:
695         case INT_TYPE_AI3_DMA:
696                 return interrupt_pcl818_ai_mode13_dma(irq, d);
697         case INT_TYPE_AI1_INT:
698         case INT_TYPE_AI3_INT:
699                 return interrupt_pcl818_ai_mode13_int(irq, d);
700         case INT_TYPE_AI1_FIFO:
701         case INT_TYPE_AI3_FIFO:
702                 return interrupt_pcl818_ai_mode13_fifo(irq, d);
703 #ifdef PCL818_MODE13_AO
704         case INT_TYPE_AO1_INT:
705         case INT_TYPE_AO3_INT:
706                 return interrupt_pcl818_ao_mode13_int(irq, d);
707 #endif
708         default:
709                 break;
710         }
711
712         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
713
714         if ((!dev->irq) || (!devpriv->irq_free) || (!devpriv->irq_blocked)
715             || (!devpriv->ai_mode)) {
716                 comedi_error(dev, "bad IRQ!");
717                 return IRQ_NONE;
718         }
719
720         comedi_error(dev, "IRQ from unknown source!");
721         return IRQ_NONE;
722 }
723
724 /*
725 ==============================================================================
726    ANALOG INPUT MODE 1 or 3 DMA , 818 cards
727 */
728 static void pcl818_ai_mode13dma_int(int mode, struct comedi_device *dev,
729                                     struct comedi_subdevice *s)
730 {
731         struct pcl818_private *devpriv = dev->private;
732         unsigned int flags;
733         unsigned int bytes;
734
735         printk("mode13dma_int, mode: %d\n", mode);
736         disable_dma(devpriv->dma);      /*  disable dma */
737         bytes = devpriv->hwdmasize[0];
738         if (!devpriv->neverending_ai) {
739                 bytes = devpriv->ai_n_chan * devpriv->ai_scans * sizeof(short); /*  how many */
740                 devpriv->dma_runs_to_end = bytes / devpriv->hwdmasize[0];       /*  how many DMA pages we must fiil */
741                 devpriv->last_dma_run = bytes % devpriv->hwdmasize[0];  /* on last dma transfer must be moved */
742                 devpriv->dma_runs_to_end--;
743                 if (devpriv->dma_runs_to_end >= 0)
744                         bytes = devpriv->hwdmasize[0];
745         }
746
747         devpriv->next_dma_buf = 0;
748         set_dma_mode(devpriv->dma, DMA_MODE_READ);
749         flags = claim_dma_lock();
750         clear_dma_ff(devpriv->dma);
751         set_dma_addr(devpriv->dma, devpriv->hwdmaptr[0]);
752         set_dma_count(devpriv->dma, bytes);
753         release_dma_lock(flags);
754         enable_dma(devpriv->dma);
755
756         if (mode == 1) {
757                 devpriv->ai_mode = INT_TYPE_AI1_DMA;
758                 outb(0x87 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Pacer+IRQ+DMA */
759         } else {
760                 devpriv->ai_mode = INT_TYPE_AI3_DMA;
761                 outb(0x86 | (dev->irq << 4), dev->iobase + PCL818_CONTROL);     /* Ext trig+IRQ+DMA */
762         };
763 }
764
765 /*
766 ==============================================================================
767    ANALOG INPUT MODE 1 or 3, 818 cards
768 */
769 static int pcl818_ai_cmd_mode(int mode, struct comedi_device *dev,
770                               struct comedi_subdevice *s)
771 {
772         struct pcl818_private *devpriv = dev->private;
773         struct comedi_cmd *cmd = &s->async->cmd;
774         int divisor1 = 0, divisor2 = 0;
775         unsigned int seglen;
776
777         dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode()\n");
778         if (!dev->irq) {
779                 comedi_error(dev, "IRQ not defined!");
780                 return -EINVAL;
781         }
782
783         if (devpriv->irq_blocked)
784                 return -EBUSY;
785
786         start_pacer(dev, -1, 0, 0);     /*  stop pacer */
787
788         seglen = check_channel_list(dev, s, devpriv->ai_chanlist,
789                                     devpriv->ai_n_chan);
790         if (seglen < 1)
791                 return -EINVAL;
792         setup_channel_list(dev, s, devpriv->ai_chanlist,
793                            devpriv->ai_n_chan, seglen);
794
795         udelay(1);
796
797         devpriv->ai_act_scan = devpriv->ai_scans;
798         devpriv->ai_act_chan = 0;
799         devpriv->irq_blocked = 1;
800         devpriv->irq_was_now_closed = 0;
801         devpriv->neverending_ai = 0;
802         devpriv->act_chanlist_pos = 0;
803         devpriv->dma_runs_to_end = 0;
804
805         if ((devpriv->ai_scans == 0) || (devpriv->ai_scans == -1))
806                 devpriv->neverending_ai = 1;    /* well, user want neverending */
807
808         if (mode == 1) {
809                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
810                                           &divisor2, &cmd->convert_arg,
811                                           TRIG_ROUND_NEAREST);
812                 if (divisor1 == 1) {    /* PCL718/818 crash if any divisor is set to 1 */
813                         divisor1 = 2;
814                         divisor2 /= 2;
815                 }
816                 if (divisor2 == 1) {
817                         divisor2 = 2;
818                         divisor1 /= 2;
819                 }
820         }
821
822         outb(0, dev->iobase + PCL818_CNTENABLE);        /* enable pacer */
823
824         switch (devpriv->dma) {
825         case 1:         /*  DMA */
826         case 3:
827                 pcl818_ai_mode13dma_int(mode, dev, s);
828                 break;
829         case 0:
830                 if (!devpriv->usefifo) {
831                         /* IRQ */
832                         /* printk("IRQ\n"); */
833                         if (mode == 1) {
834                                 devpriv->ai_mode = INT_TYPE_AI1_INT;
835                                 /* Pacer+IRQ */
836                                 outb(0x83 | (dev->irq << 4),
837                                      dev->iobase + PCL818_CONTROL);
838                         } else {
839                                 devpriv->ai_mode = INT_TYPE_AI3_INT;
840                                 /* Ext trig+IRQ */
841                                 outb(0x82 | (dev->irq << 4),
842                                      dev->iobase + PCL818_CONTROL);
843                         }
844                 } else {
845                         /* FIFO */
846                         /* enable FIFO */
847                         outb(1, dev->iobase + PCL818_FI_ENABLE);
848                         if (mode == 1) {
849                                 devpriv->ai_mode = INT_TYPE_AI1_FIFO;
850                                 /* Pacer */
851                                 outb(0x03, dev->iobase + PCL818_CONTROL);
852                         } else {
853                                 devpriv->ai_mode = INT_TYPE_AI3_FIFO;
854                                 outb(0x02, dev->iobase + PCL818_CONTROL);
855                         }
856                 }
857         }
858
859         start_pacer(dev, mode, divisor1, divisor2);
860
861         dev_dbg(dev->class_dev, "pcl818_ai_cmd_mode() end\n");
862         return 0;
863 }
864
865 /*
866 ==============================================================================
867  Start/stop pacer onboard pacer
868 */
869 static void start_pacer(struct comedi_device *dev, int mode,
870                         unsigned int divisor1, unsigned int divisor2)
871 {
872         outb(0xb4, dev->iobase + PCL818_CTRCTL);
873         outb(0x74, dev->iobase + PCL818_CTRCTL);
874         udelay(1);
875
876         if (mode == 1) {
877                 outb(divisor2 & 0xff, dev->iobase + PCL818_CTR2);
878                 outb((divisor2 >> 8) & 0xff, dev->iobase + PCL818_CTR2);
879                 outb(divisor1 & 0xff, dev->iobase + PCL818_CTR1);
880                 outb((divisor1 >> 8) & 0xff, dev->iobase + PCL818_CTR1);
881         }
882 }
883
884 /*
885 ==============================================================================
886  Check if channel list from user is builded correctly
887  If it's ok, then program scan/gain logic
888 */
889 static int check_channel_list(struct comedi_device *dev,
890                               struct comedi_subdevice *s,
891                               unsigned int *chanlist, unsigned int n_chan)
892 {
893         unsigned int chansegment[16];
894         unsigned int i, nowmustbechan, seglen, segpos;
895
896         /* correct channel and range number check itself comedi/range.c */
897         if (n_chan < 1) {
898                 comedi_error(dev, "range/channel list is empty!");
899                 return 0;
900         }
901
902         if (n_chan > 1) {
903                 /*  first channel is every time ok */
904                 chansegment[0] = chanlist[0];
905                 /*  build part of chanlist */
906                 for (i = 1, seglen = 1; i < n_chan; i++, seglen++) {
907
908                         /* printk("%d. %d * %d\n",i,
909                          * CR_CHAN(it->chanlist[i]),CR_RANGE(it->chanlist[i]));*/
910
911                         /* we detect loop, this must by finish */
912
913                         if (chanlist[0] == chanlist[i])
914                                 break;
915                         nowmustbechan =
916                             (CR_CHAN(chansegment[i - 1]) + 1) % s->n_chan;
917                         if (nowmustbechan != CR_CHAN(chanlist[i])) {    /*  channel list isn't continuous :-( */
918                                 printk
919                                     ("comedi%d: pcl818: channel list must be continuous! chanlist[%i]=%d but must be %d or %d!\n",
920                                      dev->minor, i, CR_CHAN(chanlist[i]),
921                                      nowmustbechan, CR_CHAN(chanlist[0]));
922                                 return 0;
923                         }
924                         /*  well, this is next correct channel in list */
925                         chansegment[i] = chanlist[i];
926                 }
927
928                 /*  check whole chanlist */
929                 for (i = 0, segpos = 0; i < n_chan; i++) {
930                         /* 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])); */
931                         if (chanlist[i] != chansegment[i % seglen]) {
932                                 printk
933                                     ("comedi%d: pcl818: bad channel or range number! chanlist[%i]=%d,%d,%d and not %d,%d,%d!\n",
934                                      dev->minor, i, CR_CHAN(chansegment[i]),
935                                      CR_RANGE(chansegment[i]),
936                                      CR_AREF(chansegment[i]),
937                                      CR_CHAN(chanlist[i % seglen]),
938                                      CR_RANGE(chanlist[i % seglen]),
939                                      CR_AREF(chansegment[i % seglen]));
940                                 return 0;       /*  chan/gain list is strange */
941                         }
942                 }
943         } else {
944                 seglen = 1;
945         }
946         printk("check_channel_list: seglen %d\n", seglen);
947         return seglen;
948 }
949
950 static void setup_channel_list(struct comedi_device *dev,
951                                struct comedi_subdevice *s,
952                                unsigned int *chanlist, unsigned int n_chan,
953                                unsigned int seglen)
954 {
955         struct pcl818_private *devpriv = dev->private;
956         int i;
957
958         devpriv->act_chanlist_len = seglen;
959         devpriv->act_chanlist_pos = 0;
960
961         for (i = 0; i < seglen; i++) {  /*  store range list to card */
962                 devpriv->act_chanlist[i] = CR_CHAN(chanlist[i]);
963                 outb(muxonechan[CR_CHAN(chanlist[i])], dev->iobase + PCL818_MUX);       /* select channel */
964                 outb(CR_RANGE(chanlist[i]), dev->iobase + PCL818_RANGE);        /* select gain */
965         }
966
967         udelay(1);
968
969         /* select channel interval to scan */
970         outb(devpriv->act_chanlist[0] | (devpriv->act_chanlist[seglen -
971                                                                1] << 4),
972              dev->iobase + PCL818_MUX);
973 }
974
975 /*
976 ==============================================================================
977  Check if board is switched to SE (1) or DIFF(0) mode
978 */
979 static int check_single_ended(unsigned int port)
980 {
981         if (inb(port + PCL818_STATUS) & 0x20)
982                 return 1;
983         return 0;
984 }
985
986 /*
987 ==============================================================================
988 */
989 static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
990                       struct comedi_cmd *cmd)
991 {
992         const struct pcl818_board *board = comedi_board(dev);
993         struct pcl818_private *devpriv = dev->private;
994         int err = 0;
995         int tmp, divisor1 = 0, divisor2 = 0;
996
997         /* Step 1 : check if triggers are trivially valid */
998
999         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
1000         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
1001         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
1002         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
1003         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1004
1005         if (err)
1006                 return 1;
1007
1008         /* Step 2a : make sure trigger sources are unique */
1009
1010         err |= cfc_check_trigger_is_unique(cmd->convert_src);
1011         err |= cfc_check_trigger_is_unique(cmd->stop_src);
1012
1013         /* Step 2b : and mutually compatible */
1014
1015         if (err)
1016                 return 2;
1017
1018         /* Step 3: check if arguments are trivially valid */
1019
1020         err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
1021         err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
1022
1023         if (cmd->convert_src == TRIG_TIMER)
1024                 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
1025                                                  board->ns_min);
1026         else    /* TRIG_EXT */
1027                 err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
1028
1029         err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
1030
1031         if (cmd->stop_src == TRIG_COUNT)
1032                 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
1033         else    /* TRIG_NONE */
1034                 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
1035
1036         if (err)
1037                 return 3;
1038
1039         /* step 4: fix up any arguments */
1040
1041         if (cmd->convert_src == TRIG_TIMER) {
1042                 tmp = cmd->convert_arg;
1043                 i8253_cascade_ns_to_timer(devpriv->i8253_osc_base, &divisor1,
1044                                           &divisor2, &cmd->convert_arg,
1045                                           cmd->flags & TRIG_ROUND_MASK);
1046                 if (cmd->convert_arg < board->ns_min)
1047                         cmd->convert_arg = board->ns_min;
1048                 if (tmp != cmd->convert_arg)
1049                         err++;
1050         }
1051
1052         if (err)
1053                 return 4;
1054
1055         /* step 5: complain about special chanlist considerations */
1056
1057         if (cmd->chanlist) {
1058                 if (!check_channel_list(dev, s, cmd->chanlist,
1059                                         cmd->chanlist_len))
1060                         return 5;       /*  incorrect channels list */
1061         }
1062
1063         return 0;
1064 }
1065
1066 /*
1067 ==============================================================================
1068 */
1069 static int ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1070 {
1071         struct pcl818_private *devpriv = dev->private;
1072         struct comedi_cmd *cmd = &s->async->cmd;
1073         int retval;
1074
1075         dev_dbg(dev->class_dev, "pcl818_ai_cmd()\n");
1076         devpriv->ai_n_chan = cmd->chanlist_len;
1077         devpriv->ai_chanlist = cmd->chanlist;
1078         devpriv->ai_flags = cmd->flags;
1079         devpriv->ai_data_len = s->async->prealloc_bufsz;
1080         devpriv->ai_data = s->async->prealloc_buf;
1081         devpriv->ai_timer1 = 0;
1082         devpriv->ai_timer2 = 0;
1083
1084         if (cmd->stop_src == TRIG_COUNT)
1085                 devpriv->ai_scans = cmd->stop_arg;
1086         else
1087                 devpriv->ai_scans = 0;
1088
1089         if (cmd->scan_begin_src == TRIG_FOLLOW) {       /*  mode 1, 3 */
1090                 if (cmd->convert_src == TRIG_TIMER) {   /*  mode 1 */
1091                         devpriv->ai_timer1 = cmd->convert_arg;
1092                         retval = pcl818_ai_cmd_mode(1, dev, s);
1093                         dev_dbg(dev->class_dev, "pcl818_ai_cmd() end\n");
1094                         return retval;
1095                 }
1096                 if (cmd->convert_src == TRIG_EXT) {     /*  mode 3 */
1097                         return pcl818_ai_cmd_mode(3, dev, s);
1098                 }
1099         }
1100
1101         return -1;
1102 }
1103
1104 /*
1105 ==============================================================================
1106  cancel any mode 1-4 AI
1107 */
1108 static int pcl818_ai_cancel(struct comedi_device *dev,
1109                             struct comedi_subdevice *s)
1110 {
1111         struct pcl818_private *devpriv = dev->private;
1112
1113         if (devpriv->irq_blocked > 0) {
1114                 dev_dbg(dev->class_dev, "pcl818_ai_cancel()\n");
1115                 devpriv->irq_was_now_closed = 1;
1116
1117                 switch (devpriv->ai_mode) {
1118                 case INT_TYPE_AI1_DMA:
1119                 case INT_TYPE_AI3_DMA:
1120                         if (devpriv->neverending_ai ||
1121                             (!devpriv->neverending_ai &&
1122                              devpriv->ai_act_scan > 0)) {
1123                                 /* wait for running dma transfer to end, do cleanup in interrupt */
1124                                 goto end;
1125                         }
1126                         disable_dma(devpriv->dma);
1127                 case INT_TYPE_AI1_INT:
1128                 case INT_TYPE_AI3_INT:
1129                 case INT_TYPE_AI1_FIFO:
1130                 case INT_TYPE_AI3_FIFO:
1131 #ifdef PCL818_MODE13_AO
1132                 case INT_TYPE_AO1_INT:
1133                 case INT_TYPE_AO3_INT:
1134 #endif
1135                         outb(inb(dev->iobase + PCL818_CONTROL) & 0x73, dev->iobase + PCL818_CONTROL);   /* Stop A/D */
1136                         udelay(1);
1137                         start_pacer(dev, -1, 0, 0);
1138                         outb(0, dev->iobase + PCL818_AD_LO);
1139                         inb(dev->iobase + PCL818_AD_LO);
1140                         inb(dev->iobase + PCL818_AD_HI);
1141                         outb(0, dev->iobase + PCL818_CLRINT);   /* clear INT request */
1142                         outb(0, dev->iobase + PCL818_CONTROL);  /* Stop A/D */
1143                         if (devpriv->usefifo) { /*  FIFO shutdown */
1144                                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1145                                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1146                                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1147                         }
1148                         devpriv->irq_blocked = 0;
1149                         devpriv->last_int_sub = s;
1150                         devpriv->neverending_ai = 0;
1151                         devpriv->ai_mode = 0;
1152                         devpriv->irq_was_now_closed = 0;
1153                         break;
1154                 }
1155         }
1156
1157 end:
1158         dev_dbg(dev->class_dev, "pcl818_ai_cancel() end\n");
1159         return 0;
1160 }
1161
1162 /*
1163 ==============================================================================
1164  chech for PCL818
1165 */
1166 static int pcl818_check(unsigned long iobase)
1167 {
1168         outb(0x00, iobase + PCL818_MUX);
1169         udelay(1);
1170         if (inb(iobase + PCL818_MUX) != 0x00)
1171                 return 1;       /* there isn't card */
1172         outb(0x55, iobase + PCL818_MUX);
1173         udelay(1);
1174         if (inb(iobase + PCL818_MUX) != 0x55)
1175                 return 1;       /* there isn't card */
1176         outb(0x00, iobase + PCL818_MUX);
1177         udelay(1);
1178         outb(0x18, iobase + PCL818_CONTROL);
1179         udelay(1);
1180         if (inb(iobase + PCL818_CONTROL) != 0x18)
1181                 return 1;       /* there isn't card */
1182         return 0;               /*  ok, card exist */
1183 }
1184
1185 /*
1186 ==============================================================================
1187  reset whole PCL-818 cards
1188 */
1189 static void pcl818_reset(struct comedi_device *dev)
1190 {
1191         const struct pcl818_board *board = comedi_board(dev);
1192         struct pcl818_private *devpriv = dev->private;
1193
1194         if (devpriv->usefifo) { /*  FIFO shutdown */
1195                 outb(0, dev->iobase + PCL818_FI_INTCLR);
1196                 outb(0, dev->iobase + PCL818_FI_FLUSH);
1197                 outb(0, dev->iobase + PCL818_FI_ENABLE);
1198         }
1199         outb(0, dev->iobase + PCL818_DA_LO);    /*  DAC=0V */
1200         outb(0, dev->iobase + PCL818_DA_HI);
1201         udelay(1);
1202         outb(0, dev->iobase + PCL818_DO_HI);    /*  DO=$0000 */
1203         outb(0, dev->iobase + PCL818_DO_LO);
1204         udelay(1);
1205         outb(0, dev->iobase + PCL818_CONTROL);
1206         outb(0, dev->iobase + PCL818_CNTENABLE);
1207         outb(0, dev->iobase + PCL818_MUX);
1208         outb(0, dev->iobase + PCL818_CLRINT);
1209         outb(0xb0, dev->iobase + PCL818_CTRCTL);        /* Stop pacer */
1210         outb(0x70, dev->iobase + PCL818_CTRCTL);
1211         outb(0x30, dev->iobase + PCL818_CTRCTL);
1212         if (board->is_818) {
1213                 outb(0, dev->iobase + PCL818_RANGE);
1214         } else {
1215                 outb(0, dev->iobase + PCL718_DA2_LO);
1216                 outb(0, dev->iobase + PCL718_DA2_HI);
1217         }
1218 }
1219
1220 static int pcl818_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1221 {
1222         const struct pcl818_board *board = comedi_board(dev);
1223         struct pcl818_private *devpriv;
1224         int ret;
1225         unsigned int irq;
1226         int dma;
1227         unsigned long pages;
1228         struct comedi_subdevice *s;
1229
1230         devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1231         if (!devpriv)
1232                 return -ENOMEM;
1233         dev->private = devpriv;
1234
1235         devpriv->io_range = board->io_range;
1236         if ((board->fifo) && (it->options[2] == -1)) {
1237                 /*  we've board with FIFO and we want to use FIFO */
1238                 devpriv->io_range = PCLx1xFIFO_RANGE;
1239                 devpriv->usefifo = 1;
1240         }
1241         ret = comedi_request_region(dev, it->options[0], devpriv->io_range);
1242         if (ret)
1243                 return ret;
1244
1245         if (pcl818_check(dev->iobase)) {
1246                 comedi_error(dev, "I can't detect board. FAIL!\n");
1247                 return -EIO;
1248         }
1249
1250         /* grab our IRQ */
1251         irq = 0;
1252         if (board->IRQbits != 0) {      /* board support IRQ */
1253                 irq = it->options[1];
1254                 if (irq) {      /* we want to use IRQ */
1255                         if (((1 << irq) & board->IRQbits) == 0) {
1256                                 printk
1257                                     (", IRQ %u is out of allowed range, DISABLING IT",
1258                                      irq);
1259                                 irq = 0;        /* Bad IRQ */
1260                         } else {
1261                                 if (request_irq(irq, interrupt_pcl818, 0,
1262                                                 dev->board_name, dev)) {
1263                                         printk
1264                                             (", unable to allocate IRQ %u, DISABLING IT",
1265                                              irq);
1266                                         irq = 0;        /* Can't use IRQ */
1267                                 } else {
1268                                         printk(KERN_DEBUG "irq=%u", irq);
1269                                 }
1270                         }
1271                 }
1272         }
1273
1274         dev->irq = irq;
1275         if (irq)
1276                 devpriv->irq_free = 1;   /* 1=we have allocated irq */
1277         else
1278                 devpriv->irq_free = 0;
1279
1280         devpriv->irq_blocked = 0;       /* number of subdevice which use IRQ */
1281         devpriv->ai_mode = 0;   /* mode of irq */
1282
1283         /* grab our DMA */
1284         dma = 0;
1285         devpriv->dma = dma;
1286         if (!devpriv->irq_free)
1287                 goto no_dma;    /* if we haven't IRQ, we can't use DMA */
1288         if (board->DMAbits != 0) {      /* board support DMA */
1289                 dma = it->options[2];
1290                 if (dma < 1)
1291                         goto no_dma;    /* DMA disabled */
1292                 if (((1 << dma) & board->DMAbits) == 0) {
1293                         printk(KERN_ERR "DMA is out of allowed range, FAIL!\n");
1294                         return -EINVAL; /* Bad DMA */
1295                 }
1296                 ret = request_dma(dma, dev->board_name);
1297                 if (ret)
1298                         return -EBUSY;  /* DMA isn't free */
1299                 devpriv->dma = dma;
1300                 pages = 2;      /* we need 16KB */
1301                 devpriv->dmabuf[0] = __get_dma_pages(GFP_KERNEL, pages);
1302                 if (!devpriv->dmabuf[0])
1303                         /* maybe experiment with try_to_free_pages() will help .... */
1304                         return -EBUSY;  /* no buffer :-( */
1305                 devpriv->dmapages[0] = pages;
1306                 devpriv->hwdmaptr[0] = virt_to_bus((void *)devpriv->dmabuf[0]);
1307                 devpriv->hwdmasize[0] = (1 << pages) * PAGE_SIZE;
1308                 /* printk("%d %d %ld, ",devpriv->dmapages[0],devpriv->hwdmasize[0],PAGE_SIZE); */
1309                 devpriv->dmabuf[1] = __get_dma_pages(GFP_KERNEL, pages);
1310                 if (!devpriv->dmabuf[1])
1311                         return -EBUSY;
1312                 devpriv->dmapages[1] = pages;
1313                 devpriv->hwdmaptr[1] = virt_to_bus((void *)devpriv->dmabuf[1]);
1314                 devpriv->hwdmasize[1] = (1 << pages) * PAGE_SIZE;
1315         }
1316
1317 no_dma:
1318
1319         ret = comedi_alloc_subdevices(dev, 4);
1320         if (ret)
1321                 return ret;
1322
1323         s = &dev->subdevices[0];
1324         if (!board->n_aichan_se) {
1325                 s->type = COMEDI_SUBD_UNUSED;
1326         } else {
1327                 s->type = COMEDI_SUBD_AI;
1328                 devpriv->sub_ai = s;
1329                 s->subdev_flags = SDF_READABLE;
1330                 if (check_single_ended(dev->iobase)) {
1331                         s->n_chan = board->n_aichan_se;
1332                         s->subdev_flags |= SDF_COMMON | SDF_GROUND;
1333                         printk(", %dchans S.E. DAC", s->n_chan);
1334                 } else {
1335                         s->n_chan = board->n_aichan_diff;
1336                         s->subdev_flags |= SDF_DIFF;
1337                         printk(", %dchans DIFF DAC", s->n_chan);
1338                 }
1339                 s->maxdata = board->ai_maxdata;
1340                 s->len_chanlist = s->n_chan;
1341                 s->range_table = board->ai_range_type;
1342                 s->cancel = pcl818_ai_cancel;
1343                 s->insn_read = pcl818_ai_insn_read;
1344                 if (irq) {
1345                         dev->read_subdev = s;
1346                         s->subdev_flags |= SDF_CMD_READ;
1347                         s->do_cmdtest = ai_cmdtest;
1348                         s->do_cmd = ai_cmd;
1349                 }
1350                 if (board->is_818) {
1351                         if ((it->options[4] == 1) || (it->options[4] == 10))
1352                                 s->range_table = &range_pcl818l_h_ai;   /*  secondary range list jumper selectable */
1353                 } else {
1354                         switch (it->options[4]) {
1355                         case 0:
1356                                 s->range_table = &range_bipolar10;
1357                                 break;
1358                         case 1:
1359                                 s->range_table = &range_bipolar5;
1360                                 break;
1361                         case 2:
1362                                 s->range_table = &range_bipolar2_5;
1363                                 break;
1364                         case 3:
1365                                 s->range_table = &range718_bipolar1;
1366                                 break;
1367                         case 4:
1368                                 s->range_table = &range718_bipolar0_5;
1369                                 break;
1370                         case 6:
1371                                 s->range_table = &range_unipolar10;
1372                                 break;
1373                         case 7:
1374                                 s->range_table = &range_unipolar5;
1375                                 break;
1376                         case 8:
1377                                 s->range_table = &range718_unipolar2;
1378                                 break;
1379                         case 9:
1380                                 s->range_table = &range718_unipolar1;
1381                                 break;
1382                         default:
1383                                 s->range_table = &range_unknown;
1384                                 break;
1385                         }
1386                 }
1387         }
1388
1389         s = &dev->subdevices[1];
1390         if (!board->n_aochan) {
1391                 s->type = COMEDI_SUBD_UNUSED;
1392         } else {
1393                 s->type = COMEDI_SUBD_AO;
1394                 s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
1395                 s->n_chan = board->n_aochan;
1396                 s->maxdata = board->ao_maxdata;
1397                 s->len_chanlist = board->n_aochan;
1398                 s->range_table = board->ao_range_type;
1399                 s->insn_read = pcl818_ao_insn_read;
1400                 s->insn_write = pcl818_ao_insn_write;
1401                 if (board->is_818) {
1402                         if ((it->options[4] == 1) || (it->options[4] == 10))
1403                                 s->range_table = &range_unipolar10;
1404                         if (it->options[4] == 2)
1405                                 s->range_table = &range_unknown;
1406                 } else {
1407                         if ((it->options[5] == 1) || (it->options[5] == 10))
1408                                 s->range_table = &range_unipolar10;
1409                         if (it->options[5] == 2)
1410                                 s->range_table = &range_unknown;
1411                 }
1412         }
1413
1414         s = &dev->subdevices[2];
1415         if (!board->n_dichan) {
1416                 s->type = COMEDI_SUBD_UNUSED;
1417         } else {
1418                 s->type = COMEDI_SUBD_DI;
1419                 s->subdev_flags = SDF_READABLE;
1420                 s->n_chan = board->n_dichan;
1421                 s->maxdata = 1;
1422                 s->len_chanlist = board->n_dichan;
1423                 s->range_table = &range_digital;
1424                 s->insn_bits = pcl818_di_insn_bits;
1425         }
1426
1427         s = &dev->subdevices[3];
1428         if (!board->n_dochan) {
1429                 s->type = COMEDI_SUBD_UNUSED;
1430         } else {
1431                 s->type = COMEDI_SUBD_DO;
1432                 s->subdev_flags = SDF_WRITABLE;
1433                 s->n_chan = board->n_dochan;
1434                 s->maxdata = 1;
1435                 s->len_chanlist = board->n_dochan;
1436                 s->range_table = &range_digital;
1437                 s->insn_bits = pcl818_do_insn_bits;
1438         }
1439
1440         /* select 1/10MHz oscilator */
1441         if ((it->options[3] == 0) || (it->options[3] == 10))
1442                 devpriv->i8253_osc_base = 100;
1443         else
1444                 devpriv->i8253_osc_base = 1000;
1445
1446         /* max sampling speed */
1447         devpriv->ns_min = board->ns_min;
1448
1449         if (!board->is_818) {
1450                 if ((it->options[6] == 1) || (it->options[6] == 100))
1451                         devpriv->ns_min = 10000;        /* extended PCL718 to 100kHz DAC */
1452         }
1453
1454         pcl818_reset(dev);
1455
1456         printk("\n");
1457
1458         return 0;
1459 }
1460
1461 static void pcl818_detach(struct comedi_device *dev)
1462 {
1463         struct pcl818_private *devpriv = dev->private;
1464
1465         if (devpriv) {
1466                 pcl818_ai_cancel(dev, devpriv->sub_ai);
1467                 pcl818_reset(dev);
1468                 if (devpriv->dma)
1469                         free_dma(devpriv->dma);
1470                 if (devpriv->dmabuf[0])
1471                         free_pages(devpriv->dmabuf[0], devpriv->dmapages[0]);
1472                 if (devpriv->dmabuf[1])
1473                         free_pages(devpriv->dmabuf[1], devpriv->dmapages[1]);
1474         }
1475         comedi_legacy_detach(dev);
1476 }
1477
1478 static const struct pcl818_board boardtypes[] = {
1479         {"pcl818l", 4, 16, 8, 25000, 1, 16, 16, &range_pcl818l_l_ai,
1480          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1481          0x0a, 0xfff, 0xfff, 0, 1},
1482         {"pcl818h", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1483          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1484          0x0a, 0xfff, 0xfff, 0, 1},
1485         {"pcl818hd", 9, 16, 8, 10000, 1, 16, 16, &range_pcl818h_ai,
1486          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1487          0x0a, 0xfff, 0xfff, 1, 1},
1488         {"pcl818hg", 12, 16, 8, 10000, 1, 16, 16, &range_pcl818hg_ai,
1489          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1490          0x0a, 0xfff, 0xfff, 1, 1},
1491         {"pcl818", 9, 16, 8, 10000, 2, 16, 16, &range_pcl818h_ai,
1492          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1493          0x0a, 0xfff, 0xfff, 0, 1},
1494         {"pcl718", 1, 16, 8, 16000, 2, 16, 16, &range_unipolar5,
1495          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1496          0x0a, 0xfff, 0xfff, 0, 0},
1497         /* pcm3718 */
1498         {"pcm3718", 9, 16, 8, 10000, 0, 16, 16, &range_pcl818h_ai,
1499          &range_unipolar5, PCLx1x_RANGE, 0x00fc,
1500          0x0a, 0xfff, 0xfff, 0, 1 /* XXX ? */ },
1501 };
1502
1503 static struct comedi_driver pcl818_driver = {
1504         .driver_name    = "pcl818",
1505         .module         = THIS_MODULE,
1506         .attach         = pcl818_attach,
1507         .detach         = pcl818_detach,
1508         .board_name     = &boardtypes[0].name,
1509         .num_names      = ARRAY_SIZE(boardtypes),
1510         .offset         = sizeof(struct pcl818_board),
1511 };
1512 module_comedi_driver(pcl818_driver);
1513
1514 MODULE_AUTHOR("Comedi http://www.comedi.org");
1515 MODULE_DESCRIPTION("Comedi low-level driver");
1516 MODULE_LICENSE("GPL");