das1800: don't access *data when insn->bits == 0
[comedi.git] / comedi / drivers / das1800.c
1 /*
2     comedi/drivers/das1800.c
3     Driver for Keitley das1700/das1800 series boards
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: das1800
27 Description: Keithley Metrabyte DAS1800 (& compatibles)
28 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
29 Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
30   DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
31   DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
32   DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
33   DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
34   DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
35   DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
36   DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
37   DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
38   DAS-1802AO (das-1802ao)
39 Status: works
40
41 The waveform analog output on the 'ao' cards is not supported.
42 If you need it, send me (Frank Hess) an email.
43
44 Configuration options:
45   [0] - I/O port base address
46   [1] - IRQ (optional, required for timed or externally triggered conversions)
47   [2] - DMA0 (optional, requires irq)
48   [3] - DMA1 (optional, requires irq and dma0)
49 */
50 /*
51
52 This driver supports the following Keithley boards:
53
54 das-1701st
55 das-1701st-da
56 das-1701ao
57 das-1702st
58 das-1702st-da
59 das-1702hr
60 das-1702hr-da
61 das-1702ao
62 das-1801st
63 das-1801st-da
64 das-1801hc
65 das-1801ao
66 das-1802st
67 das-1802st-da
68 das-1802hr
69 das-1802hr-da
70 das-1802hc
71 das-1802ao
72
73 Options:
74         [0] - base io address
75         [1] - irq (optional, required for timed or externally triggered conversions)
76         [2] - dma0 (optional, requires irq)
77         [3] - dma1 (optional, requires irq and dma0)
78
79 irq can be omitted, although the cmd interface will not work without it.
80
81 analog input cmd triggers supported:
82         start_src:      TRIG_NOW | TRIG_EXT
83         scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
84         scan_end_src:   TRIG_COUNT
85         convert_src:    TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
86         stop_src:       TRIG_COUNT | TRIG_EXT | TRIG_NONE
87
88 scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
89 'burst mode' which limits the valid conversion time to 64 microseconds
90 (convert_arg <= 64000).  This limitation does not apply if scan_begin_src
91 is TRIG_FOLLOW.
92
93 NOTES:
94 Only the DAS-1801ST has been tested by me.
95 Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
96
97 TODO:
98         Make it automatically allocate irq and dma channels if they are not specified
99         Add support for analog out on 'ao' cards
100         read insn for analog out
101 */
102
103 #include <linux/comedidev.h>
104
105 #include <linux/ioport.h>
106 #include <asm/dma.h>
107
108 #include "8253.h"
109 #include "comedi_fc.h"
110
111 // misc. defines
112 #define DAS1800_SIZE           16       //uses 16 io addresses
113 #define FIFO_SIZE              1024     // 1024 sample fifo
114 #define TIMER_BASE             200      // 5 Mhz master clock
115 #define UNIPOLAR               0x4      // bit that determines whether input range is uni/bipolar
116 #define DMA_BUF_SIZE           0x1ff00  // size in bytes of dma buffers
117
118 /* Registers for the das1800 */
119 #define DAS1800_FIFO            0x0
120 #define DAS1800_QRAM            0x0
121 #define DAS1800_DAC             0x0
122 #define DAS1800_SELECT          0x2
123 #define   ADC                     0x0
124 #define   QRAM                    0x1
125 #define   DAC(a)                  (0x2 + a)
126 #define DAS1800_DIGITAL         0x3
127 #define DAS1800_CONTROL_A       0x4
128 #define   FFEN                    0x1
129 #define   CGEN                    0x4
130 #define   CGSL                    0x8
131 #define   TGEN                    0x10
132 #define   TGSL                    0x20
133 #define   ATEN                    0x80
134 #define DAS1800_CONTROL_B       0x5
135 #define   DMA_CH5                 0x1
136 #define   DMA_CH6                 0x2
137 #define   DMA_CH7                 0x3
138 #define   DMA_CH5_CH6             0x5
139 #define   DMA_CH6_CH7             0x6
140 #define   DMA_CH7_CH5             0x7
141 #define   DMA_ENABLED             0x3   //mask used to determine if dma is enabled
142 #define   DMA_DUAL                0x4
143 #define   IRQ3                    0x8
144 #define   IRQ5                    0x10
145 #define   IRQ7                    0x18
146 #define   IRQ10                   0x28
147 #define   IRQ11                   0x30
148 #define   IRQ15                   0x38
149 #define   FIMD                    0x40
150 #define DAS1800_CONTROL_C       0X6
151 #define   IPCLK                   0x1
152 #define   XPCLK                   0x3
153 #define   BMDE                    0x4
154 #define   CMEN                    0x8
155 #define   UQEN                    0x10
156 #define   SD                      0x40
157 #define   UB                      0x80
158 #define DAS1800_STATUS          0x7
159 // bits that prevent interrupt status bits (and CVEN) from being cleared on write
160 #define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
161 #define   INT                     0x1
162 #define   DMATC                   0x2
163 #define   CT0TC                   0x8
164 #define   OVF                     0x10
165 #define   FHF                     0x20
166 #define   FNE                     0x40
167 #define   CVEN_MASK               0x40  // masks CVEN on write
168 #define   CVEN                    0x80
169 #define DAS1800_BURST_LENGTH    0x8
170 #define DAS1800_BURST_RATE      0x9
171 #define DAS1800_QRAM_ADDRESS    0xa
172 #define DAS1800_COUNTER         0xc
173
174 #define IOBASE2                   0x400 //offset of additional ioports used on 'ao' cards
175
176 enum {
177         das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
178         das1702hr_da,
179         das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
180         das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
181 };
182
183 static int das1800_attach(comedi_device * dev, comedi_devconfig * it);
184 static int das1800_detach(comedi_device * dev);
185 static int das1800_probe(comedi_device * dev);
186 static int das1800_cancel(comedi_device * dev, comedi_subdevice * s);
187 static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG);
188 static int das1800_ai_poll(comedi_device * dev, comedi_subdevice * s);
189 static void das1800_ai_handler(comedi_device * dev);
190 static void das1800_handle_dma(comedi_device * dev, comedi_subdevice * s,
191         unsigned int status);
192 static void das1800_flush_dma(comedi_device * dev, comedi_subdevice * s);
193 static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
194         unsigned int channel, uint16_t * buffer);
195 static void das1800_handle_fifo_half_full(comedi_device * dev,
196         comedi_subdevice * s);
197 static void das1800_handle_fifo_not_empty(comedi_device * dev,
198         comedi_subdevice * s);
199 static int das1800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
200         comedi_cmd * cmd);
201 static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s);
202 static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
203         comedi_insn * insn, lsampl_t * data);
204 static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
205         comedi_insn * insn, lsampl_t * data);
206 static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
207         comedi_insn * insn, lsampl_t * data);
208 static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
209         comedi_insn * insn, lsampl_t * data);
210
211 static int das1800_set_frequency(comedi_device * dev);
212 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
213 static unsigned int suggest_transfer_size(comedi_cmd * cmd);
214
215 // analog input ranges
216 static const comedi_lrange range_ai_das1801 = {
217         8,
218         {
219                         RANGE(-5, 5),
220                         RANGE(-1, 1),
221                         RANGE(-0.1, 0.1),
222                         RANGE(-0.02, 0.02),
223                         RANGE(0, 5),
224                         RANGE(0, 1),
225                         RANGE(0, 0.1),
226                         RANGE(0, 0.02),
227                 }
228 };
229
230 static const comedi_lrange range_ai_das1802 = {
231         8,
232         {
233                         RANGE(-10, 10),
234                         RANGE(-5, 5),
235                         RANGE(-2.5, 2.5),
236                         RANGE(-1.25, 1.25),
237                         RANGE(0, 10),
238                         RANGE(0, 5),
239                         RANGE(0, 2.5),
240                         RANGE(0, 1.25),
241                 }
242 };
243
244 typedef struct das1800_board_struct {
245         const char *name;
246         int ai_speed;           /* max conversion period in nanoseconds */
247         int resolution;         /* bits of ai resolution */
248         int qram_len;           /* length of card's channel / gain queue */
249         int common;             /* supports AREF_COMMON flag */
250         int do_n_chan;          /* number of digital output channels */
251         int ao_ability;         /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
252         int ao_n_chan;          /* number of analog out channels */
253         const comedi_lrange *range_ai;  /* available input ranges */
254 } das1800_board;
255
256 /* Warning: the maximum conversion speeds listed below are
257  * not always achievable depending on board setup (see
258  * user manual.)
259  */
260 static const das1800_board das1800_boards[] = {
261         {
262               name:     "das-1701st",
263               ai_speed:6250,
264               resolution:12,
265               qram_len:256,
266               common:   1,
267               do_n_chan:4,
268               ao_ability:0,
269               ao_n_chan:0,
270               range_ai:&range_ai_das1801,
271                 },
272         {
273               name:     "das-1701st-da",
274               ai_speed:6250,
275               resolution:12,
276               qram_len:256,
277               common:   1,
278               do_n_chan:4,
279               ao_ability:1,
280               ao_n_chan:4,
281               range_ai:&range_ai_das1801,
282                 },
283         {
284               name:     "das-1702st",
285               ai_speed:6250,
286               resolution:12,
287               qram_len:256,
288               common:   1,
289               do_n_chan:4,
290               ao_ability:0,
291               ao_n_chan:0,
292               range_ai:&range_ai_das1802,
293                 },
294         {
295               name:     "das-1702st-da",
296               ai_speed:6250,
297               resolution:12,
298               qram_len:256,
299               common:   1,
300               do_n_chan:4,
301               ao_ability:1,
302               ao_n_chan:4,
303               range_ai:&range_ai_das1802,
304                 },
305         {
306               name:     "das-1702hr",
307               ai_speed:20000,
308               resolution:16,
309               qram_len:256,
310               common:   1,
311               do_n_chan:4,
312               ao_ability:0,
313               ao_n_chan:0,
314               range_ai:&range_ai_das1802,
315                 },
316         {
317               name:     "das-1702hr-da",
318               ai_speed:20000,
319               resolution:16,
320               qram_len:256,
321               common:   1,
322               do_n_chan:4,
323               ao_ability:1,
324               ao_n_chan:2,
325               range_ai:&range_ai_das1802,
326                 },
327         {
328               name:     "das-1701ao",
329               ai_speed:6250,
330               resolution:12,
331               qram_len:256,
332               common:   1,
333               do_n_chan:4,
334               ao_ability:2,
335               ao_n_chan:2,
336               range_ai:&range_ai_das1801,
337                 },
338         {
339               name:     "das-1702ao",
340               ai_speed:6250,
341               resolution:12,
342               qram_len:256,
343               common:   1,
344               do_n_chan:4,
345               ao_ability:2,
346               ao_n_chan:2,
347               range_ai:&range_ai_das1802,
348                 },
349         {
350               name:     "das-1801st",
351               ai_speed:3000,
352               resolution:12,
353               qram_len:256,
354               common:   1,
355               do_n_chan:4,
356               ao_ability:0,
357               ao_n_chan:0,
358               range_ai:&range_ai_das1801,
359                 },
360         {
361               name:     "das-1801st-da",
362               ai_speed:3000,
363               resolution:12,
364               qram_len:256,
365               common:   1,
366               do_n_chan:4,
367               ao_ability:0,
368               ao_n_chan:4,
369               range_ai:&range_ai_das1801,
370                 },
371         {
372               name:     "das-1802st",
373               ai_speed:3000,
374               resolution:12,
375               qram_len:256,
376               common:   1,
377               do_n_chan:4,
378               ao_ability:0,
379               ao_n_chan:0,
380               range_ai:&range_ai_das1802,
381                 },
382         {
383               name:     "das-1802st-da",
384               ai_speed:3000,
385               resolution:12,
386               qram_len:256,
387               common:   1,
388               do_n_chan:4,
389               ao_ability:1,
390               ao_n_chan:4,
391               range_ai:&range_ai_das1802,
392                 },
393         {
394               name:     "das-1802hr",
395               ai_speed:10000,
396               resolution:16,
397               qram_len:256,
398               common:   1,
399               do_n_chan:4,
400               ao_ability:0,
401               ao_n_chan:0,
402               range_ai:&range_ai_das1802,
403                 },
404         {
405               name:     "das-1802hr-da",
406               ai_speed:10000,
407               resolution:16,
408               qram_len:256,
409               common:   1,
410               do_n_chan:4,
411               ao_ability:1,
412               ao_n_chan:2,
413               range_ai:&range_ai_das1802,
414                 },
415         {
416               name:     "das-1801hc",
417               ai_speed:3000,
418               resolution:12,
419               qram_len:64,
420               common:   0,
421               do_n_chan:8,
422               ao_ability:1,
423               ao_n_chan:2,
424               range_ai:&range_ai_das1801,
425                 },
426         {
427               name:     "das-1802hc",
428               ai_speed:3000,
429               resolution:12,
430               qram_len:64,
431               common:   0,
432               do_n_chan:8,
433               ao_ability:1,
434               ao_n_chan:2,
435               range_ai:&range_ai_das1802,
436                 },
437         {
438               name:     "das-1801ao",
439               ai_speed:3000,
440               resolution:12,
441               qram_len:256,
442               common:   1,
443               do_n_chan:4,
444               ao_ability:2,
445               ao_n_chan:2,
446               range_ai:&range_ai_das1801,
447                 },
448         {
449               name:     "das-1802ao",
450               ai_speed:3000,
451               resolution:12,
452               qram_len:256,
453               common:   1,
454               do_n_chan:4,
455               ao_ability:2,
456               ao_n_chan:2,
457               range_ai:&range_ai_das1802,
458                 },
459 };
460
461 /*
462  * Useful for shorthand access to the particular board structure
463  */
464 #define thisboard ((const das1800_board *)dev->board_ptr)
465
466 typedef struct {
467         volatile unsigned int count;    /* number of data points left to be taken */
468         unsigned int divisor1;  /* value to load into board's counter 1 for timed conversions */
469         unsigned int divisor2;  /* value to load into board's counter 2 for timed conversions */
470         int do_bits;            /* digital output bits */
471         int irq_dma_bits;       /* bits for control register b */
472         /* dma bits for control register b, stored so that dma can be
473          * turned on and off */
474         int dma_bits;
475         unsigned int dma0;      /* dma channels used */
476         unsigned int dma1;
477         volatile unsigned int dma_current;      /* dma channel currently in use */
478         uint16_t *ai_buf0;      /* pointers to dma buffers */
479         uint16_t *ai_buf1;
480         uint16_t *dma_current_buf;      /* pointer to dma buffer currently being used */
481         unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */
482         unsigned long iobase2;  /* secondary io address used for analog out on 'ao' boards */
483         short ao_update_bits;   /* remembers the last write to the 'update' dac */
484 } das1800_private;
485
486 #define devpriv ((das1800_private *)dev->private)
487
488 // analog out range for boards with basic analog out
489 static const comedi_lrange range_ao_1 = {
490         1,
491         {
492                         RANGE(-10, 10),
493                 }
494 };
495
496 // analog out range for 'ao' boards
497 /*
498 static const comedi_lrange range_ao_2 = {
499         2,
500         {
501                 RANGE(-10, 10),
502                 RANGE(-5, 5),
503         }
504 };
505 */
506
507 static comedi_driver driver_das1800 = {
508       driver_name:"das1800",
509       module:THIS_MODULE,
510       attach:das1800_attach,
511       detach:das1800_detach,
512       num_names:sizeof(das1800_boards) / sizeof(das1800_board),
513       board_name:&das1800_boards[0].name,
514       offset:sizeof(das1800_board),
515 };
516
517 /*
518  * A convenient macro that defines init_module() and cleanup_module(),
519  * as necessary.
520  */
521 COMEDI_INITCLEANUP(driver_das1800);
522
523 static int das1800_init_dma(comedi_device * dev, unsigned int dma0,
524         unsigned int dma1)
525 {
526         unsigned long flags;
527
528         // need an irq to do dma
529         if (dev->irq && dma0) {
530                 //encode dma0 and dma1 into 2 digit hexadecimal for switch
531                 switch ((dma0 & 0x7) | (dma1 << 4)) {
532                 case 0x5:       // dma0 == 5
533                         devpriv->dma_bits |= DMA_CH5;
534                         break;
535                 case 0x6:       // dma0 == 6
536                         devpriv->dma_bits |= DMA_CH6;
537                         break;
538                 case 0x7:       // dma0 == 7
539                         devpriv->dma_bits |= DMA_CH7;
540                         break;
541                 case 0x65:      // dma0 == 5, dma1 == 6
542                         devpriv->dma_bits |= DMA_CH5_CH6;
543                         break;
544                 case 0x76:      // dma0 == 6, dma1 == 7
545                         devpriv->dma_bits |= DMA_CH6_CH7;
546                         break;
547                 case 0x57:      // dma0 == 7, dma1 == 5
548                         devpriv->dma_bits |= DMA_CH7_CH5;
549                         break;
550                 default:
551                         printk(" only supports dma channels 5 through 7\n"
552                                 " Dual dma only allows the following combinations:\n"
553                                 " dma 5,6 / 6,7 / or 7,5\n");
554                         return -EINVAL;
555                         break;
556                 }
557                 if (request_dma(dma0, driver_das1800.driver_name)) {
558                         printk(" failed to allocate dma channel %i\n", dma0);
559                         return -EINVAL;
560                 }
561                 devpriv->dma0 = dma0;
562                 devpriv->dma_current = dma0;
563                 if (dma1) {
564                         if (request_dma(dma1, driver_das1800.driver_name)) {
565                                 printk(" failed to allocate dma channel %i\n",
566                                         dma1);
567                                 return -EINVAL;
568                         }
569                         devpriv->dma1 = dma1;
570                 }
571                 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
572                 if (devpriv->ai_buf0 == NULL)
573                         return -ENOMEM;
574                 devpriv->dma_current_buf = devpriv->ai_buf0;
575                 if (dma1) {
576                         devpriv->ai_buf1 =
577                                 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
578                         if (devpriv->ai_buf1 == NULL)
579                                 return -ENOMEM;
580                 }
581                 flags = claim_dma_lock();
582                 disable_dma(devpriv->dma0);
583                 set_dma_mode(devpriv->dma0, DMA_MODE_READ);
584                 if (dma1) {
585                         disable_dma(devpriv->dma1);
586                         set_dma_mode(devpriv->dma1, DMA_MODE_READ);
587                 }
588                 release_dma_lock(flags);
589         }
590         return 0;
591 }
592
593 static int das1800_attach(comedi_device * dev, comedi_devconfig * it)
594 {
595         comedi_subdevice *s;
596         unsigned long iobase = it->options[0];
597         unsigned int irq = it->options[1];
598         unsigned int dma0 = it->options[2];
599         unsigned int dma1 = it->options[3];
600         unsigned long iobase2;
601         int board;
602         int retval;
603
604         /* allocate and initialize dev->private */
605         if (alloc_private(dev, sizeof(das1800_private)) < 0)
606                 return -ENOMEM;
607
608         printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
609                 iobase);
610         if (irq) {
611                 printk(", irq %u", irq);
612                 if (dma0) {
613                         printk(", dma %u", dma0);
614                         if (dma1)
615                                 printk(" and %u", dma1);
616                 }
617         }
618         printk("\n");
619
620         if (iobase == 0) {
621                 printk(" io base address required\n");
622                 return -EINVAL;
623         }
624
625         /* check if io addresses are available */
626         if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
627                 printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1);
628                 return -EIO;
629         }
630         dev->iobase = iobase;
631
632         board = das1800_probe(dev);
633         if (board < 0) {
634                 printk(" unable to determine board type\n");
635                 return -ENODEV;
636         }
637
638         dev->board_ptr = das1800_boards + board;
639         dev->board_name = thisboard->name;
640
641         // if it is an 'ao' board with fancy analog out then we need extra io ports
642         if (thisboard->ao_ability == 2) {
643                 iobase2 = iobase + IOBASE2;
644                 if (!request_region(iobase2, DAS1800_SIZE,
645                                 driver_das1800.driver_name)) {
646                         printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1);
647                         return -EIO;
648                 }
649                 devpriv->iobase2 = iobase2;
650         }
651
652         /* grab our IRQ */
653         if (irq) {
654                 if (comedi_request_irq(irq, das1800_interrupt, 0,
655                                 driver_das1800.driver_name, dev)) {
656                         printk(" unable to allocate irq %u\n", irq);
657                         return -EINVAL;
658                 }
659         }
660         dev->irq = irq;
661
662         // set bits that tell card which irq to use
663         switch (irq) {
664         case 0:
665                 break;
666         case 3:
667                 devpriv->irq_dma_bits |= 0x8;
668                 break;
669         case 5:
670                 devpriv->irq_dma_bits |= 0x10;
671                 break;
672         case 7:
673                 devpriv->irq_dma_bits |= 0x18;
674                 break;
675         case 10:
676                 devpriv->irq_dma_bits |= 0x28;
677                 break;
678         case 11:
679                 devpriv->irq_dma_bits |= 0x30;
680                 break;
681         case 15:
682                 devpriv->irq_dma_bits |= 0x38;
683                 break;
684         default:
685                 printk(" irq out of range\n");
686                 return -EINVAL;
687                 break;
688         }
689
690         retval = das1800_init_dma(dev, dma0, dma1);
691         if (retval < 0)
692                 return retval;
693
694         if (devpriv->ai_buf0 == NULL) {
695                 devpriv->ai_buf0 =
696                         kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
697                 if (devpriv->ai_buf0 == NULL)
698                         return -ENOMEM;
699         }
700
701         if (alloc_subdevices(dev, 4) < 0)
702                 return -ENOMEM;
703
704         /* analog input subdevice */
705         s = dev->subdevices + 0;
706         dev->read_subdev = s;
707         s->type = COMEDI_SUBD_AI;
708         s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
709         if (thisboard->common)
710                 s->subdev_flags |= SDF_COMMON;
711         s->n_chan = thisboard->qram_len;
712         s->len_chanlist = thisboard->qram_len;
713         s->maxdata = (1 << thisboard->resolution) - 1;
714         s->range_table = thisboard->range_ai;
715         s->do_cmd = das1800_ai_do_cmd;
716         s->do_cmdtest = das1800_ai_do_cmdtest;
717         s->insn_read = das1800_ai_rinsn;
718         s->poll = das1800_ai_poll;
719         s->cancel = das1800_cancel;
720
721         /* analog out */
722         s = dev->subdevices + 1;
723         if (thisboard->ao_ability == 1) {
724                 s->type = COMEDI_SUBD_AO;
725                 s->subdev_flags = SDF_WRITABLE;
726                 s->n_chan = thisboard->ao_n_chan;
727                 s->maxdata = (1 << thisboard->resolution) - 1;
728                 s->range_table = &range_ao_1;
729                 s->insn_write = das1800_ao_winsn;
730         } else {
731                 s->type = COMEDI_SUBD_UNUSED;
732         }
733
734         /* di */
735         s = dev->subdevices + 2;
736         s->type = COMEDI_SUBD_DI;
737         s->subdev_flags = SDF_READABLE;
738         s->n_chan = 4;
739         s->maxdata = 1;
740         s->range_table = &range_digital;
741         s->insn_bits = das1800_di_rbits;
742
743         /* do */
744         s = dev->subdevices + 3;
745         s->type = COMEDI_SUBD_DO;
746         s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
747         s->n_chan = thisboard->do_n_chan;
748         s->maxdata = 1;
749         s->range_table = &range_digital;
750         s->insn_bits = das1800_do_wbits;
751
752         das1800_cancel(dev, dev->read_subdev);
753
754         // initialize digital out channels
755         outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
756
757         // initialize analog out channels
758         if (thisboard->ao_ability == 1) {
759                 // select 'update' dac channel for baseAddress + 0x0
760                 outb(DAC(thisboard->ao_n_chan - 1),
761                         dev->iobase + DAS1800_SELECT);
762                 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
763         }
764
765         return 0;
766 };
767
768 static int das1800_detach(comedi_device * dev)
769 {
770         /* only free stuff if it has been allocated by _attach */
771         if (dev->iobase)
772                 release_region(dev->iobase, DAS1800_SIZE);
773         if (dev->irq)
774                 comedi_free_irq(dev->irq, dev);
775         if (dev->private) {
776                 if (devpriv->iobase2)
777                         release_region(devpriv->iobase2, DAS1800_SIZE);
778                 if (devpriv->dma0)
779                         free_dma(devpriv->dma0);
780                 if (devpriv->dma1)
781                         free_dma(devpriv->dma1);
782                 if (devpriv->ai_buf0)
783                         kfree(devpriv->ai_buf0);
784                 if (devpriv->ai_buf1)
785                         kfree(devpriv->ai_buf1);
786         }
787
788         printk("comedi%d: %s: remove\n", dev->minor,
789                 driver_das1800.driver_name);
790
791         return 0;
792 };
793
794 /* probes and checks das-1800 series board type
795  */
796 static int das1800_probe(comedi_device * dev)
797 {
798         int id;
799         int board;
800
801         id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;   /* get id bits */
802         board = ((das1800_board *) dev->board_ptr) - das1800_boards;
803
804         switch (id) {
805         case 0x3:
806                 if (board == das1801st_da || board == das1802st_da ||
807                         board == das1701st_da || board == das1702st_da) {
808                         printk(" Board model: %s\n",
809                                 das1800_boards[board].name);
810                         return board;
811                 }
812                 printk(" Board model (probed, not recommended): das-1800st-da series\n");
813                 return das1801st;
814                 break;
815         case 0x4:
816                 if (board == das1802hr_da || board == das1702hr_da) {
817                         printk(" Board model: %s\n",
818                                 das1800_boards[board].name);
819                         return board;
820                 }
821                 printk(" Board model (probed, not recommended): das-1802hr-da\n");
822                 return das1802hr;
823                 break;
824         case 0x5:
825                 if (board == das1801ao || board == das1802ao ||
826                         board == das1701ao || board == das1702ao) {
827                         printk(" Board model: %s\n",
828                                 das1800_boards[board].name);
829                         return board;
830                 }
831                 printk(" Board model (probed, not recommended): das-1800ao series\n");
832                 return das1801ao;
833                 break;
834         case 0x6:
835                 if (board == das1802hr || board == das1702hr) {
836                         printk(" Board model: %s\n",
837                                 das1800_boards[board].name);
838                         return board;
839                 }
840                 printk(" Board model (probed, not recommended): das-1802hr\n");
841                 return das1802hr;
842                 break;
843         case 0x7:
844                 if (board == das1801st || board == das1802st ||
845                         board == das1701st || board == das1702st) {
846                         printk(" Board model: %s\n",
847                                 das1800_boards[board].name);
848                         return board;
849                 }
850                 printk(" Board model (probed, not recommended): das-1800st series\n");
851                 return das1801st;
852                 break;
853         case 0x8:
854                 if (board == das1801hc || board == das1802hc) {
855                         printk(" Board model: %s\n",
856                                 das1800_boards[board].name);
857                         return board;
858                 }
859                 printk(" Board model (probed, not recommended): das-1800hc series\n");
860                 return das1801hc;
861                 break;
862         default:
863                 printk(" Board model: probe returned 0x%x (unknown, please report)\n", id);
864                 return board;
865                 break;
866         }
867         return -1;
868 }
869
870 static int das1800_ai_poll(comedi_device * dev, comedi_subdevice * s)
871 {
872         unsigned long flags;
873
874         // prevent race with interrupt handler
875         comedi_spin_lock_irqsave(&dev->spinlock, flags);
876         das1800_ai_handler(dev);
877         comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
878
879         return s->async->buf_write_count - s->async->buf_read_count;
880 }
881
882 static irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
883 {
884         comedi_device *dev = d;
885         unsigned int status;
886
887         if (dev->attached == 0) {
888                 comedi_error(dev, "premature interrupt");
889                 return IRQ_HANDLED;
890         }
891
892         /* Prevent race with das1800_ai_poll() on multi processor systems.
893          * Also protects indirect addressing in das1800_ai_handler */
894         spin_lock(&dev->spinlock);
895         status = inb(dev->iobase + DAS1800_STATUS);
896
897         /* if interrupt was not caused by das-1800 */
898         if (!(status & INT)) {
899                 spin_unlock(&dev->spinlock);
900                 return IRQ_NONE;
901         }
902         /* clear the interrupt status bit INT */
903         outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
904         // handle interrupt
905         das1800_ai_handler(dev);
906
907         spin_unlock(&dev->spinlock);
908         return IRQ_HANDLED;
909 }
910
911 // the guts of the interrupt handler, that is shared with das1800_ai_poll
912 static void das1800_ai_handler(comedi_device * dev)
913 {
914         comedi_subdevice *s = dev->subdevices + 0;      /* analog input subdevice */
915         comedi_async *async = s->async;
916         comedi_cmd *cmd = &async->cmd;
917         unsigned int status = inb(dev->iobase + DAS1800_STATUS);
918
919         async->events = 0;
920         // select adc for base address + 0
921         outb(ADC, dev->iobase + DAS1800_SELECT);
922         // dma buffer full
923         if (devpriv->irq_dma_bits & DMA_ENABLED) {
924                 // look for data from dma transfer even if dma terminal count hasn't happened yet
925                 das1800_handle_dma(dev, s, status);
926         } else if (status & FHF) {      // if fifo half full
927                 das1800_handle_fifo_half_full(dev, s);
928         } else if (status & FNE) {      // if fifo not empty
929                 das1800_handle_fifo_not_empty(dev, s);
930         }
931
932         async->events |= COMEDI_CB_BLOCK;
933         /* if the card's fifo has overflowed */
934         if (status & OVF) {
935                 // clear OVF interrupt bit
936                 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
937                 comedi_error(dev, "DAS1800 FIFO overflow");
938                 das1800_cancel(dev, s);
939                 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
940                 comedi_event(dev, s);
941                 return;
942         }
943         // stop taking data if appropriate
944         /* stop_src TRIG_EXT */
945         if (status & CT0TC) {
946                 // clear CT0TC interrupt bit
947                 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
948                 // make sure we get all remaining data from board before quitting
949                 if (devpriv->irq_dma_bits & DMA_ENABLED)
950                         das1800_flush_dma(dev, s);
951                 else
952                         das1800_handle_fifo_not_empty(dev, s);
953                 das1800_cancel(dev, s); /* disable hardware conversions */
954                 async->events |= COMEDI_CB_EOA;
955         } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {        // stop_src TRIG_COUNT
956                 das1800_cancel(dev, s); /* disable hardware conversions */
957                 async->events |= COMEDI_CB_EOA;
958         }
959
960         comedi_event(dev, s);
961
962         return;
963 }
964
965 static void das1800_handle_dma(comedi_device * dev, comedi_subdevice * s,
966         unsigned int status)
967 {
968         unsigned long flags;
969         const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
970
971         flags = claim_dma_lock();
972         das1800_flush_dma_channel(dev, s, devpriv->dma_current,
973                 devpriv->dma_current_buf);
974         // re-enable  dma channel
975         set_dma_addr(devpriv->dma_current,
976                 virt_to_bus(devpriv->dma_current_buf));
977         set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
978         enable_dma(devpriv->dma_current);
979         release_dma_lock(flags);
980
981         if (status & DMATC) {
982                 // clear DMATC interrupt bit
983                 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
984                 // switch dma channels for next time, if appropriate
985                 if (dual_dma) {
986                         // read data from the other channel next time
987                         if (devpriv->dma_current == devpriv->dma0) {
988                                 devpriv->dma_current = devpriv->dma1;
989                                 devpriv->dma_current_buf = devpriv->ai_buf1;
990                         } else {
991                                 devpriv->dma_current = devpriv->dma0;
992                                 devpriv->dma_current_buf = devpriv->ai_buf0;
993                         }
994                 }
995         }
996
997         return;
998 }
999
1000 static inline uint16_t munge_bipolar_sample(const comedi_device * dev,
1001         uint16_t sample)
1002 {
1003         sample += 1 << (thisboard->resolution - 1);
1004         return sample;
1005 }
1006
1007 static void munge_data(comedi_device * dev, uint16_t * array,
1008         unsigned int num_elements)
1009 {
1010         unsigned int i;
1011         int unipolar;
1012
1013         /* see if card is using a unipolar or bipolar range so we can munge data correctly */
1014         unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1015
1016         /* convert to unsigned type if we are in a bipolar mode */
1017         if (!unipolar) {
1018                 for (i = 0; i < num_elements; i++) {
1019                         array[i] = munge_bipolar_sample(dev, array[i]);
1020                 }
1021         }
1022 }
1023
1024 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1025  * Assumes dma lock is held */
1026 static void das1800_flush_dma_channel(comedi_device * dev, comedi_subdevice * s,
1027         unsigned int channel, uint16_t * buffer)
1028 {
1029         unsigned int num_bytes, num_samples;
1030         comedi_cmd *cmd = &s->async->cmd;
1031
1032         disable_dma(channel);
1033
1034         /* clear flip-flop to make sure 2-byte registers
1035          * get set correctly */
1036         clear_dma_ff(channel);
1037
1038         // figure out how many points to read
1039         num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1040         num_samples = num_bytes / sizeof(sampl_t);
1041
1042         /* if we only need some of the points */
1043         if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1044                 num_samples = devpriv->count;
1045
1046         munge_data(dev, buffer, num_samples);
1047         cfc_write_array_to_buffer(s, buffer, num_bytes);
1048         if (s->async->cmd.stop_src == TRIG_COUNT)
1049                 devpriv->count -= num_samples;
1050
1051         return;
1052 }
1053
1054 /* flushes remaining data from board when external trigger has stopped aquisition
1055  * and we are using dma transfers */
1056 static void das1800_flush_dma(comedi_device * dev, comedi_subdevice * s)
1057 {
1058         unsigned long flags;
1059         const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1060
1061         flags = claim_dma_lock();
1062         das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1063                 devpriv->dma_current_buf);
1064
1065         if (dual_dma) {
1066                 // switch to other channel and flush it
1067                 if (devpriv->dma_current == devpriv->dma0) {
1068                         devpriv->dma_current = devpriv->dma1;
1069                         devpriv->dma_current_buf = devpriv->ai_buf1;
1070                 } else {
1071                         devpriv->dma_current = devpriv->dma0;
1072                         devpriv->dma_current_buf = devpriv->ai_buf0;
1073                 }
1074                 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1075                         devpriv->dma_current_buf);
1076         }
1077
1078         release_dma_lock(flags);
1079
1080         // get any remaining samples in fifo
1081         das1800_handle_fifo_not_empty(dev, s);
1082
1083         return;
1084 }
1085
1086 static void das1800_handle_fifo_half_full(comedi_device * dev,
1087         comedi_subdevice * s)
1088 {
1089         int numPoints = 0;      /* number of points to read */
1090         comedi_cmd *cmd = &s->async->cmd;
1091
1092         numPoints = FIFO_SIZE / 2;
1093         /* if we only need some of the points */
1094         if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1095                 numPoints = devpriv->count;
1096         insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1097         munge_data(dev, devpriv->ai_buf0, numPoints);
1098         cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1099                 numPoints * sizeof(devpriv->ai_buf0[0]));
1100         if (cmd->stop_src == TRIG_COUNT)
1101                 devpriv->count -= numPoints;
1102         return;
1103 }
1104
1105 static void das1800_handle_fifo_not_empty(comedi_device * dev,
1106         comedi_subdevice * s)
1107 {
1108         sampl_t dpnt;
1109         int unipolar;
1110         comedi_cmd *cmd = &s->async->cmd;
1111
1112         unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1113
1114         while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1115                 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1116                         break;
1117                 dpnt = inw(dev->iobase + DAS1800_FIFO);
1118                 /* convert to unsigned type if we are in a bipolar mode */
1119                 if (!unipolar) ;
1120                 dpnt = munge_bipolar_sample(dev, dpnt);
1121                 cfc_write_to_buffer(s, dpnt);
1122                 if (cmd->stop_src == TRIG_COUNT)
1123                         devpriv->count--;
1124         }
1125
1126         return;
1127 }
1128
1129 static int das1800_cancel(comedi_device * dev, comedi_subdevice * s)
1130 {
1131         outb(0x0, dev->iobase + DAS1800_STATUS);        /* disable conversions */
1132         outb(0x0, dev->iobase + DAS1800_CONTROL_B);     /* disable interrupts and dma */
1133         outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* disable and clear fifo and stop triggering */
1134         if (devpriv->dma0)
1135                 disable_dma(devpriv->dma0);
1136         if (devpriv->dma1)
1137                 disable_dma(devpriv->dma1);
1138         return 0;
1139 }
1140
1141 /* test analog input cmd */
1142 static int das1800_ai_do_cmdtest(comedi_device * dev, comedi_subdevice * s,
1143         comedi_cmd * cmd)
1144 {
1145         int err = 0;
1146         int tmp;
1147         unsigned int tmp_arg;
1148         int i;
1149         int unipolar;
1150
1151         /* step 1: make sure trigger sources are trivially valid */
1152
1153         tmp = cmd->start_src;
1154         cmd->start_src &= TRIG_NOW | TRIG_EXT;
1155         if (!cmd->start_src || tmp != cmd->start_src)
1156                 err++;
1157
1158         tmp = cmd->scan_begin_src;
1159         cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1160         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1161                 err++;
1162
1163         tmp = cmd->convert_src;
1164         cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1165         if (!cmd->convert_src || tmp != cmd->convert_src)
1166                 err++;
1167
1168         tmp = cmd->scan_end_src;
1169         cmd->scan_end_src &= TRIG_COUNT;
1170         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1171                 err++;
1172
1173         tmp = cmd->stop_src;
1174         cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1175         if (!cmd->stop_src || tmp != cmd->stop_src)
1176                 err++;
1177
1178         if (err)
1179                 return 1;
1180
1181         /* step 2: make sure trigger sources are unique and mutually compatible */
1182
1183         // uniqueness check
1184         if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1185                 err++;
1186         if (cmd->scan_begin_src != TRIG_FOLLOW &&
1187                 cmd->scan_begin_src != TRIG_TIMER &&
1188                 cmd->scan_begin_src != TRIG_EXT)
1189                 err++;
1190         if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1191                 err++;
1192         if (cmd->stop_src != TRIG_COUNT &&
1193                 cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1194                 err++;
1195         //compatibility check
1196         if (cmd->scan_begin_src != TRIG_FOLLOW &&
1197                 cmd->convert_src != TRIG_TIMER)
1198                 err++;
1199
1200         if (err)
1201                 return 2;
1202
1203         /* step 3: make sure arguments are trivially compatible */
1204
1205         if (cmd->start_arg != 0) {
1206                 cmd->start_arg = 0;
1207                 err++;
1208         }
1209         if (cmd->convert_src == TRIG_TIMER) {
1210                 if (cmd->convert_arg < thisboard->ai_speed) {
1211                         cmd->convert_arg = thisboard->ai_speed;
1212                         err++;
1213                 }
1214         }
1215         if (!cmd->chanlist_len) {
1216                 cmd->chanlist_len = 1;
1217                 err++;
1218         }
1219         if (cmd->scan_end_arg != cmd->chanlist_len) {
1220                 cmd->scan_end_arg = cmd->chanlist_len;
1221                 err++;
1222         }
1223
1224         switch (cmd->stop_src) {
1225         case TRIG_COUNT:
1226                 if (!cmd->stop_arg) {
1227                         cmd->stop_arg = 1;
1228                         err++;
1229                 }
1230                 break;
1231         case TRIG_NONE:
1232                 if (cmd->stop_arg != 0) {
1233                         cmd->stop_arg = 0;
1234                         err++;
1235                 }
1236                 break;
1237         default:
1238                 break;
1239         }
1240
1241         if (err)
1242                 return 3;
1243
1244         /* step 4: fix up any arguments */
1245
1246         if (cmd->convert_src == TRIG_TIMER) {
1247                 // if we are not in burst mode
1248                 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1249                         tmp_arg = cmd->convert_arg;
1250                         /* calculate counter values that give desired timing */
1251                         i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1252                                 &(devpriv->divisor1), &(devpriv->divisor2),
1253                                 &(cmd->convert_arg),
1254                                 cmd->flags & TRIG_ROUND_MASK);
1255                         if (tmp_arg != cmd->convert_arg)
1256                                 err++;
1257                 }
1258                 // if we are in burst mode
1259                 else {
1260                         // check that convert_arg is compatible
1261                         tmp_arg = cmd->convert_arg;
1262                         cmd->convert_arg =
1263                                 burst_convert_arg(cmd->convert_arg,
1264                                 cmd->flags & TRIG_ROUND_MASK);
1265                         if (tmp_arg != cmd->convert_arg)
1266                                 err++;
1267
1268                         if (cmd->scan_begin_src == TRIG_TIMER) {
1269                                 // if scans are timed faster than conversion rate allows
1270                                 if (cmd->convert_arg * cmd->chanlist_len >
1271                                         cmd->scan_begin_arg) {
1272                                         cmd->scan_begin_arg =
1273                                                 cmd->convert_arg *
1274                                                 cmd->chanlist_len;
1275                                         err++;
1276                                 }
1277                                 tmp_arg = cmd->scan_begin_arg;
1278                                 /* calculate counter values that give desired timing */
1279                                 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1280                                         &(devpriv->divisor1),
1281                                         &(devpriv->divisor2),
1282                                         &(cmd->scan_begin_arg),
1283                                         cmd->flags & TRIG_ROUND_MASK);
1284                                 if (tmp_arg != cmd->scan_begin_arg)
1285                                         err++;
1286                         }
1287                 }
1288         }
1289
1290         if (err)
1291                 return 4;
1292
1293         // make sure user is not trying to mix unipolar and bipolar ranges
1294         if (cmd->chanlist) {
1295                 unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1296                 for (i = 1; i < cmd->chanlist_len; i++) {
1297                         if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1298                                 comedi_error(dev,
1299                                         "unipolar and bipolar ranges cannot be mixed in the chanlist");
1300                                 err++;
1301                                 break;
1302                         }
1303                 }
1304         }
1305
1306         if (err)
1307                 return 5;
1308
1309         return 0;
1310 }
1311
1312 /* analog input cmd interface */
1313
1314 // first, some utility functions used in the main ai_do_cmd()
1315
1316 // returns appropriate bits for control register a, depending on command
1317 static int control_a_bits(comedi_cmd cmd)
1318 {
1319         int control_a;
1320
1321         control_a = FFEN;       //enable fifo
1322         if (cmd.stop_src == TRIG_EXT) {
1323                 control_a |= ATEN;
1324         }
1325         switch (cmd.start_src) {
1326         case TRIG_EXT:
1327                 control_a |= TGEN | CGSL;
1328                 break;
1329         case TRIG_NOW:
1330                 control_a |= CGEN;
1331                 break;
1332         default:
1333                 break;
1334         }
1335
1336         return control_a;
1337 }
1338
1339 // returns appropriate bits for control register c, depending on command
1340 static int control_c_bits(comedi_cmd cmd)
1341 {
1342         int control_c;
1343         int aref;
1344
1345         /* set clock source to internal or external, select analog reference,
1346          * select unipolar / bipolar
1347          */
1348         aref = CR_AREF(cmd.chanlist[0]);
1349         control_c = UQEN;       //enable upper qram addresses
1350         if (aref != AREF_DIFF)
1351                 control_c |= SD;
1352         if (aref == AREF_COMMON)
1353                 control_c |= CMEN;
1354         /* if a unipolar range was selected */
1355         if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1356                 control_c |= UB;
1357         switch (cmd.scan_begin_src) {
1358         case TRIG_FOLLOW:       // not in burst mode
1359                 switch (cmd.convert_src) {
1360                 case TRIG_TIMER:
1361                         /* trig on cascaded counters */
1362                         control_c |= IPCLK;
1363                         break;
1364                 case TRIG_EXT:
1365                         /* trig on falling edge of external trigger */
1366                         control_c |= XPCLK;
1367                         break;
1368                 default:
1369                         break;
1370                 }
1371                 break;
1372         case TRIG_TIMER:
1373                 // burst mode with internal pacer clock
1374                 control_c |= BMDE | IPCLK;
1375                 break;
1376         case TRIG_EXT:
1377                 // burst mode with external trigger
1378                 control_c |= BMDE | XPCLK;
1379                 break;
1380         default:
1381                 break;
1382         }
1383
1384         return control_c;
1385 }
1386
1387 // sets up counters
1388 static int setup_counters(comedi_device * dev, comedi_cmd cmd)
1389 {
1390         // setup cascaded counters for conversion/scan frequency
1391         switch (cmd.scan_begin_src) {
1392         case TRIG_FOLLOW:       // not in burst mode
1393                 if (cmd.convert_src == TRIG_TIMER) {
1394                         /* set conversion frequency */
1395                         i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1396                                 &(devpriv->divisor1), &(devpriv->divisor2),
1397                                 &(cmd.convert_arg),
1398                                 cmd.flags & TRIG_ROUND_MASK);
1399                         if (das1800_set_frequency(dev) < 0) {
1400                                 return -1;
1401                         }
1402                 }
1403                 break;
1404         case TRIG_TIMER:        // in burst mode
1405                 /* set scan frequency */
1406                 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1407                         &(devpriv->divisor2), &(cmd.scan_begin_arg),
1408                         cmd.flags & TRIG_ROUND_MASK);
1409                 if (das1800_set_frequency(dev) < 0) {
1410                         return -1;
1411                 }
1412                 break;
1413         default:
1414                 break;
1415         }
1416
1417         // setup counter 0 for 'about triggering'
1418         if (cmd.stop_src == TRIG_EXT) {
1419                 // load counter 0 in mode 0
1420                 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1421         }
1422
1423         return 0;
1424 }
1425
1426 // sets up dma
1427 static void setup_dma(comedi_device * dev, comedi_cmd cmd)
1428 {
1429         unsigned long lock_flags;
1430         const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1431
1432         if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1433                 return;
1434
1435         /* determine a reasonable dma transfer size */
1436         devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1437         lock_flags = claim_dma_lock();
1438         disable_dma(devpriv->dma0);
1439         /* clear flip-flop to make sure 2-byte registers for
1440          * count and address get set correctly */
1441         clear_dma_ff(devpriv->dma0);
1442         set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1443         // set appropriate size of transfer
1444         set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1445         devpriv->dma_current = devpriv->dma0;
1446         devpriv->dma_current_buf = devpriv->ai_buf0;
1447         enable_dma(devpriv->dma0);
1448         // set up dual dma if appropriate
1449         if (dual_dma) {
1450                 disable_dma(devpriv->dma1);
1451                 /* clear flip-flop to make sure 2-byte registers for
1452                  * count and address get set correctly */
1453                 clear_dma_ff(devpriv->dma1);
1454                 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1455                 // set appropriate size of transfer
1456                 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1457                 enable_dma(devpriv->dma1);
1458         }
1459         release_dma_lock(lock_flags);
1460
1461         return;
1462 }
1463
1464 // programs channel/gain list into card
1465 static void program_chanlist(comedi_device * dev, comedi_cmd cmd)
1466 {
1467         int i, n, chan_range;
1468         unsigned long irq_flags;
1469         const int range_mask = 0x3;     //masks unipolar/bipolar bit off range
1470         const int range_bitshift = 8;
1471
1472         n = cmd.chanlist_len;
1473         // spinlock protects indirect addressing
1474         comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1475         outb(QRAM, dev->iobase + DAS1800_SELECT);       /* select QRAM for baseAddress + 0x0 */
1476         outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);        /*set QRAM address start */
1477         /* make channel / gain list */
1478         for (i = 0; i < n; i++) {
1479                 chan_range =
1480                         CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd.
1481                                         chanlist[i]) & range_mask) <<
1482                         range_bitshift);
1483                 outw(chan_range, dev->iobase + DAS1800_QRAM);
1484         }
1485         outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);        /*finish write to QRAM */
1486         comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1487
1488         return;
1489 }
1490
1491 // analog input do_cmd
1492 static int das1800_ai_do_cmd(comedi_device * dev, comedi_subdevice * s)
1493 {
1494         int ret;
1495         int control_a, control_c;
1496         comedi_async *async = s->async;
1497         comedi_cmd cmd = async->cmd;
1498
1499         if (!dev->irq) {
1500                 comedi_error(dev,
1501                         "no irq assigned for das-1800, cannot do hardware conversions");
1502                 return -1;
1503         }
1504
1505         /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1506          * (because dma in handler is unsafe at hard real-time priority) */
1507         if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1508                 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1509         } else {
1510                 devpriv->irq_dma_bits |= devpriv->dma_bits;
1511         }
1512         // interrupt on end of conversion for TRIG_WAKE_EOS
1513         if (cmd.flags & TRIG_WAKE_EOS) {
1514                 // interrupt fifo not empty
1515                 devpriv->irq_dma_bits &= ~FIMD;
1516         } else {
1517                 // interrupt fifo half full
1518                 devpriv->irq_dma_bits |= FIMD;
1519         }
1520         // determine how many conversions we need
1521         if (cmd.stop_src == TRIG_COUNT) {
1522                 devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1523         }
1524
1525         das1800_cancel(dev, s);
1526
1527         // determine proper bits for control registers
1528         control_a = control_a_bits(cmd);
1529         control_c = control_c_bits(cmd);
1530
1531         /* setup card and start */
1532         program_chanlist(dev, cmd);
1533         ret = setup_counters(dev, cmd);
1534         if (ret < 0) {
1535                 comedi_error(dev, "Error setting up counters");
1536                 return ret;
1537         }
1538         setup_dma(dev, cmd);
1539         outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1540         // set conversion rate and length for burst mode
1541         if (control_c & BMDE) {
1542                 // program conversion period with number of microseconds minus 1
1543                 outb(cmd.convert_arg / 1000 - 1,
1544                         dev->iobase + DAS1800_BURST_RATE);
1545                 outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1546         }
1547         outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);   // enable irq/dma
1548         outb(control_a, dev->iobase + DAS1800_CONTROL_A);       /* enable fifo and triggering */
1549         outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
1550
1551         return 0;
1552 }
1553
1554 /* read analog input */
1555 static int das1800_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
1556         comedi_insn * insn, lsampl_t * data)
1557 {
1558         int i, n;
1559         int chan, range, aref, chan_range;
1560         int timeout = 1000;
1561         short dpnt;
1562         int conv_flags = 0;
1563         unsigned long irq_flags;
1564
1565         /* set up analog reference and unipolar / bipolar mode */
1566         aref = CR_AREF(insn->chanspec);
1567         conv_flags |= UQEN;
1568         if (aref != AREF_DIFF)
1569                 conv_flags |= SD;
1570         if (aref == AREF_COMMON)
1571                 conv_flags |= CMEN;
1572         /* if a unipolar range was selected */
1573         if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1574                 conv_flags |= UB;
1575
1576         outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);      /* software conversion enabled */
1577         outb(CVEN, dev->iobase + DAS1800_STATUS);       /* enable conversions */
1578         outb(0x0, dev->iobase + DAS1800_CONTROL_A);     /* reset fifo */
1579         outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1580
1581         chan = CR_CHAN(insn->chanspec);
1582         /* mask of unipolar/bipolar bit from range */
1583         range = CR_RANGE(insn->chanspec) & 0x3;
1584         chan_range = chan | (range << 8);
1585         comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1586         outb(QRAM, dev->iobase + DAS1800_SELECT);       /* select QRAM for baseAddress + 0x0 */
1587         outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);  /* set QRAM address start */
1588         outw(chan_range, dev->iobase + DAS1800_QRAM);
1589         outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);  /*finish write to QRAM */
1590         outb(ADC, dev->iobase + DAS1800_SELECT);        /* select ADC for baseAddress + 0x0 */
1591
1592         for (n = 0; n < insn->n; n++) {
1593                 /* trigger conversion */
1594                 outb(0, dev->iobase + DAS1800_FIFO);
1595                 for (i = 0; i < timeout; i++) {
1596                         if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1597                                 break;
1598                 }
1599                 if (i == timeout) {
1600                         comedi_error(dev, "timeout");
1601                         return -ETIME;
1602                 }
1603                 dpnt = inw(dev->iobase + DAS1800_FIFO);
1604                 /* shift data to offset binary for bipolar ranges */
1605                 if ((conv_flags & UB) == 0)
1606                         dpnt += 1 << (thisboard->resolution - 1);
1607                 data[n] = dpnt;
1608         }
1609         comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1610
1611         return n;
1612 }
1613
1614 /* writes to an analog output channel */
1615 static int das1800_ao_winsn(comedi_device * dev, comedi_subdevice * s,
1616         comedi_insn * insn, lsampl_t * data)
1617 {
1618         int chan = CR_CHAN(insn->chanspec);
1619 //      int range = CR_RANGE(insn->chanspec);
1620         int update_chan = thisboard->ao_n_chan - 1;
1621         short output;
1622         unsigned long irq_flags;
1623
1624         if (insn->n == 0)
1625                 return 0;
1626
1627         //  card expects two's complement data
1628         output = data[0] - (1 << (thisboard->resolution - 1));
1629         // if the write is to the 'update' channel, we need to remember its value
1630         if (chan == update_chan)
1631                 devpriv->ao_update_bits = output;
1632         // write to channel
1633         comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1634         outb(DAC(chan), dev->iobase + DAS1800_SELECT);  /* select dac channel for baseAddress + 0x0 */
1635         outw(output, dev->iobase + DAS1800_DAC);
1636         // now we need to write to 'update' channel to update all dac channels
1637         if (chan != update_chan) {
1638                 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);   /* select 'update' channel for baseAddress + 0x0 */
1639                 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1640         }
1641         comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1642
1643         return 1;
1644 }
1645
1646 /* reads from digital input channels */
1647 static int das1800_di_rbits(comedi_device * dev, comedi_subdevice * s,
1648         comedi_insn * insn, lsampl_t * data)
1649 {
1650
1651         data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1652         data[0] = 0;
1653
1654         return 2;
1655 }
1656
1657 /* writes to digital output channels */
1658 static int das1800_do_wbits(comedi_device * dev, comedi_subdevice * s,
1659         comedi_insn * insn, lsampl_t * data)
1660 {
1661         lsampl_t wbits;
1662
1663         // only set bits that have been masked
1664         data[0] &= (1 << s->n_chan) - 1;
1665         wbits = devpriv->do_bits;
1666         wbits &= ~data[0];
1667         wbits |= data[0] & data[1];
1668         devpriv->do_bits = wbits;
1669
1670         outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1671
1672         data[1] = devpriv->do_bits;
1673
1674         return 2;
1675 }
1676
1677 /* loads counters with divisor1, divisor2 from private structure */
1678 static int das1800_set_frequency(comedi_device * dev)
1679 {
1680         int err = 0;
1681
1682         // counter 1, mode 2
1683         if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1684                         2))
1685                 err++;
1686         // counter 2, mode 2
1687         if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1688                         2))
1689                 err++;
1690         if (err)
1691                 return -1;
1692
1693         return 0;
1694 }
1695
1696 /* converts requested conversion timing to timing compatible with
1697  * hardware, used only when card is in 'burst mode'
1698  */
1699 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1700 {
1701         unsigned int micro_sec;
1702
1703         // in burst mode, the maximum conversion time is 64 microseconds
1704         if (convert_arg > 64000)
1705                 convert_arg = 64000;
1706
1707         // the conversion time must be an integral number of microseconds
1708         switch (round_mode) {
1709         case TRIG_ROUND_NEAREST:
1710         default:
1711                 micro_sec = (convert_arg + 500) / 1000;
1712                 break;
1713         case TRIG_ROUND_DOWN:
1714                 micro_sec = convert_arg / 1000;
1715                 break;
1716         case TRIG_ROUND_UP:
1717                 micro_sec = (convert_arg - 1) / 1000 + 1;
1718                 break;
1719         }
1720
1721         // return number of nanoseconds
1722         return micro_sec * 1000;
1723 }
1724
1725 // utility function that suggests a dma transfer size based on the conversion period 'ns'
1726 static unsigned int suggest_transfer_size(comedi_cmd * cmd)
1727 {
1728         unsigned int size = DMA_BUF_SIZE;
1729         static const int sample_size = 2;       // size in bytes of one sample from board
1730         unsigned int fill_time = 300000000;     // target time in nanoseconds for filling dma buffer
1731         unsigned int max_size;  // maximum size we will allow for a transfer
1732
1733         // make dma buffer fill in 0.3 seconds for timed modes
1734         switch (cmd->scan_begin_src) {
1735         case TRIG_FOLLOW:       // not in burst mode
1736                 if (cmd->convert_src == TRIG_TIMER)
1737                         size = (fill_time / cmd->convert_arg) * sample_size;
1738                 break;
1739         case TRIG_TIMER:
1740                 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1741                         sample_size;
1742                 break;
1743         default:
1744                 size = DMA_BUF_SIZE;
1745                 break;
1746         }
1747
1748         // set a minimum and maximum size allowed
1749         max_size = DMA_BUF_SIZE;
1750         // if we are taking limited number of conversions, limit transfer size to that
1751         if (cmd->stop_src == TRIG_COUNT &&
1752                 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1753                 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1754
1755         if (size > max_size)
1756                 size = max_size;
1757         if (size < sample_size)
1758                 size = sample_size;
1759
1760         return size;
1761 }