Linux-libre 4.19.123-gnu
[librecmc/linux-libre.git] / drivers / staging / comedi / drivers / das16.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * das16.c
4  * DAS16 driver
5  *
6  * COMEDI - Linux Control and Measurement Device Interface
7  * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8  * Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
9  * Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10  */
11
12 /*
13  * Driver: das16
14  * Description: DAS16 compatible boards
15  * Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
16  * Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
17  *   DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
18  *   DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
19  *   DAS-1602 (das-1602),
20  *   [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
21  *   PC104-DAS16JR/16 (pc104-das16jr/16), CIO-DAS16 (cio-das16),
22  *   CIO-DAS16F (cio-das16/f), CIO-DAS16/JR (cio-das16/jr),
23  *   CIO-DAS16JR/16 (cio-das16jr/16), CIO-DAS1401/12 (cio-das1401/12),
24  *   CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
25  *   CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
26  *   CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
27  * Status: works
28  * Updated: 2003-10-12
29  *
30  * A rewrite of the das16 and das1600 drivers.
31  *
32  * Options:
33  *      [0] - base io address
34  *      [1] - irq (does nothing, irq is not used anymore)
35  *      [2] - dma channel (optional, required for comedi_command support)
36  *      [3] - master clock speed in MHz (optional, 1 or 10, ignored if
37  *              board can probe clock, defaults to 1)
38  *      [4] - analog input range lowest voltage in microvolts (optional,
39  *              only useful if your board does not have software
40  *              programmable gain)
41  *      [5] - analog input range highest voltage in microvolts (optional,
42  *              only useful if board does not have software programmable
43  *              gain)
44  *      [6] - analog output range lowest voltage in microvolts (optional)
45  *      [7] - analog output range highest voltage in microvolts (optional)
46  *
47  * Passing a zero for an option is the same as leaving it unspecified.
48  */
49
50 /*
51  * Testing and debugging help provided by Daniel Koch.
52  *
53  * Keithley Manuals:
54  *      2309.PDF (das16)
55  *      4919.PDF (das1400, 1600)
56  *      4922.PDF (das-1400)
57  *      4923.PDF (das1200, 1400, 1600)
58  *
59  * Computer boards manuals also available from their website
60  * www.measurementcomputing.com
61  */
62
63 #include <linux/module.h>
64 #include <linux/slab.h>
65 #include <linux/interrupt.h>
66
67 #include "../comedidev.h"
68
69 #include "comedi_isadma.h"
70 #include "comedi_8254.h"
71 #include "8255.h"
72
73 #define DAS16_DMA_SIZE 0xff00   /*  size in bytes of allocated dma buffer */
74
75 /*
76  * Register I/O map
77  */
78 #define DAS16_TRIG_REG                  0x00
79 #define DAS16_AI_LSB_REG                0x00
80 #define DAS16_AI_MSB_REG                0x01
81 #define DAS16_MUX_REG                   0x02
82 #define DAS16_DIO_REG                   0x03
83 #define DAS16_AO_LSB_REG(x)             ((x) ? 0x06 : 0x04)
84 #define DAS16_AO_MSB_REG(x)             ((x) ? 0x07 : 0x05)
85 #define DAS16_STATUS_REG                0x08
86 #define DAS16_STATUS_BUSY               BIT(7)
87 #define DAS16_STATUS_UNIPOLAR           BIT(6)
88 #define DAS16_STATUS_MUXBIT             BIT(5)
89 #define DAS16_STATUS_INT                BIT(4)
90 #define DAS16_CTRL_REG                  0x09
91 #define DAS16_CTRL_INTE                 BIT(7)
92 #define DAS16_CTRL_IRQ(x)               (((x) & 0x7) << 4)
93 #define DAS16_CTRL_DMAE                 BIT(2)
94 #define DAS16_CTRL_PACING_MASK          (3 << 0)
95 #define DAS16_CTRL_INT_PACER            (3 << 0)
96 #define DAS16_CTRL_EXT_PACER            (2 << 0)
97 #define DAS16_CTRL_SOFT_PACER           (0 << 0)
98 #define DAS16_PACER_REG                 0x0a
99 #define DAS16_PACER_BURST_LEN(x)        (((x) & 0xf) << 4)
100 #define DAS16_PACER_CTR0                BIT(1)
101 #define DAS16_PACER_TRIG0               BIT(0)
102 #define DAS16_GAIN_REG                  0x0b
103 #define DAS16_TIMER_BASE_REG            0x0c    /* to 0x0f */
104
105 #define DAS1600_CONV_REG                0x404
106 #define DAS1600_CONV_DISABLE            BIT(6)
107 #define DAS1600_BURST_REG               0x405
108 #define DAS1600_BURST_VAL               BIT(6)
109 #define DAS1600_ENABLE_REG              0x406
110 #define DAS1600_ENABLE_VAL              BIT(6)
111 #define DAS1600_STATUS_REG              0x407
112 #define DAS1600_STATUS_BME              BIT(6)
113 #define DAS1600_STATUS_ME               BIT(5)
114 #define DAS1600_STATUS_CD               BIT(4)
115 #define DAS1600_STATUS_WS               BIT(1)
116 #define DAS1600_STATUS_CLK_10MHZ        BIT(0)
117
118 static const struct comedi_lrange range_das1x01_bip = {
119         4, {
120                 BIP_RANGE(10),
121                 BIP_RANGE(1),
122                 BIP_RANGE(0.1),
123                 BIP_RANGE(0.01)
124         }
125 };
126
127 static const struct comedi_lrange range_das1x01_unip = {
128         4, {
129                 UNI_RANGE(10),
130                 UNI_RANGE(1),
131                 UNI_RANGE(0.1),
132                 UNI_RANGE(0.01)
133         }
134 };
135
136 static const struct comedi_lrange range_das1x02_bip = {
137         4, {
138                 BIP_RANGE(10),
139                 BIP_RANGE(5),
140                 BIP_RANGE(2.5),
141                 BIP_RANGE(1.25)
142         }
143 };
144
145 static const struct comedi_lrange range_das1x02_unip = {
146         4, {
147                 UNI_RANGE(10),
148                 UNI_RANGE(5),
149                 UNI_RANGE(2.5),
150                 UNI_RANGE(1.25)
151         }
152 };
153
154 static const struct comedi_lrange range_das16jr = {
155         9, {
156                 BIP_RANGE(10),
157                 BIP_RANGE(5),
158                 BIP_RANGE(2.5),
159                 BIP_RANGE(1.25),
160                 BIP_RANGE(0.625),
161                 UNI_RANGE(10),
162                 UNI_RANGE(5),
163                 UNI_RANGE(2.5),
164                 UNI_RANGE(1.25)
165         }
166 };
167
168 static const struct comedi_lrange range_das16jr_16 = {
169         8, {
170                 BIP_RANGE(10),
171                 BIP_RANGE(5),
172                 BIP_RANGE(2.5),
173                 BIP_RANGE(1.25),
174                 UNI_RANGE(10),
175                 UNI_RANGE(5),
176                 UNI_RANGE(2.5),
177                 UNI_RANGE(1.25)
178         }
179 };
180
181 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
182 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
183 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
184
185 enum {
186         das16_pg_none = 0,
187         das16_pg_16jr,
188         das16_pg_16jr_16,
189         das16_pg_1601,
190         das16_pg_1602,
191 };
192
193 static const int *const das16_gainlists[] = {
194         NULL,
195         das16jr_gainlist,
196         das16jr_16_gainlist,
197         das1600_gainlist,
198         das1600_gainlist,
199 };
200
201 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
202         &range_unknown,
203         &range_das16jr,
204         &range_das16jr_16,
205         &range_das1x01_unip,
206         &range_das1x02_unip,
207 };
208
209 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
210         &range_unknown,
211         &range_das16jr,
212         &range_das16jr_16,
213         &range_das1x01_bip,
214         &range_das1x02_bip,
215 };
216
217 struct das16_board {
218         const char *name;
219         unsigned int ai_maxdata;
220         unsigned int ai_speed;  /*  max conversion speed in nanosec */
221         unsigned int ai_pg;
222         unsigned int has_ao:1;
223         unsigned int has_8255:1;
224
225         unsigned int i8255_offset;
226
227         unsigned int size;
228         unsigned int id;
229 };
230
231 static const struct das16_board das16_boards[] = {
232         {
233                 .name           = "das-16",
234                 .ai_maxdata     = 0x0fff,
235                 .ai_speed       = 15000,
236                 .ai_pg          = das16_pg_none,
237                 .has_ao         = 1,
238                 .has_8255       = 1,
239                 .i8255_offset   = 0x10,
240                 .size           = 0x14,
241                 .id             = 0x00,
242         }, {
243                 .name           = "das-16g",
244                 .ai_maxdata     = 0x0fff,
245                 .ai_speed       = 15000,
246                 .ai_pg          = das16_pg_none,
247                 .has_ao         = 1,
248                 .has_8255       = 1,
249                 .i8255_offset   = 0x10,
250                 .size           = 0x14,
251                 .id             = 0x00,
252         }, {
253                 .name           = "das-16f",
254                 .ai_maxdata     = 0x0fff,
255                 .ai_speed       = 8500,
256                 .ai_pg          = das16_pg_none,
257                 .has_ao         = 1,
258                 .has_8255       = 1,
259                 .i8255_offset   = 0x10,
260                 .size           = 0x14,
261                 .id             = 0x00,
262         }, {
263                 .name           = "cio-das16",
264                 .ai_maxdata     = 0x0fff,
265                 .ai_speed       = 20000,
266                 .ai_pg          = das16_pg_none,
267                 .has_ao         = 1,
268                 .has_8255       = 1,
269                 .i8255_offset   = 0x10,
270                 .size           = 0x14,
271                 .id             = 0x80,
272         }, {
273                 .name           = "cio-das16/f",
274                 .ai_maxdata     = 0x0fff,
275                 .ai_speed       = 10000,
276                 .ai_pg          = das16_pg_none,
277                 .has_ao         = 1,
278                 .has_8255       = 1,
279                 .i8255_offset   = 0x10,
280                 .size           = 0x14,
281                 .id             = 0x80,
282         }, {
283                 .name           = "cio-das16/jr",
284                 .ai_maxdata     = 0x0fff,
285                 .ai_speed       = 7692,
286                 .ai_pg          = das16_pg_16jr,
287                 .size           = 0x10,
288                 .id             = 0x00,
289         }, {
290                 .name           = "pc104-das16jr",
291                 .ai_maxdata     = 0x0fff,
292                 .ai_speed       = 3300,
293                 .ai_pg          = das16_pg_16jr,
294                 .size           = 0x10,
295                 .id             = 0x00,
296         }, {
297                 .name           = "cio-das16jr/16",
298                 .ai_maxdata     = 0xffff,
299                 .ai_speed       = 10000,
300                 .ai_pg          = das16_pg_16jr_16,
301                 .size           = 0x10,
302                 .id             = 0x00,
303         }, {
304                 .name           = "pc104-das16jr/16",
305                 .ai_maxdata     = 0xffff,
306                 .ai_speed       = 10000,
307                 .ai_pg          = das16_pg_16jr_16,
308                 .size           = 0x10,
309                 .id             = 0x00,
310         }, {
311                 .name           = "das-1201",
312                 .ai_maxdata     = 0x0fff,
313                 .ai_speed       = 20000,
314                 .ai_pg          = das16_pg_none,
315                 .has_8255       = 1,
316                 .i8255_offset   = 0x400,
317                 .size           = 0x408,
318                 .id             = 0x20,
319         }, {
320                 .name           = "das-1202",
321                 .ai_maxdata     = 0x0fff,
322                 .ai_speed       = 10000,
323                 .ai_pg          = das16_pg_none,
324                 .has_8255       = 1,
325                 .i8255_offset   = 0x400,
326                 .size           = 0x408,
327                 .id             = 0x20,
328         }, {
329                 .name           = "das-1401",
330                 .ai_maxdata     = 0x0fff,
331                 .ai_speed       = 10000,
332                 .ai_pg          = das16_pg_1601,
333                 .size           = 0x408,
334                 .id             = 0xc0,
335         }, {
336                 .name           = "das-1402",
337                 .ai_maxdata     = 0x0fff,
338                 .ai_speed       = 10000,
339                 .ai_pg          = das16_pg_1602,
340                 .size           = 0x408,
341                 .id             = 0xc0,
342         }, {
343                 .name           = "das-1601",
344                 .ai_maxdata     = 0x0fff,
345                 .ai_speed       = 10000,
346                 .ai_pg          = das16_pg_1601,
347                 .has_ao         = 1,
348                 .has_8255       = 1,
349                 .i8255_offset   = 0x400,
350                 .size           = 0x408,
351                 .id             = 0xc0,
352         }, {
353                 .name           = "das-1602",
354                 .ai_maxdata     = 0x0fff,
355                 .ai_speed       = 10000,
356                 .ai_pg          = das16_pg_1602,
357                 .has_ao         = 1,
358                 .has_8255       = 1,
359                 .i8255_offset   = 0x400,
360                 .size           = 0x408,
361                 .id             = 0xc0,
362         }, {
363                 .name           = "cio-das1401/12",
364                 .ai_maxdata     = 0x0fff,
365                 .ai_speed       = 6250,
366                 .ai_pg          = das16_pg_1601,
367                 .size           = 0x408,
368                 .id             = 0xc0,
369         }, {
370                 .name           = "cio-das1402/12",
371                 .ai_maxdata     = 0x0fff,
372                 .ai_speed       = 6250,
373                 .ai_pg          = das16_pg_1602,
374                 .size           = 0x408,
375                 .id             = 0xc0,
376         }, {
377                 .name           = "cio-das1402/16",
378                 .ai_maxdata     = 0xffff,
379                 .ai_speed       = 10000,
380                 .ai_pg          = das16_pg_1602,
381                 .size           = 0x408,
382                 .id             = 0xc0,
383         }, {
384                 .name           = "cio-das1601/12",
385                 .ai_maxdata     = 0x0fff,
386                 .ai_speed       = 6250,
387                 .ai_pg          = das16_pg_1601,
388                 .has_ao         = 1,
389                 .has_8255       = 1,
390                 .i8255_offset   = 0x400,
391                 .size           = 0x408,
392                 .id             = 0xc0,
393         }, {
394                 .name           = "cio-das1602/12",
395                 .ai_maxdata     = 0x0fff,
396                 .ai_speed       = 10000,
397                 .ai_pg          = das16_pg_1602,
398                 .has_ao         = 1,
399                 .has_8255       = 1,
400                 .i8255_offset   = 0x400,
401                 .size           = 0x408,
402                 .id             = 0xc0,
403         }, {
404                 .name           = "cio-das1602/16",
405                 .ai_maxdata     = 0xffff,
406                 .ai_speed       = 10000,
407                 .ai_pg          = das16_pg_1602,
408                 .has_ao         = 1,
409                 .has_8255       = 1,
410                 .i8255_offset   = 0x400,
411                 .size           = 0x408,
412                 .id             = 0xc0,
413         }, {
414                 .name           = "cio-das16/330",
415                 .ai_maxdata     = 0x0fff,
416                 .ai_speed       = 3030,
417                 .ai_pg          = das16_pg_16jr,
418                 .size           = 0x14,
419                 .id             = 0xf0,
420         },
421 };
422
423 /*
424  * Period for timer interrupt in jiffies.  It's a function
425  * to deal with possibility of dynamic HZ patches
426  */
427 static inline int timer_period(void)
428 {
429         return HZ / 20;
430 }
431
432 struct das16_private_struct {
433         struct comedi_isadma    *dma;
434         struct comedi_device    *dev;
435         unsigned int            clockbase;
436         unsigned int            ctrl_reg;
437         unsigned int            divisor1;
438         unsigned int            divisor2;
439         struct timer_list       timer;
440         unsigned long           extra_iobase;
441         unsigned int            can_burst:1;
442         unsigned int            timer_running:1;
443 };
444
445 static void das16_ai_setup_dma(struct comedi_device *dev,
446                                struct comedi_subdevice *s,
447                                unsigned int unread_samples)
448 {
449         struct das16_private_struct *devpriv = dev->private;
450         struct comedi_isadma *dma = devpriv->dma;
451         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
452         unsigned int max_samples = comedi_bytes_to_samples(s, desc->maxsize);
453         unsigned int nsamples;
454
455         /*
456          * Determine dma size based on the buffer size plus the number of
457          * unread samples and the number of samples remaining in the command.
458          */
459         nsamples = comedi_nsamples_left(s, max_samples + unread_samples);
460         if (nsamples > unread_samples) {
461                 nsamples -= unread_samples;
462                 desc->size = comedi_samples_to_bytes(s, nsamples);
463                 comedi_isadma_program(desc);
464         }
465 }
466
467 static void das16_interrupt(struct comedi_device *dev)
468 {
469         struct das16_private_struct *devpriv = dev->private;
470         struct comedi_subdevice *s = dev->read_subdev;
471         struct comedi_async *async = s->async;
472         struct comedi_cmd *cmd = &async->cmd;
473         struct comedi_isadma *dma = devpriv->dma;
474         struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
475         unsigned long spin_flags;
476         unsigned int residue;
477         unsigned int nbytes;
478         unsigned int nsamples;
479
480         spin_lock_irqsave(&dev->spinlock, spin_flags);
481         if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
482                 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
483                 return;
484         }
485
486         /*
487          * The pc104-das16jr (at least) has problems if the dma
488          * transfer is interrupted in the middle of transferring
489          * a 16 bit sample.
490          */
491         residue = comedi_isadma_disable_on_sample(desc->chan,
492                                                   comedi_bytes_per_sample(s));
493
494         /* figure out how many samples to read */
495         if (residue > desc->size) {
496                 dev_err(dev->class_dev, "residue > transfer size!\n");
497                 async->events |= COMEDI_CB_ERROR;
498                 nbytes = 0;
499         } else {
500                 nbytes = desc->size - residue;
501         }
502         nsamples = comedi_bytes_to_samples(s, nbytes);
503
504         /* restart DMA if more samples are needed */
505         if (nsamples) {
506                 dma->cur_dma = 1 - dma->cur_dma;
507                 das16_ai_setup_dma(dev, s, nsamples);
508         }
509
510         spin_unlock_irqrestore(&dev->spinlock, spin_flags);
511
512         comedi_buf_write_samples(s, desc->virt_addr, nsamples);
513
514         if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
515                 async->events |= COMEDI_CB_EOA;
516
517         comedi_handle_events(dev, s);
518 }
519
520 static void das16_timer_interrupt(struct timer_list *t)
521 {
522         struct das16_private_struct *devpriv = from_timer(devpriv, t, timer);
523         struct comedi_device *dev = devpriv->dev;
524         unsigned long flags;
525
526         das16_interrupt(dev);
527
528         spin_lock_irqsave(&dev->spinlock, flags);
529         if (devpriv->timer_running)
530                 mod_timer(&devpriv->timer, jiffies + timer_period());
531         spin_unlock_irqrestore(&dev->spinlock, flags);
532 }
533
534 static void das16_ai_set_mux_range(struct comedi_device *dev,
535                                    unsigned int first_chan,
536                                    unsigned int last_chan,
537                                    unsigned int range)
538 {
539         const struct das16_board *board = dev->board_ptr;
540
541         /* set multiplexer */
542         outb(first_chan | (last_chan << 4), dev->iobase + DAS16_MUX_REG);
543
544         /* some boards do not have programmable gain */
545         if (board->ai_pg == das16_pg_none)
546                 return;
547
548         /*
549          * Set gain (this is also burst rate register but according to
550          * computer boards manual, burst rate does nothing, even on
551          * keithley cards).
552          */
553         outb((das16_gainlists[board->ai_pg])[range],
554              dev->iobase + DAS16_GAIN_REG);
555 }
556
557 static int das16_ai_check_chanlist(struct comedi_device *dev,
558                                    struct comedi_subdevice *s,
559                                    struct comedi_cmd *cmd)
560 {
561         unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
562         unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
563         int i;
564
565         for (i = 1; i < cmd->chanlist_len; i++) {
566                 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
567                 unsigned int range = CR_RANGE(cmd->chanlist[i]);
568
569                 if (chan != ((chan0 + i) % s->n_chan)) {
570                         dev_dbg(dev->class_dev,
571                                 "entries in chanlist must be consecutive channels, counting upwards\n");
572                         return -EINVAL;
573                 }
574
575                 if (range != range0) {
576                         dev_dbg(dev->class_dev,
577                                 "entries in chanlist must all have the same gain\n");
578                         return -EINVAL;
579                 }
580         }
581
582         return 0;
583 }
584
585 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
586                           struct comedi_cmd *cmd)
587 {
588         const struct das16_board *board = dev->board_ptr;
589         struct das16_private_struct *devpriv = dev->private;
590         int err = 0;
591         unsigned int trig_mask;
592         unsigned int arg;
593
594         /* Step 1 : check if triggers are trivially valid */
595
596         err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
597
598         trig_mask = TRIG_FOLLOW;
599         if (devpriv->can_burst)
600                 trig_mask |= TRIG_TIMER | TRIG_EXT;
601         err |= comedi_check_trigger_src(&cmd->scan_begin_src, trig_mask);
602
603         trig_mask = TRIG_TIMER | TRIG_EXT;
604         if (devpriv->can_burst)
605                 trig_mask |= TRIG_NOW;
606         err |= comedi_check_trigger_src(&cmd->convert_src, trig_mask);
607
608         err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
609         err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
610
611         if (err)
612                 return 1;
613
614         /* Step 2a : make sure trigger sources are unique */
615
616         err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
617         err |= comedi_check_trigger_is_unique(cmd->convert_src);
618         err |= comedi_check_trigger_is_unique(cmd->stop_src);
619
620         /* Step 2b : and mutually compatible */
621
622         /*  make sure scan_begin_src and convert_src don't conflict */
623         if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
624                 err |= -EINVAL;
625         if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
626                 err |= -EINVAL;
627
628         if (err)
629                 return 2;
630
631         /* Step 3: check if arguments are trivially valid */
632
633         err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
634
635         if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
636                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
637
638         err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
639                                            cmd->chanlist_len);
640
641         /* check against maximum frequency */
642         if (cmd->scan_begin_src == TRIG_TIMER) {
643                 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
644                                                     board->ai_speed *
645                                                     cmd->chanlist_len);
646         }
647
648         if (cmd->convert_src == TRIG_TIMER) {
649                 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
650                                                     board->ai_speed);
651         }
652
653         if (cmd->stop_src == TRIG_COUNT)
654                 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
655         else    /* TRIG_NONE */
656                 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
657
658         if (err)
659                 return 3;
660
661         /*  step 4: fix up arguments */
662         if (cmd->scan_begin_src == TRIG_TIMER) {
663                 arg = cmd->scan_begin_arg;
664                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
665                 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
666         }
667         if (cmd->convert_src == TRIG_TIMER) {
668                 arg = cmd->convert_arg;
669                 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
670                 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
671         }
672         if (err)
673                 return 4;
674
675         /* Step 5: check channel list if it exists */
676         if (cmd->chanlist && cmd->chanlist_len > 0)
677                 err |= das16_ai_check_chanlist(dev, s, cmd);
678
679         if (err)
680                 return 5;
681
682         return 0;
683 }
684
685 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
686                                     unsigned int flags)
687 {
688         comedi_8254_cascade_ns_to_timer(dev->pacer, &ns, flags);
689         comedi_8254_update_divisors(dev->pacer);
690         comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
691
692         return ns;
693 }
694
695 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
696 {
697         struct das16_private_struct *devpriv = dev->private;
698         struct comedi_isadma *dma = devpriv->dma;
699         struct comedi_async *async = s->async;
700         struct comedi_cmd *cmd = &async->cmd;
701         unsigned int first_chan = CR_CHAN(cmd->chanlist[0]);
702         unsigned int last_chan = CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]);
703         unsigned int range = CR_RANGE(cmd->chanlist[0]);
704         unsigned int byte;
705         unsigned long flags;
706
707         if (cmd->flags & CMDF_PRIORITY) {
708                 dev_err(dev->class_dev,
709                         "isa dma transfers cannot be performed with CMDF_PRIORITY, aborting\n");
710                 return -1;
711         }
712
713         if (devpriv->can_burst)
714                 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
715
716         /* set mux and range for chanlist scan */
717         das16_ai_set_mux_range(dev, first_chan, last_chan, range);
718
719         /* set counter mode and counts */
720         cmd->convert_arg = das16_set_pacer(dev, cmd->convert_arg, cmd->flags);
721
722         /* enable counters */
723         byte = 0;
724         if (devpriv->can_burst) {
725                 if (cmd->convert_src == TRIG_NOW) {
726                         outb(DAS1600_BURST_VAL,
727                              dev->iobase + DAS1600_BURST_REG);
728                         /*  set burst length */
729                         byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
730                 } else {
731                         outb(0, dev->iobase + DAS1600_BURST_REG);
732                 }
733         }
734         outb(byte, dev->iobase + DAS16_PACER_REG);
735
736         /* set up dma transfer */
737         dma->cur_dma = 0;
738         das16_ai_setup_dma(dev, s, 0);
739
740         /*  set up timer */
741         spin_lock_irqsave(&dev->spinlock, flags);
742         devpriv->timer_running = 1;
743         devpriv->timer.expires = jiffies + timer_period();
744         add_timer(&devpriv->timer);
745
746         /* enable DMA interrupt with external or internal pacing */
747         devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_PACING_MASK);
748         devpriv->ctrl_reg |= DAS16_CTRL_DMAE;
749         if (cmd->convert_src == TRIG_EXT)
750                 devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
751         else
752                 devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
753         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
754
755         if (devpriv->can_burst)
756                 outb(0, dev->iobase + DAS1600_CONV_REG);
757         spin_unlock_irqrestore(&dev->spinlock, flags);
758
759         return 0;
760 }
761
762 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
763 {
764         struct das16_private_struct *devpriv = dev->private;
765         struct comedi_isadma *dma = devpriv->dma;
766         unsigned long flags;
767
768         spin_lock_irqsave(&dev->spinlock, flags);
769
770         /* disable interrupts, dma and pacer clocked conversions */
771         devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE | DAS16_CTRL_DMAE |
772                                DAS16_CTRL_PACING_MASK);
773         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
774
775         comedi_isadma_disable(dma->chan);
776
777         /*  disable SW timer */
778         if (devpriv->timer_running) {
779                 devpriv->timer_running = 0;
780                 del_timer(&devpriv->timer);
781         }
782
783         if (devpriv->can_burst)
784                 outb(0, dev->iobase + DAS1600_BURST_REG);
785
786         spin_unlock_irqrestore(&dev->spinlock, flags);
787
788         return 0;
789 }
790
791 static void das16_ai_munge(struct comedi_device *dev,
792                            struct comedi_subdevice *s, void *array,
793                            unsigned int num_bytes,
794                            unsigned int start_chan_index)
795 {
796         unsigned short *data = array;
797         unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
798         unsigned int i;
799         __le16 *buf = array;
800
801         for (i = 0; i < num_samples; i++) {
802                 data[i] = le16_to_cpu(buf[i]);
803                 if (s->maxdata == 0x0fff)
804                         data[i] >>= 4;
805                 data[i] &= s->maxdata;
806         }
807 }
808
809 static int das16_ai_eoc(struct comedi_device *dev,
810                         struct comedi_subdevice *s,
811                         struct comedi_insn *insn,
812                         unsigned long context)
813 {
814         unsigned int status;
815
816         status = inb(dev->iobase + DAS16_STATUS_REG);
817         if ((status & DAS16_STATUS_BUSY) == 0)
818                 return 0;
819         return -EBUSY;
820 }
821
822 static int das16_ai_insn_read(struct comedi_device *dev,
823                               struct comedi_subdevice *s,
824                               struct comedi_insn *insn,
825                               unsigned int *data)
826 {
827         unsigned int chan = CR_CHAN(insn->chanspec);
828         unsigned int range = CR_RANGE(insn->chanspec);
829         unsigned int val;
830         int ret;
831         int i;
832
833         /* set mux and range for single channel */
834         das16_ai_set_mux_range(dev, chan, chan, range);
835
836         for (i = 0; i < insn->n; i++) {
837                 /* trigger conversion */
838                 outb_p(0, dev->iobase + DAS16_TRIG_REG);
839
840                 ret = comedi_timeout(dev, s, insn, das16_ai_eoc, 0);
841                 if (ret)
842                         return ret;
843
844                 val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
845                 val |= inb(dev->iobase + DAS16_AI_LSB_REG);
846                 if (s->maxdata == 0x0fff)
847                         val >>= 4;
848                 val &= s->maxdata;
849
850                 data[i] = val;
851         }
852
853         return insn->n;
854 }
855
856 static int das16_ao_insn_write(struct comedi_device *dev,
857                                struct comedi_subdevice *s,
858                                struct comedi_insn *insn,
859                                unsigned int *data)
860 {
861         unsigned int chan = CR_CHAN(insn->chanspec);
862         int i;
863
864         for (i = 0; i < insn->n; i++) {
865                 unsigned int val = data[i];
866
867                 s->readback[chan] = val;
868
869                 val <<= 4;
870
871                 outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
872                 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
873         }
874
875         return insn->n;
876 }
877
878 static int das16_di_insn_bits(struct comedi_device *dev,
879                               struct comedi_subdevice *s,
880                               struct comedi_insn *insn,
881                               unsigned int *data)
882 {
883         data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
884
885         return insn->n;
886 }
887
888 static int das16_do_insn_bits(struct comedi_device *dev,
889                               struct comedi_subdevice *s,
890                               struct comedi_insn *insn,
891                               unsigned int *data)
892 {
893         if (comedi_dio_update_state(s, data))
894                 outb(s->state, dev->iobase + DAS16_DIO_REG);
895
896         data[1] = s->state;
897
898         return insn->n;
899 }
900
901 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
902 {
903         const struct das16_board *board = dev->board_ptr;
904         int diobits;
905
906         /* diobits indicates boards */
907         diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
908         if (board->id != diobits) {
909                 dev_err(dev->class_dev,
910                         "requested board's id bits are incorrect (0x%x != 0x%x)\n",
911                         board->id, diobits);
912                 return -EINVAL;
913         }
914
915         return 0;
916 }
917
918 static void das16_reset(struct comedi_device *dev)
919 {
920         outb(0, dev->iobase + DAS16_STATUS_REG);
921         outb(0, dev->iobase + DAS16_CTRL_REG);
922         outb(0, dev->iobase + DAS16_PACER_REG);
923 }
924
925 static void das16_alloc_dma(struct comedi_device *dev, unsigned int dma_chan)
926 {
927         struct das16_private_struct *devpriv = dev->private;
928
929         timer_setup(&devpriv->timer, das16_timer_interrupt, 0);
930
931         /* only DMA channels 3 and 1 are valid */
932         if (!(dma_chan == 1 || dma_chan == 3))
933                 return;
934
935         /* DMA uses two buffers */
936         devpriv->dma = comedi_isadma_alloc(dev, 2, dma_chan, dma_chan,
937                                            DAS16_DMA_SIZE, COMEDI_ISADMA_READ);
938 }
939
940 static void das16_free_dma(struct comedi_device *dev)
941 {
942         struct das16_private_struct *devpriv = dev->private;
943
944         if (devpriv) {
945                 del_timer_sync(&devpriv->timer);
946                 comedi_isadma_free(devpriv->dma);
947         }
948 }
949
950 static const struct comedi_lrange *das16_ai_range(struct comedi_device *dev,
951                                                   struct comedi_subdevice *s,
952                                                   struct comedi_devconfig *it,
953                                                   unsigned int pg_type,
954                                                   unsigned int status)
955 {
956         unsigned int min = it->options[4];
957         unsigned int max = it->options[5];
958
959         /* get any user-defined input range */
960         if (pg_type == das16_pg_none && (min || max)) {
961                 struct comedi_lrange *lrange;
962                 struct comedi_krange *krange;
963
964                 /* allocate single-range range table */
965                 lrange = comedi_alloc_spriv(s,
966                                             sizeof(*lrange) + sizeof(*krange));
967                 if (!lrange)
968                         return &range_unknown;
969
970                 /* initialize ai range */
971                 lrange->length = 1;
972                 krange = lrange->range;
973                 krange->min = min;
974                 krange->max = max;
975                 krange->flags = UNIT_volt;
976
977                 return lrange;
978         }
979
980         /* use software programmable range */
981         if (status & DAS16_STATUS_UNIPOLAR)
982                 return das16_ai_uni_lranges[pg_type];
983         return das16_ai_bip_lranges[pg_type];
984 }
985
986 static const struct comedi_lrange *das16_ao_range(struct comedi_device *dev,
987                                                   struct comedi_subdevice *s,
988                                                   struct comedi_devconfig *it)
989 {
990         unsigned int min = it->options[6];
991         unsigned int max = it->options[7];
992
993         /* get any user-defined output range */
994         if (min || max) {
995                 struct comedi_lrange *lrange;
996                 struct comedi_krange *krange;
997
998                 /* allocate single-range range table */
999                 lrange = comedi_alloc_spriv(s,
1000                                             sizeof(*lrange) + sizeof(*krange));
1001                 if (!lrange)
1002                         return &range_unknown;
1003
1004                 /* initialize ao range */
1005                 lrange->length = 1;
1006                 krange = lrange->range;
1007                 krange->min = min;
1008                 krange->max = max;
1009                 krange->flags = UNIT_volt;
1010
1011                 return lrange;
1012         }
1013
1014         return &range_unknown;
1015 }
1016
1017 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1018 {
1019         const struct das16_board *board = dev->board_ptr;
1020         struct das16_private_struct *devpriv;
1021         struct comedi_subdevice *s;
1022         unsigned int osc_base;
1023         unsigned int status;
1024         int ret;
1025
1026         /*  check that clock setting is valid */
1027         if (it->options[3]) {
1028                 if (it->options[3] != 1 && it->options[3] != 10) {
1029                         dev_err(dev->class_dev,
1030                                 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1031                         return -EINVAL;
1032                 }
1033         }
1034
1035         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1036         if (!devpriv)
1037                 return -ENOMEM;
1038         devpriv->dev = dev;
1039
1040         if (board->size < 0x400) {
1041                 ret = comedi_request_region(dev, it->options[0], board->size);
1042                 if (ret)
1043                         return ret;
1044         } else {
1045                 ret = comedi_request_region(dev, it->options[0], 0x10);
1046                 if (ret)
1047                         return ret;
1048                 /* Request an additional region for the 8255 */
1049                 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1050                                               board->size & 0x3ff);
1051                 if (ret)
1052                         return ret;
1053                 devpriv->extra_iobase = dev->iobase + 0x400;
1054                 devpriv->can_burst = 1;
1055         }
1056
1057         /*  probe id bits to make sure they are consistent */
1058         if (das16_probe(dev, it))
1059                 return -EINVAL;
1060
1061         /*  get master clock speed */
1062         osc_base = I8254_OSC_BASE_1MHZ;
1063         if (devpriv->can_burst) {
1064                 status = inb(dev->iobase + DAS1600_STATUS_REG);
1065                 if (status & DAS1600_STATUS_CLK_10MHZ)
1066                         osc_base = I8254_OSC_BASE_10MHZ;
1067         } else {
1068                 if (it->options[3])
1069                         osc_base = I8254_OSC_BASE_1MHZ / it->options[3];
1070         }
1071
1072         dev->pacer = comedi_8254_init(dev->iobase + DAS16_TIMER_BASE_REG,
1073                                       osc_base, I8254_IO8, 0);
1074         if (!dev->pacer)
1075                 return -ENOMEM;
1076
1077         das16_alloc_dma(dev, it->options[2]);
1078
1079         ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1080         if (ret)
1081                 return ret;
1082
1083         status = inb(dev->iobase + DAS16_STATUS_REG);
1084
1085         /* Analog Input subdevice */
1086         s = &dev->subdevices[0];
1087         s->type         = COMEDI_SUBD_AI;
1088         s->subdev_flags = SDF_READABLE;
1089         if (status & DAS16_STATUS_MUXBIT) {
1090                 s->subdev_flags |= SDF_GROUND;
1091                 s->n_chan       = 16;
1092         } else {
1093                 s->subdev_flags |= SDF_DIFF;
1094                 s->n_chan       = 8;
1095         }
1096         s->len_chanlist = s->n_chan;
1097         s->maxdata      = board->ai_maxdata;
1098         s->range_table  = das16_ai_range(dev, s, it, board->ai_pg, status);
1099         s->insn_read    = das16_ai_insn_read;
1100         if (devpriv->dma) {
1101                 dev->read_subdev = s;
1102                 s->subdev_flags |= SDF_CMD_READ;
1103                 s->do_cmdtest   = das16_cmd_test;
1104                 s->do_cmd       = das16_cmd_exec;
1105                 s->cancel       = das16_cancel;
1106                 s->munge        = das16_ai_munge;
1107         }
1108
1109         /* Analog Output subdevice */
1110         s = &dev->subdevices[1];
1111         if (board->has_ao) {
1112                 s->type         = COMEDI_SUBD_AO;
1113                 s->subdev_flags = SDF_WRITABLE;
1114                 s->n_chan       = 2;
1115                 s->maxdata      = 0x0fff;
1116                 s->range_table  = das16_ao_range(dev, s, it);
1117                 s->insn_write   = das16_ao_insn_write;
1118
1119                 ret = comedi_alloc_subdev_readback(s);
1120                 if (ret)
1121                         return ret;
1122         } else {
1123                 s->type         = COMEDI_SUBD_UNUSED;
1124         }
1125
1126         /* Digital Input subdevice */
1127         s = &dev->subdevices[2];
1128         s->type         = COMEDI_SUBD_DI;
1129         s->subdev_flags = SDF_READABLE;
1130         s->n_chan       = 4;
1131         s->maxdata      = 1;
1132         s->range_table  = &range_digital;
1133         s->insn_bits    = das16_di_insn_bits;
1134
1135         /* Digital Output subdevice */
1136         s = &dev->subdevices[3];
1137         s->type         = COMEDI_SUBD_DO;
1138         s->subdev_flags = SDF_WRITABLE;
1139         s->n_chan       = 4;
1140         s->maxdata      = 1;
1141         s->range_table  = &range_digital;
1142         s->insn_bits    = das16_do_insn_bits;
1143
1144         /* initialize digital output lines */
1145         outb(s->state, dev->iobase + DAS16_DIO_REG);
1146
1147         /* 8255 Digital I/O subdevice */
1148         if (board->has_8255) {
1149                 s = &dev->subdevices[4];
1150                 ret = subdev_8255_init(dev, s, NULL, board->i8255_offset);
1151                 if (ret)
1152                         return ret;
1153         }
1154
1155         das16_reset(dev);
1156         /* set the interrupt level */
1157         devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1158         outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1159
1160         if (devpriv->can_burst) {
1161                 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1162                 outb(0, dev->iobase + DAS1600_CONV_REG);
1163                 outb(0, dev->iobase + DAS1600_BURST_REG);
1164         }
1165
1166         return 0;
1167 }
1168
1169 static void das16_detach(struct comedi_device *dev)
1170 {
1171         const struct das16_board *board = dev->board_ptr;
1172         struct das16_private_struct *devpriv = dev->private;
1173
1174         if (devpriv) {
1175                 if (dev->iobase)
1176                         das16_reset(dev);
1177                 das16_free_dma(dev);
1178
1179                 if (devpriv->extra_iobase)
1180                         release_region(devpriv->extra_iobase,
1181                                        board->size & 0x3ff);
1182         }
1183
1184         comedi_legacy_detach(dev);
1185 }
1186
1187 static struct comedi_driver das16_driver = {
1188         .driver_name    = "das16",
1189         .module         = THIS_MODULE,
1190         .attach         = das16_attach,
1191         .detach         = das16_detach,
1192         .board_name     = &das16_boards[0].name,
1193         .num_names      = ARRAY_SIZE(das16_boards),
1194         .offset         = sizeof(das16_boards[0]),
1195 };
1196 module_comedi_driver(das16_driver);
1197
1198 MODULE_AUTHOR("Comedi http://www.comedi.org");
1199 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1200 MODULE_LICENSE("GPL");