Merge tag 'dt' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[platform/adaptation/renesas_rcar/renesas_kernel.git] / drivers / staging / comedi / drivers / das800.c
1 /*
2     comedi/drivers/das800.c
3     Driver for Keitley das800 series boards and compatibles
4     Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
5
6     COMEDI - Linux Control and Measurement Device Interface
7     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8
9     This program is free software; you can redistribute it and/or modify
10     it under the terms of the GNU General Public License as published by
11     the Free Software Foundation; either version 2 of the License, or
12     (at your option) any later version.
13
14     This program is distributed in the hope that it will be useful,
15     but WITHOUT ANY WARRANTY; without even the implied warranty of
16     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17     GNU General Public License for more details.
18
19     You should have received a copy of the GNU General Public License
20     along with this program; if not, write to the Free Software
21     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22
23 ************************************************************************
24 */
25 /*
26 Driver: das800
27 Description: Keithley Metrabyte DAS800 (& compatibles)
28 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
29 Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
30   DAS-802 (das-802),
31   [Measurement Computing] CIO-DAS800 (cio-das800),
32   CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
33   CIO-DAS802/16 (cio-das802/16)
34 Status: works, cio-das802/16 untested - email me if you have tested it
35
36 Configuration options:
37   [0] - I/O port base address
38   [1] - IRQ (optional, required for timed or externally triggered conversions)
39
40 Notes:
41         IRQ can be omitted, although the cmd interface will not work without it.
42
43         All entries in the channel/gain list must use the same gain and be
44         consecutive channels counting upwards in channel number (these are
45         hardware limitations.)
46
47         I've never tested the gain setting stuff since I only have a
48         DAS-800 board with fixed gain.
49
50         The cio-das802/16 does not have a fifo-empty status bit!  Therefore
51         only fifo-half-full transfers are possible with this card.
52 */
53 /*
54
55 cmd triggers supported:
56         start_src:      TRIG_NOW | TRIG_EXT
57         scan_begin_src: TRIG_FOLLOW
58         scan_end_src:   TRIG_COUNT
59         convert_src:    TRIG_TIMER | TRIG_EXT
60         stop_src:       TRIG_NONE | TRIG_COUNT
61
62
63 */
64
65 #include <linux/interrupt.h>
66 #include "../comedidev.h"
67
68 #include <linux/ioport.h>
69 #include <linux/delay.h>
70
71 #include "8253.h"
72 #include "comedi_fc.h"
73
74 #define DAS800_SIZE           8
75 #define TIMER_BASE            1000
76 #define N_CHAN_AI             8 /*  number of analog input channels */
77
78 /* Registers for the das800 */
79
80 #define DAS800_LSB            0
81 #define   FIFO_EMPTY            0x1
82 #define   FIFO_OVF              0x2
83 #define DAS800_MSB            1
84 #define DAS800_CONTROL1       2
85 #define   CONTROL1_INTE         0x8
86 #define DAS800_CONV_CONTROL   2
87 #define   ITE                   0x1
88 #define   CASC                  0x2
89 #define   DTEN                  0x4
90 #define   IEOC                  0x8
91 #define   EACS                  0x10
92 #define   CONV_HCEN             0x80
93 #define DAS800_SCAN_LIMITS    2
94 #define DAS800_STATUS         2
95 #define   IRQ                   0x8
96 #define   BUSY                  0x80
97 #define DAS800_GAIN           3
98 #define   CIO_FFOV              0x8     /*  fifo overflow for cio-das802/16 */
99 #define   CIO_ENHF              0x90    /*  interrupt fifo half full for cio-das802/16 */
100 #define   CONTROL1              0x80
101 #define   CONV_CONTROL          0xa0
102 #define   SCAN_LIMITS           0xc0
103 #define   ID                    0xe0
104 #define DAS800_8254           4
105 #define DAS800_STATUS2        7
106 #define   STATUS2_HCEN          0x80
107 #define   STATUS2_INTE          0X20
108 #define DAS800_ID             7
109
110 struct das800_board {
111         const char *name;
112         int ai_speed;
113         const struct comedi_lrange *ai_range;
114         int resolution;
115 };
116
117 /* analog input ranges */
118 static const struct comedi_lrange range_das800_ai = {
119         1,
120         {
121          RANGE(-5, 5),
122          }
123 };
124
125 static const struct comedi_lrange range_das801_ai = {
126         9,
127         {
128          RANGE(-5, 5),
129          RANGE(-10, 10),
130          RANGE(0, 10),
131          RANGE(-0.5, 0.5),
132          RANGE(0, 1),
133          RANGE(-0.05, 0.05),
134          RANGE(0, 0.1),
135          RANGE(-0.01, 0.01),
136          RANGE(0, 0.02),
137          }
138 };
139
140 static const struct comedi_lrange range_cio_das801_ai = {
141         9,
142         {
143          RANGE(-5, 5),
144          RANGE(-10, 10),
145          RANGE(0, 10),
146          RANGE(-0.5, 0.5),
147          RANGE(0, 1),
148          RANGE(-0.05, 0.05),
149          RANGE(0, 0.1),
150          RANGE(-0.005, 0.005),
151          RANGE(0, 0.01),
152          }
153 };
154
155 static const struct comedi_lrange range_das802_ai = {
156         9,
157         {
158          RANGE(-5, 5),
159          RANGE(-10, 10),
160          RANGE(0, 10),
161          RANGE(-2.5, 2.5),
162          RANGE(0, 5),
163          RANGE(-1.25, 1.25),
164          RANGE(0, 2.5),
165          RANGE(-0.625, 0.625),
166          RANGE(0, 1.25),
167          }
168 };
169
170 static const struct comedi_lrange range_das80216_ai = {
171         8,
172         {
173          RANGE(-10, 10),
174          RANGE(0, 10),
175          RANGE(-5, 5),
176          RANGE(0, 5),
177          RANGE(-2.5, 2.5),
178          RANGE(0, 2.5),
179          RANGE(-1.25, 1.25),
180          RANGE(0, 1.25),
181          }
182 };
183
184 enum { das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216 };
185
186 static const struct das800_board das800_boards[] = {
187         {
188          .name = "das-800",
189          .ai_speed = 25000,
190          .ai_range = &range_das800_ai,
191          .resolution = 12,
192          },
193         {
194          .name = "cio-das800",
195          .ai_speed = 20000,
196          .ai_range = &range_das800_ai,
197          .resolution = 12,
198          },
199         {
200          .name = "das-801",
201          .ai_speed = 25000,
202          .ai_range = &range_das801_ai,
203          .resolution = 12,
204          },
205         {
206          .name = "cio-das801",
207          .ai_speed = 20000,
208          .ai_range = &range_cio_das801_ai,
209          .resolution = 12,
210          },
211         {
212          .name = "das-802",
213          .ai_speed = 25000,
214          .ai_range = &range_das802_ai,
215          .resolution = 12,
216          },
217         {
218          .name = "cio-das802",
219          .ai_speed = 20000,
220          .ai_range = &range_das802_ai,
221          .resolution = 12,
222          },
223         {
224          .name = "cio-das802/16",
225          .ai_speed = 10000,
226          .ai_range = &range_das80216_ai,
227          .resolution = 16,
228          },
229 };
230
231 /*
232  * Useful for shorthand access to the particular board structure
233  */
234 #define thisboard ((const struct das800_board *)dev->board_ptr)
235
236 struct das800_private {
237         volatile unsigned int count;    /* number of data points left to be taken */
238         volatile int forever;   /* flag indicating whether we should take data forever */
239         unsigned int divisor1;  /* value to load into board's counter 1 for timed conversions */
240         unsigned int divisor2;  /* value to load into board's counter 2 for timed conversions */
241         volatile int do_bits;   /* digital output bits */
242 };
243
244 #define devpriv ((struct das800_private *)dev->private)
245
246 static int das800_attach(struct comedi_device *dev,
247                          struct comedi_devconfig *it);
248 static void das800_detach(struct comedi_device *dev);
249 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
250
251 static struct comedi_driver driver_das800 = {
252         .driver_name = "das800",
253         .module = THIS_MODULE,
254         .attach = das800_attach,
255         .detach = das800_detach,
256         .num_names = ARRAY_SIZE(das800_boards),
257         .board_name = &das800_boards[0].name,
258         .offset = sizeof(struct das800_board),
259 };
260
261 static irqreturn_t das800_interrupt(int irq, void *d);
262 static void enable_das800(struct comedi_device *dev);
263 static void disable_das800(struct comedi_device *dev);
264 static int das800_ai_do_cmdtest(struct comedi_device *dev,
265                                 struct comedi_subdevice *s,
266                                 struct comedi_cmd *cmd);
267 static int das800_ai_do_cmd(struct comedi_device *dev,
268                             struct comedi_subdevice *s);
269 static int das800_ai_rinsn(struct comedi_device *dev,
270                            struct comedi_subdevice *s, struct comedi_insn *insn,
271                            unsigned int *data);
272 static int das800_di_rbits(struct comedi_device *dev,
273                            struct comedi_subdevice *s, struct comedi_insn *insn,
274                            unsigned int *data);
275 static int das800_do_wbits(struct comedi_device *dev,
276                            struct comedi_subdevice *s, struct comedi_insn *insn,
277                            unsigned int *data);
278 static int das800_probe(struct comedi_device *dev);
279 static int das800_set_frequency(struct comedi_device *dev);
280
281 /* checks and probes das-800 series board type */
282 static int das800_probe(struct comedi_device *dev)
283 {
284         int id_bits;
285         unsigned long irq_flags;
286         int board;
287
288         /*  'comedi spin lock irqsave' disables even rt interrupts, we use them to protect indirect addressing */
289         spin_lock_irqsave(&dev->spinlock, irq_flags);
290         outb(ID, dev->iobase + DAS800_GAIN);    /* select base address + 7 to be ID register */
291         id_bits = inb(dev->iobase + DAS800_ID) & 0x3;   /* get id bits */
292         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
293
294         board = thisboard - das800_boards;
295
296         switch (id_bits) {
297         case 0x0:
298                 if (board == das800) {
299                         dev_dbg(dev->class_dev, "Board model: DAS-800\n");
300                         return board;
301                 }
302                 if (board == ciodas800) {
303                         dev_dbg(dev->class_dev, "Board model: CIO-DAS800\n");
304                         return board;
305                 }
306                 dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n");
307                 return das800;
308                 break;
309         case 0x2:
310                 if (board == das801) {
311                         dev_dbg(dev->class_dev, "Board model: DAS-801\n");
312                         return board;
313                 }
314                 if (board == ciodas801) {
315                         dev_dbg(dev->class_dev, "Board model: CIO-DAS801\n");
316                         return board;
317                 }
318                 dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n");
319                 return das801;
320                 break;
321         case 0x3:
322                 if (board == das802) {
323                         dev_dbg(dev->class_dev, "Board model: DAS-802\n");
324                         return board;
325                 }
326                 if (board == ciodas802) {
327                         dev_dbg(dev->class_dev, "Board model: CIO-DAS802\n");
328                         return board;
329                 }
330                 if (board == ciodas80216) {
331                         dev_dbg(dev->class_dev, "Board model: CIO-DAS802/16\n");
332                         return board;
333                 }
334                 dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n");
335                 return das802;
336                 break;
337         default:
338                 dev_dbg(dev->class_dev,
339                         "Board model: probe returned 0x%x (unknown)\n",
340                         id_bits);
341                 return board;
342                 break;
343         }
344         return -1;
345 }
346
347 /*
348  * A convenient macro that defines init_module() and cleanup_module(),
349  * as necessary.
350  */
351 static int __init driver_das800_init_module(void)
352 {
353         return comedi_driver_register(&driver_das800);
354 }
355
356 static void __exit driver_das800_cleanup_module(void)
357 {
358         comedi_driver_unregister(&driver_das800);
359 }
360
361 module_init(driver_das800_init_module);
362 module_exit(driver_das800_cleanup_module);
363
364 /* interrupt service routine */
365 static irqreturn_t das800_interrupt(int irq, void *d)
366 {
367         short i;                /* loop index */
368         short dataPoint = 0;
369         struct comedi_device *dev = d;
370         struct comedi_subdevice *s = dev->read_subdev;  /* analog input subdevice */
371         struct comedi_async *async;
372         int status;
373         unsigned long irq_flags;
374         static const int max_loops = 128;       /*  half-fifo size for cio-das802/16 */
375         /*  flags */
376         int fifo_empty = 0;
377         int fifo_overflow = 0;
378
379         status = inb(dev->iobase + DAS800_STATUS);
380         /* if interrupt was not generated by board or driver not attached, quit */
381         if (!(status & IRQ))
382                 return IRQ_NONE;
383         if (!(dev->attached))
384                 return IRQ_HANDLED;
385
386         /* wait until here to initialize async, since we will get null dereference
387          * if interrupt occurs before driver is fully attached!
388          */
389         async = s->async;
390
391         /*  if hardware conversions are not enabled, then quit */
392         spin_lock_irqsave(&dev->spinlock, irq_flags);
393         outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select base address + 7 to be STATUS2 register */
394         status = inb(dev->iobase + DAS800_STATUS2) & STATUS2_HCEN;
395         /* don't release spinlock yet since we want to make sure no one else disables hardware conversions */
396         if (status == 0) {
397                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
398                 return IRQ_HANDLED;
399         }
400
401         /* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */
402         for (i = 0; i < max_loops; i++) {
403                 /* read 16 bits from dev->iobase and dev->iobase + 1 */
404                 dataPoint = inb(dev->iobase + DAS800_LSB);
405                 dataPoint += inb(dev->iobase + DAS800_MSB) << 8;
406                 if (thisboard->resolution == 12) {
407                         fifo_empty = dataPoint & FIFO_EMPTY;
408                         fifo_overflow = dataPoint & FIFO_OVF;
409                         if (fifo_overflow)
410                                 break;
411                 } else {
412                         fifo_empty = 0; /*  cio-das802/16 has no fifo empty status bit */
413                 }
414                 if (fifo_empty)
415                         break;
416                 /* strip off extraneous bits for 12 bit cards */
417                 if (thisboard->resolution == 12)
418                         dataPoint = (dataPoint >> 4) & 0xfff;
419                 /* if there are more data points to collect */
420                 if (devpriv->count > 0 || devpriv->forever == 1) {
421                         /* write data point to buffer */
422                         cfc_write_to_buffer(s, dataPoint);
423                         if (devpriv->count > 0)
424                                 devpriv->count--;
425                 }
426         }
427         async->events |= COMEDI_CB_BLOCK;
428         /* check for fifo overflow */
429         if (thisboard->resolution == 12) {
430                 fifo_overflow = dataPoint & FIFO_OVF;
431                 /*  else cio-das802/16 */
432         } else {
433                 fifo_overflow = inb(dev->iobase + DAS800_GAIN) & CIO_FFOV;
434         }
435         if (fifo_overflow) {
436                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
437                 comedi_error(dev, "DAS800 FIFO overflow");
438                 das800_cancel(dev, s);
439                 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
440                 comedi_event(dev, s);
441                 async->events = 0;
442                 return IRQ_HANDLED;
443         }
444         if (devpriv->count > 0 || devpriv->forever == 1) {
445                 /* Re-enable card's interrupt.
446                  * We already have spinlock, so indirect addressing is safe */
447                 outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select dev->iobase + 2 to be control register 1 */
448                 outb(CONTROL1_INTE | devpriv->do_bits,
449                      dev->iobase + DAS800_CONTROL1);
450                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
451                 /* otherwise, stop taking data */
452         } else {
453                 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
454                 disable_das800(dev);    /* disable hardware triggered conversions */
455                 async->events |= COMEDI_CB_EOA;
456         }
457         comedi_event(dev, s);
458         async->events = 0;
459         return IRQ_HANDLED;
460 }
461
462 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
463 {
464         struct comedi_subdevice *s;
465         unsigned long iobase = it->options[0];
466         unsigned int irq = it->options[1];
467         unsigned long irq_flags;
468         int board;
469         int ret;
470
471         dev_info(dev->class_dev, "das800: io 0x%lx\n", iobase);
472         if (irq)
473                 dev_dbg(dev->class_dev, "irq %u\n", irq);
474
475         /* allocate and initialize dev->private */
476         if (alloc_private(dev, sizeof(struct das800_private)) < 0)
477                 return -ENOMEM;
478
479         if (iobase == 0) {
480                 dev_err(dev->class_dev,
481                         "io base address required for das800\n");
482                 return -EINVAL;
483         }
484
485         /* check if io addresses are available */
486         if (!request_region(iobase, DAS800_SIZE, "das800")) {
487                 dev_err(dev->class_dev, "I/O port conflict\n");
488                 return -EIO;
489         }
490         dev->iobase = iobase;
491
492         board = das800_probe(dev);
493         if (board < 0) {
494                 dev_dbg(dev->class_dev, "unable to determine board type\n");
495                 return -ENODEV;
496         }
497         dev->board_ptr = das800_boards + board;
498
499         /* grab our IRQ */
500         if (irq == 1 || irq > 7) {
501                 dev_err(dev->class_dev, "irq out of range\n");
502                 return -EINVAL;
503         }
504         if (irq) {
505                 if (request_irq(irq, das800_interrupt, 0, "das800", dev)) {
506                         dev_err(dev->class_dev, "unable to allocate irq %u\n",
507                                 irq);
508                         return -EINVAL;
509                 }
510         }
511         dev->irq = irq;
512
513         dev->board_name = thisboard->name;
514
515         ret = comedi_alloc_subdevices(dev, 3);
516         if (ret)
517                 return ret;
518
519         /* analog input subdevice */
520         s = &dev->subdevices[0];
521         dev->read_subdev = s;
522         s->type = COMEDI_SUBD_AI;
523         s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ;
524         s->n_chan = 8;
525         s->len_chanlist = 8;
526         s->maxdata = (1 << thisboard->resolution) - 1;
527         s->range_table = thisboard->ai_range;
528         s->do_cmd = das800_ai_do_cmd;
529         s->do_cmdtest = das800_ai_do_cmdtest;
530         s->insn_read = das800_ai_rinsn;
531         s->cancel = das800_cancel;
532
533         /* di */
534         s = &dev->subdevices[1];
535         s->type = COMEDI_SUBD_DI;
536         s->subdev_flags = SDF_READABLE;
537         s->n_chan = 3;
538         s->maxdata = 1;
539         s->range_table = &range_digital;
540         s->insn_bits = das800_di_rbits;
541
542         /* do */
543         s = &dev->subdevices[2];
544         s->type = COMEDI_SUBD_DO;
545         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
546         s->n_chan = 4;
547         s->maxdata = 1;
548         s->range_table = &range_digital;
549         s->insn_bits = das800_do_wbits;
550
551         disable_das800(dev);
552
553         /* initialize digital out channels */
554         spin_lock_irqsave(&dev->spinlock, irq_flags);
555         outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select dev->iobase + 2 to be control register 1 */
556         outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);
557         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
558
559         return 0;
560 };
561
562 static void das800_detach(struct comedi_device *dev)
563 {
564         if (dev->iobase)
565                 release_region(dev->iobase, DAS800_SIZE);
566         if (dev->irq)
567                 free_irq(dev->irq, dev);
568 };
569
570 static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
571 {
572         devpriv->forever = 0;
573         devpriv->count = 0;
574         disable_das800(dev);
575         return 0;
576 }
577
578 /* enable_das800 makes the card start taking hardware triggered conversions */
579 static void enable_das800(struct comedi_device *dev)
580 {
581         unsigned long irq_flags;
582         spin_lock_irqsave(&dev->spinlock, irq_flags);
583         /*  enable fifo-half full interrupts for cio-das802/16 */
584         if (thisboard->resolution == 16)
585                 outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
586         outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);  /* select dev->iobase + 2 to be conversion control register */
587         outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL);     /* enable hardware triggering */
588         outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select dev->iobase + 2 to be control register 1 */
589         outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);  /* enable card's interrupt */
590         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
591 }
592
593 /* disable_das800 stops hardware triggered conversions */
594 static void disable_das800(struct comedi_device *dev)
595 {
596         unsigned long irq_flags;
597         spin_lock_irqsave(&dev->spinlock, irq_flags);
598         outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);  /* select dev->iobase + 2 to be conversion control register */
599         outb(0x0, dev->iobase + DAS800_CONV_CONTROL);   /* disable hardware triggering of conversions */
600         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
601 }
602
603 static int das800_ai_do_cmdtest(struct comedi_device *dev,
604                                 struct comedi_subdevice *s,
605                                 struct comedi_cmd *cmd)
606 {
607         int err = 0;
608         int tmp;
609         int gain, startChan;
610         int i;
611
612         /* Step 1 : check if triggers are trivially valid */
613
614         err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
615         err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_FOLLOW);
616         err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
617         err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
618         err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
619
620         if (err)
621                 return 1;
622
623         /* Step 2a : make sure trigger sources are unique */
624
625         err |= cfc_check_trigger_is_unique(cmd->start_src);
626         err |= cfc_check_trigger_is_unique(cmd->convert_src);
627         err |= cfc_check_trigger_is_unique(cmd->stop_src);
628
629         /* Step 2b : and mutually compatible */
630
631         if (err)
632                 return 2;
633
634         /* step 3: make sure arguments are trivially compatible */
635
636         if (cmd->start_arg != 0) {
637                 cmd->start_arg = 0;
638                 err++;
639         }
640         if (cmd->convert_src == TRIG_TIMER) {
641                 if (cmd->convert_arg < thisboard->ai_speed) {
642                         cmd->convert_arg = thisboard->ai_speed;
643                         err++;
644                 }
645         }
646         if (!cmd->chanlist_len) {
647                 cmd->chanlist_len = 1;
648                 err++;
649         }
650         if (cmd->scan_end_arg != cmd->chanlist_len) {
651                 cmd->scan_end_arg = cmd->chanlist_len;
652                 err++;
653         }
654         if (cmd->stop_src == TRIG_COUNT) {
655                 if (!cmd->stop_arg) {
656                         cmd->stop_arg = 1;
657                         err++;
658                 }
659         } else {                /* TRIG_NONE */
660                 if (cmd->stop_arg != 0) {
661                         cmd->stop_arg = 0;
662                         err++;
663                 }
664         }
665
666         if (err)
667                 return 3;
668
669         /* step 4: fix up any arguments */
670
671         if (cmd->convert_src == TRIG_TIMER) {
672                 tmp = cmd->convert_arg;
673                 /* calculate counter values that give desired timing */
674                 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
675                                                &(devpriv->divisor2),
676                                                &(cmd->convert_arg),
677                                                cmd->flags & TRIG_ROUND_MASK);
678                 if (tmp != cmd->convert_arg)
679                         err++;
680         }
681
682         if (err)
683                 return 4;
684
685         /*  check channel/gain list against card's limitations */
686         if (cmd->chanlist) {
687                 gain = CR_RANGE(cmd->chanlist[0]);
688                 startChan = CR_CHAN(cmd->chanlist[0]);
689                 for (i = 1; i < cmd->chanlist_len; i++) {
690                         if (CR_CHAN(cmd->chanlist[i]) !=
691                             (startChan + i) % N_CHAN_AI) {
692                                 comedi_error(dev,
693                                              "entries in chanlist must be consecutive channels, counting upwards\n");
694                                 err++;
695                         }
696                         if (CR_RANGE(cmd->chanlist[i]) != gain) {
697                                 comedi_error(dev,
698                                              "entries in chanlist must all have the same gain\n");
699                                 err++;
700                         }
701                 }
702         }
703
704         if (err)
705                 return 5;
706
707         return 0;
708 }
709
710 static int das800_ai_do_cmd(struct comedi_device *dev,
711                             struct comedi_subdevice *s)
712 {
713         int startChan, endChan, scan, gain;
714         int conv_bits;
715         unsigned long irq_flags;
716         struct comedi_async *async = s->async;
717
718         if (!dev->irq) {
719                 comedi_error(dev,
720                              "no irq assigned for das-800, cannot do hardware conversions");
721                 return -1;
722         }
723
724         disable_das800(dev);
725
726         /* set channel scan limits */
727         startChan = CR_CHAN(async->cmd.chanlist[0]);
728         endChan = (startChan + async->cmd.chanlist_len - 1) % 8;
729         scan = (endChan << 3) | startChan;
730
731         spin_lock_irqsave(&dev->spinlock, irq_flags);
732         outb(SCAN_LIMITS, dev->iobase + DAS800_GAIN);   /* select base address + 2 to be scan limits register */
733         outb(scan, dev->iobase + DAS800_SCAN_LIMITS);   /* set scan limits */
734         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
735
736         /* set gain */
737         gain = CR_RANGE(async->cmd.chanlist[0]);
738         if (thisboard->resolution == 12 && gain > 0)
739                 gain += 0x7;
740         gain &= 0xf;
741         outb(gain, dev->iobase + DAS800_GAIN);
742
743         switch (async->cmd.stop_src) {
744         case TRIG_COUNT:
745                 devpriv->count = async->cmd.stop_arg * async->cmd.chanlist_len;
746                 devpriv->forever = 0;
747                 break;
748         case TRIG_NONE:
749                 devpriv->forever = 1;
750                 devpriv->count = 0;
751                 break;
752         default:
753                 break;
754         }
755
756         /* enable auto channel scan, send interrupts on end of conversion
757          * and set clock source to internal or external
758          */
759         conv_bits = 0;
760         conv_bits |= EACS | IEOC;
761         if (async->cmd.start_src == TRIG_EXT)
762                 conv_bits |= DTEN;
763         switch (async->cmd.convert_src) {
764         case TRIG_TIMER:
765                 conv_bits |= CASC | ITE;
766                 /* set conversion frequency */
767                 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
768                                                &(devpriv->divisor2),
769                                                &(async->cmd.convert_arg),
770                                                async->cmd.
771                                                flags & TRIG_ROUND_MASK);
772                 if (das800_set_frequency(dev) < 0) {
773                         comedi_error(dev, "Error setting up counters");
774                         return -1;
775                 }
776                 break;
777         case TRIG_EXT:
778                 break;
779         default:
780                 break;
781         }
782
783         spin_lock_irqsave(&dev->spinlock, irq_flags);
784         outb(CONV_CONTROL, dev->iobase + DAS800_GAIN);  /* select dev->iobase + 2 to be conversion control register */
785         outb(conv_bits, dev->iobase + DAS800_CONV_CONTROL);
786         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
787         async->events = 0;
788         enable_das800(dev);
789         return 0;
790 }
791
792 static int das800_ai_rinsn(struct comedi_device *dev,
793                            struct comedi_subdevice *s, struct comedi_insn *insn,
794                            unsigned int *data)
795 {
796         int i, n;
797         int chan;
798         int range;
799         int lsb, msb;
800         int timeout = 1000;
801         unsigned long irq_flags;
802
803         disable_das800(dev);    /* disable hardware conversions (enables software conversions) */
804
805         /* set multiplexer */
806         chan = CR_CHAN(insn->chanspec);
807
808         spin_lock_irqsave(&dev->spinlock, irq_flags);
809         outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select dev->iobase + 2 to be control register 1 */
810         outb(chan | devpriv->do_bits, dev->iobase + DAS800_CONTROL1);
811         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
812
813         /* set gain / range */
814         range = CR_RANGE(insn->chanspec);
815         if (thisboard->resolution == 12 && range)
816                 range += 0x7;
817         range &= 0xf;
818         outb(range, dev->iobase + DAS800_GAIN);
819
820         udelay(5);
821
822         for (n = 0; n < insn->n; n++) {
823                 /* trigger conversion */
824                 outb_p(0, dev->iobase + DAS800_MSB);
825
826                 for (i = 0; i < timeout; i++) {
827                         if (!(inb(dev->iobase + DAS800_STATUS) & BUSY))
828                                 break;
829                 }
830                 if (i == timeout) {
831                         comedi_error(dev, "timeout");
832                         return -ETIME;
833                 }
834                 lsb = inb(dev->iobase + DAS800_LSB);
835                 msb = inb(dev->iobase + DAS800_MSB);
836                 if (thisboard->resolution == 12) {
837                         data[n] = (lsb >> 4) & 0xff;
838                         data[n] |= (msb << 4);
839                 } else {
840                         data[n] = (msb << 8) | lsb;
841                 }
842         }
843
844         return n;
845 }
846
847 static int das800_di_rbits(struct comedi_device *dev,
848                            struct comedi_subdevice *s, struct comedi_insn *insn,
849                            unsigned int *data)
850 {
851         unsigned int bits;
852
853         bits = inb(dev->iobase + DAS800_STATUS) >> 4;
854         bits &= 0x7;
855         data[1] = bits;
856         data[0] = 0;
857
858         return insn->n;
859 }
860
861 static int das800_do_wbits(struct comedi_device *dev,
862                            struct comedi_subdevice *s, struct comedi_insn *insn,
863                            unsigned int *data)
864 {
865         int wbits;
866         unsigned long irq_flags;
867
868         /*  only set bits that have been masked */
869         data[0] &= 0xf;
870         wbits = devpriv->do_bits >> 4;
871         wbits &= ~data[0];
872         wbits |= data[0] & data[1];
873         devpriv->do_bits = wbits << 4;
874
875         spin_lock_irqsave(&dev->spinlock, irq_flags);
876         outb(CONTROL1, dev->iobase + DAS800_GAIN);      /* select dev->iobase + 2 to be control register 1 */
877         outb(devpriv->do_bits | CONTROL1_INTE, dev->iobase + DAS800_CONTROL1);
878         spin_unlock_irqrestore(&dev->spinlock, irq_flags);
879
880         data[1] = wbits;
881
882         return insn->n;
883 }
884
885 /* loads counters with divisor1, divisor2 from private structure */
886 static int das800_set_frequency(struct comedi_device *dev)
887 {
888         int err = 0;
889
890         if (i8254_load(dev->iobase + DAS800_8254, 0, 1, devpriv->divisor1, 2))
891                 err++;
892         if (i8254_load(dev->iobase + DAS800_8254, 0, 2, devpriv->divisor2, 2))
893                 err++;
894         if (err)
895                 return -1;
896
897         return 0;
898 }
899
900 MODULE_AUTHOR("Comedi http://www.comedi.org");
901 MODULE_DESCRIPTION("Comedi low-level driver");
902 MODULE_LICENSE("GPL");