Merge branch 'for-3.11' of git://linux-nfs.org/~bfields/linux
[linux-2.6.git] / drivers / staging / comedi / drivers / das16.c
blobdbec3ba995487553ee558ceabb7ed47fe356ab94
1 /*
2 comedi/drivers/das16.c
3 DAS16 driver
5 COMEDI - Linux Control and Measurement Device Interface
6 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 Copyright (C) 2000 Chris R. Baugher <baugher@enteract.com>
8 Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 2 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
21 Driver: das16
22 Description: DAS16 compatible boards
23 Author: Sam Moore, Warren Jasper, ds, Chris Baugher, Frank Hess, Roman Fietze
24 Devices: [Keithley Metrabyte] DAS-16 (das-16), DAS-16G (das-16g),
25 DAS-16F (das-16f), DAS-1201 (das-1201), DAS-1202 (das-1202),
26 DAS-1401 (das-1401), DAS-1402 (das-1402), DAS-1601 (das-1601),
27 DAS-1602 (das-1602),
28 [ComputerBoards] PC104-DAS16/JR (pc104-das16jr),
29 PC104-DAS16JR/16 (pc104-das16jr/16),
30 CIO-DAS16JR/16 (cio-das16jr/16),
31 CIO-DAS16/JR (cio-das16/jr), CIO-DAS1401/12 (cio-das1401/12),
32 CIO-DAS1402/12 (cio-das1402/12), CIO-DAS1402/16 (cio-das1402/16),
33 CIO-DAS1601/12 (cio-das1601/12), CIO-DAS1602/12 (cio-das1602/12),
34 CIO-DAS1602/16 (cio-das1602/16), CIO-DAS16/330 (cio-das16/330)
35 Status: works
36 Updated: 2003-10-12
38 A rewrite of the das16 and das1600 drivers.
39 Options:
40 [0] - base io address
41 [1] - irq (does nothing, irq is not used anymore)
42 [2] - dma (optional, required for comedi_command support)
43 [3] - master clock speed in MHz (optional, 1 or 10, ignored if
44 board can probe clock, defaults to 1)
45 [4] - analog input range lowest voltage in microvolts (optional,
46 only useful if your board does not have software
47 programmable gain)
48 [5] - analog input range highest voltage in microvolts (optional,
49 only useful if board does not have software programmable
50 gain)
51 [6] - analog output range lowest voltage in microvolts (optional)
52 [7] - analog output range highest voltage in microvolts (optional)
53 [8] - use timer mode for DMA. Timer mode is needed e.g. for
54 buggy DMA controllers in NS CS5530A (Geode Companion), and for
55 'jr' cards that lack a hardware fifo. This option is no
56 longer needed, since timer mode is _always_ used.
58 Passing a zero for an option is the same as leaving it unspecified.
63 Testing and debugging help provided by Daniel Koch.
65 Keithley Manuals:
66 2309.PDF (das16)
67 4919.PDF (das1400, 1600)
68 4922.PDF (das-1400)
69 4923.PDF (das1200, 1400, 1600)
71 Computer boards manuals also available from their website
72 www.measurementcomputing.com
76 #include <linux/pci.h>
77 #include <linux/slab.h>
78 #include <linux/interrupt.h>
80 #include <asm/dma.h>
82 #include "../comedidev.h"
84 #include "8253.h"
85 #include "8255.h"
86 #include "comedi_fc.h"
88 #undef DEBUG
89 /* #define DEBUG */
91 #ifdef DEBUG
92 #define DEBUG_PRINT(format, args...) \
93 printk(KERN_DEBUG "das16: " format, ## args)
94 #else
95 #define DEBUG_PRINT(format, args...)
96 #endif
98 #define DAS16_SIZE 20 /* number of ioports */
99 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
102 cio-das16.pdf
104 "das16"
105 "das16/f"
107 0 a/d bits 0-3 start 12 bit
108 1 a/d bits 4-11 unused
109 2 mux read mux set
110 3 di 4 bit do 4 bit
111 4 unused ao0_lsb
112 5 unused ao0_msb
113 6 unused ao1_lsb
114 7 unused ao1_msb
115 8 status eoc uni/bip interrupt reset
116 9 dma, int, trig ctrl set dma, int
117 a pacer control unused
118 b reserved reserved
119 cdef 8254
120 0123 8255
125 cio-das16jr.pdf
127 "das16jr"
129 0 a/d bits 0-3 start 12 bit
130 1 a/d bits 4-11 unused
131 2 mux read mux set
132 3 di 4 bit do 4 bit
133 4567 unused unused
134 8 status eoc uni/bip interrupt reset
135 9 dma, int, trig ctrl set dma, int
136 a pacer control unused
137 b gain status gain control
138 cdef 8254
143 cio-das16jr_16.pdf
145 "das16jr_16"
147 0 a/d bits 0-7 start 16 bit
148 1 a/d bits 8-15 unused
149 2 mux read mux set
150 3 di 4 bit do 4 bit
151 4567 unused unused
152 8 status eoc uni/bip interrupt reset
153 9 dma, int, trig ctrl set dma, int
154 a pacer control unused
155 b gain status gain control
156 cdef 8254
160 cio-das160x-1x.pdf
162 "das1601/12"
163 "das1602/12"
164 "das1602/16"
166 0 a/d bits 0-3 start 12 bit
167 1 a/d bits 4-11 unused
168 2 mux read mux set
169 3 di 4 bit do 4 bit
170 4 unused ao0_lsb
171 5 unused ao0_msb
172 6 unused ao1_lsb
173 7 unused ao1_msb
174 8 status eoc uni/bip interrupt reset
175 9 dma, int, trig ctrl set dma, int
176 a pacer control unused
177 b gain status gain control
178 cdef 8254
179 400 8255
180 404 unused conversion enable
181 405 unused burst enable
182 406 unused das1600 enable
183 407 status
187 /* size in bytes of a sample from board */
188 static const int sample_size = 2;
190 #define DAS16_TRIG 0
191 #define DAS16_AI_LSB 0
192 #define DAS16_AI_MSB 1
193 #define DAS16_MUX 2
194 #define DAS16_DIO 3
195 #define DAS16_AO_LSB(x) ((x) ? 6 : 4)
196 #define DAS16_AO_MSB(x) ((x) ? 7 : 5)
197 #define DAS16_STATUS 8
198 #define BUSY (1<<7)
199 #define UNIPOLAR (1<<6)
200 #define DAS16_MUXBIT (1<<5)
201 #define DAS16_INT (1<<4)
202 #define DAS16_CONTROL 9
203 #define DAS16_INTE (1<<7)
204 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
205 #define DMA_ENABLE (1<<2)
206 #define PACING_MASK 0x3
207 #define INT_PACER 0x03
208 #define EXT_PACER 0x02
209 #define DAS16_SOFT 0x00
210 #define DAS16_PACER 0x0A
211 #define DAS16_CTR0 (1<<1)
212 #define DAS16_TRIG0 (1<<0)
213 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
214 #define DAS16_GAIN 0x0B
215 #define DAS16_CNTR0_DATA 0x0C
216 #define DAS16_CNTR1_DATA 0x0D
217 #define DAS16_CNTR2_DATA 0x0E
218 #define DAS16_CNTR_CONTROL 0x0F
219 #define DAS16_TERM_CNT 0x00
220 #define DAS16_ONE_SHOT 0x02
221 #define DAS16_RATE_GEN 0x04
222 #define DAS16_CNTR_LSB_MSB 0x30
223 #define DAS16_CNTR0 0x00
224 #define DAS16_CNTR1 0x40
225 #define DAS16_CNTR2 0x80
227 #define DAS1600_CONV 0x404
228 #define DAS1600_CONV_DISABLE 0x40
229 #define DAS1600_BURST 0x405
230 #define DAS1600_BURST_VAL 0x40
231 #define DAS1600_ENABLE 0x406
232 #define DAS1600_ENABLE_VAL 0x40
233 #define DAS1600_STATUS_B 0x407
234 #define DAS1600_BME 0x40
235 #define DAS1600_ME 0x20
236 #define DAS1600_CD 0x10
237 #define DAS1600_WS 0x02
238 #define DAS1600_CLK_10MHZ 0x01
240 static const struct comedi_lrange range_das1x01_bip = { 4, {
241 BIP_RANGE(10),
242 BIP_RANGE(1),
243 BIP_RANGE(0.1),
244 BIP_RANGE(0.01),
248 static const struct comedi_lrange range_das1x01_unip = { 4, {
249 UNI_RANGE(10),
250 UNI_RANGE(1),
251 UNI_RANGE(0.1),
252 UNI_RANGE(0.01),
256 static const struct comedi_lrange range_das1x02_bip = { 4, {
257 BIP_RANGE(10),
258 BIP_RANGE(5),
259 BIP_RANGE(2.5),
260 BIP_RANGE(1.25),
264 static const struct comedi_lrange range_das1x02_unip = { 4, {
265 UNI_RANGE(10),
266 UNI_RANGE(5),
267 UNI_RANGE(2.5),
268 UNI_RANGE(1.25),
272 static const struct comedi_lrange range_das16jr = { 9, {
273 /* also used by 16/330 */
274 BIP_RANGE(10),
275 BIP_RANGE(5),
276 BIP_RANGE(2.5),
277 BIP_RANGE(1.25),
278 BIP_RANGE(0.625),
279 UNI_RANGE(10),
280 UNI_RANGE(5),
281 UNI_RANGE(2.5),
282 UNI_RANGE(1.25),
286 static const struct comedi_lrange range_das16jr_16 = { 8, {
287 BIP_RANGE(10),
288 BIP_RANGE(5),
289 BIP_RANGE(2.5),
290 BIP_RANGE(1.25),
291 UNI_RANGE(10),
292 UNI_RANGE(5),
293 UNI_RANGE(2.5),
294 UNI_RANGE(1.25),
298 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
299 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
300 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
302 enum {
303 das16_pg_none = 0,
304 das16_pg_16jr,
305 das16_pg_16jr_16,
306 das16_pg_1601,
307 das16_pg_1602,
309 static const int *const das16_gainlists[] = {
310 NULL,
311 das16jr_gainlist,
312 das16jr_16_gainlist,
313 das1600_gainlist,
314 das1600_gainlist,
317 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
318 &range_unknown,
319 &range_das16jr,
320 &range_das16jr_16,
321 &range_das1x01_unip,
322 &range_das1x02_unip,
325 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
326 &range_unknown,
327 &range_das16jr,
328 &range_das16jr_16,
329 &range_das1x01_bip,
330 &range_das1x02_bip,
333 struct munge_info {
334 uint8_t byte;
335 unsigned have_byte:1;
338 struct das16_board {
339 const char *name;
340 void *ai;
341 unsigned int ai_nbits;
342 unsigned int ai_speed; /* max conversion speed in nanosec */
343 unsigned int ai_pg;
344 void *ao;
345 unsigned int ao_nbits;
346 void *di;
347 void *do_;
349 unsigned int i8255_offset;
350 unsigned int i8254_offset;
352 unsigned int size;
353 unsigned int id;
356 #define DAS16_TIMEOUT 1000
358 /* Period for timer interrupt in jiffies. It's a function
359 * to deal with possibility of dynamic HZ patches */
360 static inline int timer_period(void)
362 return HZ / 20;
365 struct das16_private_struct {
366 unsigned int ai_unipolar; /* unipolar flag */
367 unsigned int ai_singleended; /* single ended flag */
368 unsigned int clockbase; /* master clock speed in ns */
369 volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
370 volatile unsigned long adc_byte_count; /* number of bytes remaining */
371 /* divisor dividing master clock to get conversion frequency */
372 unsigned int divisor1;
373 /* divisor dividing master clock to get conversion frequency */
374 unsigned int divisor2;
375 unsigned int dma_chan; /* dma channel */
376 uint16_t *dma_buffer[2];
377 dma_addr_t dma_buffer_addr[2];
378 unsigned int current_buffer;
379 volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
381 * user-defined analog input and output ranges
382 * defined from config options
384 struct comedi_lrange *user_ai_range_table;
385 struct comedi_lrange *user_ao_range_table;
387 struct timer_list timer; /* for timed interrupt */
388 volatile short timer_running;
389 volatile short timer_mode; /* true if using timer mode */
391 unsigned long extra_iobase;
394 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
395 struct comedi_cmd *cmd)
397 const struct das16_board *board = comedi_board(dev);
398 struct das16_private_struct *devpriv = dev->private;
399 int err = 0, tmp;
400 int gain, start_chan, i;
401 int mask;
403 /* Step 1 : check if triggers are trivially valid */
405 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
407 mask = TRIG_FOLLOW;
408 /* if board supports burst mode */
409 if (board->size > 0x400)
410 mask |= TRIG_TIMER | TRIG_EXT;
411 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
413 tmp = cmd->convert_src;
414 mask = TRIG_TIMER | TRIG_EXT;
415 /* if board supports burst mode */
416 if (board->size > 0x400)
417 mask |= TRIG_NOW;
418 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
420 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
421 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
423 if (err)
424 return 1;
426 /* Step 2a : make sure trigger sources are unique */
428 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
429 err |= cfc_check_trigger_is_unique(cmd->convert_src);
430 err |= cfc_check_trigger_is_unique(cmd->stop_src);
432 /* Step 2b : and mutually compatible */
434 /* make sure scan_begin_src and convert_src dont conflict */
435 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
436 err |= -EINVAL;
437 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
438 err |= -EINVAL;
440 if (err)
441 return 2;
443 /* Step 3: check if arguments are trivially valid */
445 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
447 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
448 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
450 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
452 /* check against maximum frequency */
453 if (cmd->scan_begin_src == TRIG_TIMER)
454 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
455 board->ai_speed * cmd->chanlist_len);
457 if (cmd->convert_src == TRIG_TIMER)
458 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
459 board->ai_speed);
461 if (cmd->stop_src == TRIG_NONE)
462 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
464 if (err)
465 return 3;
467 /* step 4: fix up arguments */
468 if (cmd->scan_begin_src == TRIG_TIMER) {
469 unsigned int tmp = cmd->scan_begin_arg;
470 /* set divisors, correct timing arguments */
471 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
472 &(devpriv->divisor1),
473 &(devpriv->divisor2),
474 &(cmd->scan_begin_arg),
475 cmd->flags & TRIG_ROUND_MASK);
476 err += (tmp != cmd->scan_begin_arg);
478 if (cmd->convert_src == TRIG_TIMER) {
479 unsigned int tmp = cmd->convert_arg;
480 /* set divisors, correct timing arguments */
481 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
482 &(devpriv->divisor1),
483 &(devpriv->divisor2),
484 &(cmd->convert_arg),
485 cmd->flags & TRIG_ROUND_MASK);
486 err += (tmp != cmd->convert_arg);
488 if (err)
489 return 4;
491 /* check channel/gain list against card's limitations */
492 if (cmd->chanlist) {
493 gain = CR_RANGE(cmd->chanlist[0]);
494 start_chan = CR_CHAN(cmd->chanlist[0]);
495 for (i = 1; i < cmd->chanlist_len; i++) {
496 if (CR_CHAN(cmd->chanlist[i]) !=
497 (start_chan + i) % s->n_chan) {
498 comedi_error(dev,
499 "entries in chanlist must be "
500 "consecutive channels, "
501 "counting upwards\n");
502 err++;
504 if (CR_RANGE(cmd->chanlist[i]) != gain) {
505 comedi_error(dev,
506 "entries in chanlist must all "
507 "have the same gain\n");
508 err++;
512 if (err)
513 return 5;
515 return 0;
518 /* utility function that suggests a dma transfer size in bytes */
519 static unsigned int das16_suggest_transfer_size(struct comedi_device *dev,
520 const struct comedi_cmd *cmd)
522 struct das16_private_struct *devpriv = dev->private;
523 unsigned int size;
524 unsigned int freq;
526 /* if we are using timer interrupt, we don't care how long it
527 * will take to complete transfer since it will be interrupted
528 * by timer interrupt */
529 if (devpriv->timer_mode)
530 return DAS16_DMA_SIZE;
532 /* otherwise, we are relying on dma terminal count interrupt,
533 * so pick a reasonable size */
534 if (cmd->convert_src == TRIG_TIMER)
535 freq = 1000000000 / cmd->convert_arg;
536 else if (cmd->scan_begin_src == TRIG_TIMER)
537 freq = (1000000000 / cmd->scan_begin_arg) * cmd->chanlist_len;
538 /* return some default value */
539 else
540 freq = 0xffffffff;
542 if (cmd->flags & TRIG_WAKE_EOS) {
543 size = sample_size * cmd->chanlist_len;
544 } else {
545 /* make buffer fill in no more than 1/3 second */
546 size = (freq / 3) * sample_size;
549 /* set a minimum and maximum size allowed */
550 if (size > DAS16_DMA_SIZE)
551 size = DAS16_DMA_SIZE - DAS16_DMA_SIZE % sample_size;
552 else if (size < sample_size)
553 size = sample_size;
555 if (cmd->stop_src == TRIG_COUNT && size > devpriv->adc_byte_count)
556 size = devpriv->adc_byte_count;
558 return size;
561 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
562 int rounding_flags)
564 struct das16_private_struct *devpriv = dev->private;
566 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
567 &(devpriv->divisor2), &ns,
568 rounding_flags & TRIG_ROUND_MASK);
570 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
571 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
572 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
574 return ns;
577 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
579 const struct das16_board *board = comedi_board(dev);
580 struct das16_private_struct *devpriv = dev->private;
581 struct comedi_async *async = s->async;
582 struct comedi_cmd *cmd = &async->cmd;
583 unsigned int byte;
584 unsigned long flags;
585 int range;
587 if (devpriv->dma_chan == 0 || (dev->irq == 0
588 && devpriv->timer_mode == 0)) {
589 comedi_error(dev,
590 "irq (or use of 'timer mode') dma required to "
591 "execute comedi_cmd");
592 return -1;
594 if (cmd->flags & TRIG_RT) {
595 comedi_error(dev, "isa dma transfers cannot be performed with "
596 "TRIG_RT, aborting");
597 return -1;
600 devpriv->adc_byte_count =
601 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
603 /* disable conversions for das1600 mode */
604 if (board->size > 0x400)
605 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
607 /* set scan limits */
608 byte = CR_CHAN(cmd->chanlist[0]);
609 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
610 outb(byte, dev->iobase + DAS16_MUX);
612 /* set gain (this is also burst rate register but according to
613 * computer boards manual, burst rate does nothing, even on
614 * keithley cards) */
615 if (board->ai_pg != das16_pg_none) {
616 range = CR_RANGE(cmd->chanlist[0]);
617 outb((das16_gainlists[board->ai_pg])[range],
618 dev->iobase + DAS16_GAIN);
621 /* set counter mode and counts */
622 cmd->convert_arg =
623 das16_set_pacer(dev, cmd->convert_arg,
624 cmd->flags & TRIG_ROUND_MASK);
625 DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
627 /* enable counters */
628 byte = 0;
629 /* Enable burst mode if appropriate. */
630 if (board->size > 0x400) {
631 if (cmd->convert_src == TRIG_NOW) {
632 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
633 /* set burst length */
634 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
635 } else {
636 outb(0, dev->iobase + DAS1600_BURST);
639 outb(byte, dev->iobase + DAS16_PACER);
641 /* set up dma transfer */
642 flags = claim_dma_lock();
643 disable_dma(devpriv->dma_chan);
644 /* clear flip-flop to make sure 2-byte registers for
645 * count and address get set correctly */
646 clear_dma_ff(devpriv->dma_chan);
647 devpriv->current_buffer = 0;
648 set_dma_addr(devpriv->dma_chan,
649 devpriv->dma_buffer_addr[devpriv->current_buffer]);
650 /* set appropriate size of transfer */
651 devpriv->dma_transfer_size = das16_suggest_transfer_size(dev, cmd);
652 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
653 enable_dma(devpriv->dma_chan);
654 release_dma_lock(flags);
656 /* set up interrupt */
657 if (devpriv->timer_mode) {
658 devpriv->timer_running = 1;
659 devpriv->timer.expires = jiffies + timer_period();
660 add_timer(&devpriv->timer);
661 devpriv->control_state &= ~DAS16_INTE;
662 } else {
663 /* clear interrupt bit */
664 outb(0x00, dev->iobase + DAS16_STATUS);
665 /* enable interrupts */
666 devpriv->control_state |= DAS16_INTE;
668 devpriv->control_state |= DMA_ENABLE;
669 devpriv->control_state &= ~PACING_MASK;
670 if (cmd->convert_src == TRIG_EXT)
671 devpriv->control_state |= EXT_PACER;
672 else
673 devpriv->control_state |= INT_PACER;
674 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
676 /* Enable conversions if using das1600 mode */
677 if (board->size > 0x400)
678 outb(0, dev->iobase + DAS1600_CONV);
681 return 0;
684 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
686 const struct das16_board *board = comedi_board(dev);
687 struct das16_private_struct *devpriv = dev->private;
688 unsigned long flags;
690 spin_lock_irqsave(&dev->spinlock, flags);
691 /* disable interrupts, dma and pacer clocked conversions */
692 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
693 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
694 if (devpriv->dma_chan)
695 disable_dma(devpriv->dma_chan);
697 /* disable SW timer */
698 if (devpriv->timer_mode && devpriv->timer_running) {
699 devpriv->timer_running = 0;
700 del_timer(&devpriv->timer);
703 /* disable burst mode */
704 if (board->size > 0x400)
705 outb(0, dev->iobase + DAS1600_BURST);
708 spin_unlock_irqrestore(&dev->spinlock, flags);
710 return 0;
713 static void das16_reset(struct comedi_device *dev)
715 outb(0, dev->iobase + DAS16_STATUS);
716 outb(0, dev->iobase + DAS16_CONTROL);
717 outb(0, dev->iobase + DAS16_PACER);
718 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
721 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
722 struct comedi_insn *insn, unsigned int *data)
724 const struct das16_board *board = comedi_board(dev);
725 struct das16_private_struct *devpriv = dev->private;
726 int i, n;
727 int range;
728 int chan;
729 int msb, lsb;
731 /* disable interrupts and pacing */
732 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
733 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
735 /* set multiplexer */
736 chan = CR_CHAN(insn->chanspec);
737 chan |= CR_CHAN(insn->chanspec) << 4;
738 outb(chan, dev->iobase + DAS16_MUX);
740 /* set gain */
741 if (board->ai_pg != das16_pg_none) {
742 range = CR_RANGE(insn->chanspec);
743 outb((das16_gainlists[board->ai_pg])[range],
744 dev->iobase + DAS16_GAIN);
747 for (n = 0; n < insn->n; n++) {
748 /* trigger conversion */
749 outb_p(0, dev->iobase + DAS16_TRIG);
751 for (i = 0; i < DAS16_TIMEOUT; i++) {
752 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
753 break;
755 if (i == DAS16_TIMEOUT) {
756 printk("das16: timeout\n");
757 return -ETIME;
759 msb = inb(dev->iobase + DAS16_AI_MSB);
760 lsb = inb(dev->iobase + DAS16_AI_LSB);
761 if (board->ai_nbits == 12)
762 data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
763 else
764 data[n] = lsb | (msb << 8);
768 return n;
771 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
772 struct comedi_insn *insn, unsigned int *data)
774 unsigned int bits;
776 bits = inb(dev->iobase + DAS16_DIO) & 0xf;
777 data[1] = bits;
778 data[0] = 0;
780 return insn->n;
783 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
784 struct comedi_insn *insn, unsigned int *data)
786 unsigned int wbits;
788 /* only set bits that have been masked */
789 data[0] &= 0xf;
790 wbits = s->state;
791 /* zero bits that have been masked */
792 wbits &= ~data[0];
793 /* set masked bits */
794 wbits |= data[0] & data[1];
795 s->state = wbits;
796 data[1] = wbits;
798 outb(s->state, dev->iobase + DAS16_DIO);
800 return insn->n;
803 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
804 struct comedi_insn *insn, unsigned int *data)
806 const struct das16_board *board = comedi_board(dev);
807 int i;
808 int lsb, msb;
809 int chan;
811 chan = CR_CHAN(insn->chanspec);
813 for (i = 0; i < insn->n; i++) {
814 if (board->ao_nbits == 12) {
815 lsb = (data[i] << 4) & 0xff;
816 msb = (data[i] >> 4) & 0xff;
817 } else {
818 lsb = data[i] & 0xff;
819 msb = (data[i] >> 8) & 0xff;
821 outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
822 outb(msb, dev->iobase + DAS16_AO_MSB(chan));
825 return i;
828 /* the pc104-das16jr (at least) has problems if the dma
829 transfer is interrupted in the middle of transferring
830 a 16 bit sample, so this function takes care to get
831 an even transfer count after disabling dma
832 channel.
834 static int disable_dma_on_even(struct comedi_device *dev)
836 struct das16_private_struct *devpriv = dev->private;
837 int residue;
838 int i;
839 static const int disable_limit = 100;
840 static const int enable_timeout = 100;
842 disable_dma(devpriv->dma_chan);
843 residue = get_dma_residue(devpriv->dma_chan);
844 for (i = 0; i < disable_limit && (residue % 2); ++i) {
845 int j;
846 enable_dma(devpriv->dma_chan);
847 for (j = 0; j < enable_timeout; ++j) {
848 int new_residue;
849 udelay(2);
850 new_residue = get_dma_residue(devpriv->dma_chan);
851 if (new_residue != residue)
852 break;
854 disable_dma(devpriv->dma_chan);
855 residue = get_dma_residue(devpriv->dma_chan);
857 if (i == disable_limit) {
858 comedi_error(dev, "failed to get an even dma transfer, "
859 "could be trouble.");
861 return residue;
864 static void das16_interrupt(struct comedi_device *dev)
866 const struct das16_board *board = comedi_board(dev);
867 struct das16_private_struct *devpriv = dev->private;
868 unsigned long dma_flags, spin_flags;
869 struct comedi_subdevice *s = dev->read_subdev;
870 struct comedi_async *async;
871 struct comedi_cmd *cmd;
872 int num_bytes, residue;
873 int buffer_index;
875 if (!dev->attached) {
876 comedi_error(dev, "premature interrupt");
877 return;
879 /* initialize async here to make sure it is not NULL */
880 async = s->async;
881 cmd = &async->cmd;
883 if (devpriv->dma_chan == 0) {
884 comedi_error(dev, "interrupt with no dma channel?");
885 return;
888 spin_lock_irqsave(&dev->spinlock, spin_flags);
889 if ((devpriv->control_state & DMA_ENABLE) == 0) {
890 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
891 DEBUG_PRINT("interrupt while dma disabled?\n");
892 return;
895 dma_flags = claim_dma_lock();
896 clear_dma_ff(devpriv->dma_chan);
897 residue = disable_dma_on_even(dev);
899 /* figure out how many points to read */
900 if (residue > devpriv->dma_transfer_size) {
901 comedi_error(dev, "residue > transfer size!\n");
902 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
903 num_bytes = 0;
904 } else
905 num_bytes = devpriv->dma_transfer_size - residue;
907 if (cmd->stop_src == TRIG_COUNT &&
908 num_bytes >= devpriv->adc_byte_count) {
909 num_bytes = devpriv->adc_byte_count;
910 async->events |= COMEDI_CB_EOA;
913 buffer_index = devpriv->current_buffer;
914 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
915 devpriv->adc_byte_count -= num_bytes;
917 /* figure out how many bytes for next transfer */
918 if (cmd->stop_src == TRIG_COUNT && devpriv->timer_mode == 0 &&
919 devpriv->dma_transfer_size > devpriv->adc_byte_count)
920 devpriv->dma_transfer_size = devpriv->adc_byte_count;
922 /* re-enable dma */
923 if ((async->events & COMEDI_CB_EOA) == 0) {
924 set_dma_addr(devpriv->dma_chan,
925 devpriv->dma_buffer_addr[devpriv->current_buffer]);
926 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
927 enable_dma(devpriv->dma_chan);
928 /* reenable conversions for das1600 mode, (stupid hardware) */
929 if (board->size > 0x400 && devpriv->timer_mode == 0)
930 outb(0x00, dev->iobase + DAS1600_CONV);
933 release_dma_lock(dma_flags);
935 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
937 cfc_write_array_to_buffer(s,
938 devpriv->dma_buffer[buffer_index], num_bytes);
940 cfc_handle_events(dev, s);
943 static irqreturn_t das16_dma_interrupt(int irq, void *d)
945 int status;
946 struct comedi_device *dev = d;
948 status = inb(dev->iobase + DAS16_STATUS);
950 if ((status & DAS16_INT) == 0) {
951 DEBUG_PRINT("spurious interrupt\n");
952 return IRQ_NONE;
955 /* clear interrupt */
956 outb(0x00, dev->iobase + DAS16_STATUS);
957 das16_interrupt(dev);
958 return IRQ_HANDLED;
961 static void das16_timer_interrupt(unsigned long arg)
963 struct comedi_device *dev = (struct comedi_device *)arg;
964 struct das16_private_struct *devpriv = dev->private;
966 das16_interrupt(dev);
968 if (devpriv->timer_running)
969 mod_timer(&devpriv->timer, jiffies + timer_period());
972 static void reg_dump(struct comedi_device *dev)
974 DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
975 DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
976 DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
977 DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
978 DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
979 DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
980 DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
981 DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
982 inb(dev->iobase + DAS16_CNTR_CONTROL));
983 DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
984 DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
985 DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
986 DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
987 inb(dev->iobase + DAS1600_STATUS_B));
990 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
992 const struct das16_board *board = comedi_board(dev);
993 struct das16_private_struct *devpriv = dev->private;
994 int status;
995 int diobits;
997 /* status is available on all boards */
999 status = inb(dev->iobase + DAS16_STATUS);
1001 if ((status & UNIPOLAR))
1002 devpriv->ai_unipolar = 1;
1003 else
1004 devpriv->ai_unipolar = 0;
1007 if ((status & DAS16_MUXBIT))
1008 devpriv->ai_singleended = 1;
1009 else
1010 devpriv->ai_singleended = 0;
1013 /* diobits indicates boards */
1015 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
1017 printk(KERN_INFO " id bits are 0x%02x\n", diobits);
1018 if (board->id != diobits) {
1019 printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
1020 board->id);
1023 return 0;
1026 static int das1600_mode_detect(struct comedi_device *dev)
1028 struct das16_private_struct *devpriv = dev->private;
1029 int status = 0;
1031 status = inb(dev->iobase + DAS1600_STATUS_B);
1033 if (status & DAS1600_CLK_10MHZ) {
1034 devpriv->clockbase = 100;
1035 printk(KERN_INFO " 10MHz pacer clock\n");
1036 } else {
1037 devpriv->clockbase = 1000;
1038 printk(KERN_INFO " 1MHz pacer clock\n");
1041 reg_dump(dev);
1043 return 0;
1046 static void das16_ai_munge(struct comedi_device *dev,
1047 struct comedi_subdevice *s, void *array,
1048 unsigned int num_bytes,
1049 unsigned int start_chan_index)
1051 const struct das16_board *board = comedi_board(dev);
1052 unsigned int i, num_samples = num_bytes / sizeof(short);
1053 short *data = array;
1055 for (i = 0; i < num_samples; i++) {
1056 data[i] = le16_to_cpu(data[i]);
1057 if (board->ai_nbits == 12)
1058 data[i] = (data[i] >> 4) & 0xfff;
1065 * Options list:
1066 * 0 I/O base
1067 * 1 IRQ
1068 * 2 DMA
1069 * 3 Clock speed (in MHz)
1071 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1073 const struct das16_board *board = comedi_board(dev);
1074 struct das16_private_struct *devpriv;
1075 struct comedi_subdevice *s;
1076 int ret;
1077 unsigned int irq;
1078 unsigned int dma_chan;
1079 int timer_mode;
1080 unsigned long flags;
1081 struct comedi_krange *user_ai_range, *user_ao_range;
1083 #if 0
1084 irq = it->options[1];
1085 timer_mode = it->options[8];
1086 #endif
1087 /* always use time_mode since using irq can drop samples while
1088 * waiting for dma done interrupt (due to hardware limitations) */
1089 irq = 0;
1090 timer_mode = 1;
1091 if (timer_mode)
1092 irq = 0;
1094 /* check that clock setting is valid */
1095 if (it->options[3]) {
1096 if (it->options[3] != 0 &&
1097 it->options[3] != 1 && it->options[3] != 10) {
1098 printk
1099 ("\n Invalid option. Master clock must be set "
1100 "to 1 or 10 (MHz)\n");
1101 return -EINVAL;
1105 devpriv = kzalloc(sizeof(*devpriv), GFP_KERNEL);
1106 if (!devpriv)
1107 return -ENOMEM;
1108 dev->private = devpriv;
1110 if (board->size < 0x400) {
1111 ret = comedi_request_region(dev, it->options[0], board->size);
1112 if (ret)
1113 return ret;
1114 } else {
1115 ret = comedi_request_region(dev, it->options[0], 0x10);
1116 if (ret)
1117 return ret;
1118 /* Request an additional region for the 8255 */
1119 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1120 board->size & 0x3ff);
1121 if (ret)
1122 return ret;
1123 devpriv->extra_iobase = dev->iobase + 0x400;
1126 /* probe id bits to make sure they are consistent */
1127 if (das16_probe(dev, it)) {
1128 printk(KERN_ERR " id bits do not match selected board, aborting\n");
1129 return -EINVAL;
1132 /* get master clock speed */
1133 if (board->size < 0x400) {
1134 if (it->options[3])
1135 devpriv->clockbase = 1000 / it->options[3];
1136 else
1137 devpriv->clockbase = 1000; /* 1 MHz default */
1138 } else {
1139 das1600_mode_detect(dev);
1142 /* now for the irq */
1143 if (irq > 1 && irq < 8) {
1144 ret = request_irq(irq, das16_dma_interrupt, 0,
1145 dev->board_name, dev);
1147 if (ret < 0)
1148 return ret;
1149 dev->irq = irq;
1150 printk(KERN_INFO " ( irq = %u )", irq);
1151 } else if (irq == 0) {
1152 printk(" ( no irq )");
1153 } else {
1154 printk(" invalid irq\n");
1155 return -EINVAL;
1158 /* initialize dma */
1159 dma_chan = it->options[2];
1160 if (dma_chan == 1 || dma_chan == 3) {
1161 /* allocate dma buffers */
1162 int i;
1163 for (i = 0; i < 2; i++) {
1164 devpriv->dma_buffer[i] = pci_alloc_consistent(
1165 NULL, DAS16_DMA_SIZE,
1166 &devpriv->dma_buffer_addr[i]);
1168 if (devpriv->dma_buffer[i] == NULL)
1169 return -ENOMEM;
1171 if (request_dma(dma_chan, dev->board_name)) {
1172 printk(KERN_ERR " failed to allocate dma channel %i\n",
1173 dma_chan);
1174 return -EINVAL;
1176 devpriv->dma_chan = dma_chan;
1177 flags = claim_dma_lock();
1178 disable_dma(devpriv->dma_chan);
1179 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1180 release_dma_lock(flags);
1181 printk(KERN_INFO " ( dma = %u)\n", dma_chan);
1182 } else if (dma_chan == 0) {
1183 printk(KERN_INFO " ( no dma )\n");
1184 } else {
1185 printk(KERN_ERR " invalid dma channel\n");
1186 return -EINVAL;
1189 /* get any user-defined input range */
1190 if (board->ai_pg == das16_pg_none &&
1191 (it->options[4] || it->options[5])) {
1192 /* allocate single-range range table */
1193 devpriv->user_ai_range_table =
1194 kmalloc(sizeof(struct comedi_lrange) +
1195 sizeof(struct comedi_krange), GFP_KERNEL);
1196 /* initialize ai range */
1197 devpriv->user_ai_range_table->length = 1;
1198 user_ai_range = devpriv->user_ai_range_table->range;
1199 user_ai_range->min = it->options[4];
1200 user_ai_range->max = it->options[5];
1201 user_ai_range->flags = UNIT_volt;
1203 /* get any user-defined output range */
1204 if (it->options[6] || it->options[7]) {
1205 /* allocate single-range range table */
1206 devpriv->user_ao_range_table =
1207 kmalloc(sizeof(struct comedi_lrange) +
1208 sizeof(struct comedi_krange), GFP_KERNEL);
1209 /* initialize ao range */
1210 devpriv->user_ao_range_table->length = 1;
1211 user_ao_range = devpriv->user_ao_range_table->range;
1212 user_ao_range->min = it->options[6];
1213 user_ao_range->max = it->options[7];
1214 user_ao_range->flags = UNIT_volt;
1217 if (timer_mode) {
1218 init_timer(&(devpriv->timer));
1219 devpriv->timer.function = das16_timer_interrupt;
1220 devpriv->timer.data = (unsigned long)dev;
1222 devpriv->timer_mode = timer_mode ? 1 : 0;
1224 ret = comedi_alloc_subdevices(dev, 5);
1225 if (ret)
1226 return ret;
1228 s = &dev->subdevices[0];
1229 dev->read_subdev = s;
1230 /* ai */
1231 if (board->ai) {
1232 s->type = COMEDI_SUBD_AI;
1233 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1234 if (devpriv->ai_singleended) {
1235 s->n_chan = 16;
1236 s->len_chanlist = 16;
1237 s->subdev_flags |= SDF_GROUND;
1238 } else {
1239 s->n_chan = 8;
1240 s->len_chanlist = 8;
1241 s->subdev_flags |= SDF_DIFF;
1243 s->maxdata = (1 << board->ai_nbits) - 1;
1244 if (devpriv->user_ai_range_table) { /* user defined ai range */
1245 s->range_table = devpriv->user_ai_range_table;
1246 } else if (devpriv->ai_unipolar) {
1247 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1248 } else {
1249 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1251 s->insn_read = board->ai;
1252 s->do_cmdtest = das16_cmd_test;
1253 s->do_cmd = das16_cmd_exec;
1254 s->cancel = das16_cancel;
1255 s->munge = das16_ai_munge;
1256 } else {
1257 s->type = COMEDI_SUBD_UNUSED;
1260 s = &dev->subdevices[1];
1261 /* ao */
1262 if (board->ao) {
1263 s->type = COMEDI_SUBD_AO;
1264 s->subdev_flags = SDF_WRITABLE;
1265 s->n_chan = 2;
1266 s->maxdata = (1 << board->ao_nbits) - 1;
1267 /* user defined ao range */
1268 if (devpriv->user_ao_range_table)
1269 s->range_table = devpriv->user_ao_range_table;
1270 else
1271 s->range_table = &range_unknown;
1273 s->insn_write = board->ao;
1274 } else {
1275 s->type = COMEDI_SUBD_UNUSED;
1278 s = &dev->subdevices[2];
1279 /* di */
1280 if (board->di) {
1281 s->type = COMEDI_SUBD_DI;
1282 s->subdev_flags = SDF_READABLE;
1283 s->n_chan = 4;
1284 s->maxdata = 1;
1285 s->range_table = &range_digital;
1286 s->insn_bits = board->di;
1287 } else {
1288 s->type = COMEDI_SUBD_UNUSED;
1291 s = &dev->subdevices[3];
1292 /* do */
1293 if (board->do_) {
1294 s->type = COMEDI_SUBD_DO;
1295 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1296 s->n_chan = 4;
1297 s->maxdata = 1;
1298 s->range_table = &range_digital;
1299 s->insn_bits = board->do_;
1300 /* initialize digital output lines */
1301 outb(s->state, dev->iobase + DAS16_DIO);
1302 } else {
1303 s->type = COMEDI_SUBD_UNUSED;
1306 s = &dev->subdevices[4];
1307 /* 8255 */
1308 if (board->i8255_offset != 0) {
1309 subdev_8255_init(dev, s, NULL, (dev->iobase +
1310 board->i8255_offset));
1311 } else {
1312 s->type = COMEDI_SUBD_UNUSED;
1315 das16_reset(dev);
1316 /* set the interrupt level */
1317 devpriv->control_state = DAS16_IRQ(dev->irq);
1318 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1320 /* turn on das1600 mode if available */
1321 if (board->size > 0x400) {
1322 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1323 outb(0, dev->iobase + DAS1600_CONV);
1324 outb(0, dev->iobase + DAS1600_BURST);
1327 return 0;
1330 static void das16_detach(struct comedi_device *dev)
1332 const struct das16_board *board = comedi_board(dev);
1333 struct das16_private_struct *devpriv = dev->private;
1335 das16_reset(dev);
1336 if (devpriv) {
1337 int i;
1338 for (i = 0; i < 2; i++) {
1339 if (devpriv->dma_buffer[i])
1340 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1341 devpriv->dma_buffer[i],
1342 devpriv->
1343 dma_buffer_addr[i]);
1345 if (devpriv->dma_chan)
1346 free_dma(devpriv->dma_chan);
1347 kfree(devpriv->user_ai_range_table);
1348 kfree(devpriv->user_ao_range_table);
1350 if (devpriv->extra_iobase)
1351 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1352 comedi_legacy_detach(dev);
1355 static const struct das16_board das16_boards[] = {
1357 .name = "das-16",
1358 .ai = das16_ai_rinsn,
1359 .ai_nbits = 12,
1360 .ai_speed = 15000,
1361 .ai_pg = das16_pg_none,
1362 .ao = das16_ao_winsn,
1363 .ao_nbits = 12,
1364 .di = das16_di_rbits,
1365 .do_ = das16_do_wbits,
1366 .i8255_offset = 0x10,
1367 .i8254_offset = 0x0c,
1368 .size = 0x14,
1369 .id = 0x00,
1370 }, {
1371 .name = "das-16g",
1372 .ai = das16_ai_rinsn,
1373 .ai_nbits = 12,
1374 .ai_speed = 15000,
1375 .ai_pg = das16_pg_none,
1376 .ao = das16_ao_winsn,
1377 .ao_nbits = 12,
1378 .di = das16_di_rbits,
1379 .do_ = das16_do_wbits,
1380 .i8255_offset = 0x10,
1381 .i8254_offset = 0x0c,
1382 .size = 0x14,
1383 .id = 0x00,
1384 }, {
1385 .name = "das-16f",
1386 .ai = das16_ai_rinsn,
1387 .ai_nbits = 12,
1388 .ai_speed = 8500,
1389 .ai_pg = das16_pg_none,
1390 .ao = das16_ao_winsn,
1391 .ao_nbits = 12,
1392 .di = das16_di_rbits,
1393 .do_ = das16_do_wbits,
1394 .i8255_offset = 0x10,
1395 .i8254_offset = 0x0c,
1396 .size = 0x14,
1397 .id = 0x00,
1398 }, {
1399 .name = "cio-das16",
1400 .ai = das16_ai_rinsn,
1401 .ai_nbits = 12,
1402 .ai_speed = 20000,
1403 .ai_pg = das16_pg_none,
1404 .ao = das16_ao_winsn,
1405 .ao_nbits = 12,
1406 .di = das16_di_rbits,
1407 .do_ = das16_do_wbits,
1408 .i8255_offset = 0x10,
1409 .i8254_offset = 0x0c,
1410 .size = 0x14,
1411 .id = 0x80,
1412 }, {
1413 .name = "cio-das16/f",
1414 .ai = das16_ai_rinsn,
1415 .ai_nbits = 12,
1416 .ai_speed = 10000,
1417 .ai_pg = das16_pg_none,
1418 .ao = das16_ao_winsn,
1419 .ao_nbits = 12,
1420 .di = das16_di_rbits,
1421 .do_ = das16_do_wbits,
1422 .i8255_offset = 0x10,
1423 .i8254_offset = 0x0c,
1424 .size = 0x14,
1425 .id = 0x80,
1426 }, {
1427 .name = "cio-das16/jr",
1428 .ai = das16_ai_rinsn,
1429 .ai_nbits = 12,
1430 .ai_speed = 7692,
1431 .ai_pg = das16_pg_16jr,
1432 .ao = NULL,
1433 .di = das16_di_rbits,
1434 .do_ = das16_do_wbits,
1435 .i8255_offset = 0,
1436 .i8254_offset = 0x0c,
1437 .size = 0x10,
1438 .id = 0x00,
1439 }, {
1440 .name = "pc104-das16jr",
1441 .ai = das16_ai_rinsn,
1442 .ai_nbits = 12,
1443 .ai_speed = 3300,
1444 .ai_pg = das16_pg_16jr,
1445 .ao = NULL,
1446 .di = das16_di_rbits,
1447 .do_ = das16_do_wbits,
1448 .i8255_offset = 0,
1449 .i8254_offset = 0x0c,
1450 .size = 0x10,
1451 .id = 0x00,
1452 }, {
1453 .name = "cio-das16jr/16",
1454 .ai = das16_ai_rinsn,
1455 .ai_nbits = 16,
1456 .ai_speed = 10000,
1457 .ai_pg = das16_pg_16jr_16,
1458 .ao = NULL,
1459 .di = das16_di_rbits,
1460 .do_ = das16_do_wbits,
1461 .i8255_offset = 0,
1462 .i8254_offset = 0x0c,
1463 .size = 0x10,
1464 .id = 0x00,
1465 }, {
1466 .name = "pc104-das16jr/16",
1467 .ai = das16_ai_rinsn,
1468 .ai_nbits = 16,
1469 .ai_speed = 10000,
1470 .ai_pg = das16_pg_16jr_16,
1471 .ao = NULL,
1472 .di = das16_di_rbits,
1473 .do_ = das16_do_wbits,
1474 .i8255_offset = 0,
1475 .i8254_offset = 0x0c,
1476 .size = 0x10,
1477 .id = 0x00,
1478 }, {
1479 .name = "das-1201",
1480 .ai = das16_ai_rinsn,
1481 .ai_nbits = 12,
1482 .ai_speed = 20000,
1483 .ai_pg = das16_pg_none,
1484 .ao = NULL,
1485 .di = das16_di_rbits,
1486 .do_ = das16_do_wbits,
1487 .i8255_offset = 0x400,
1488 .i8254_offset = 0x0c,
1489 .size = 0x408,
1490 .id = 0x20,
1491 }, {
1492 .name = "das-1202",
1493 .ai = das16_ai_rinsn,
1494 .ai_nbits = 12,
1495 .ai_speed = 10000,
1496 .ai_pg = das16_pg_none,
1497 .ao = NULL,
1498 .di = das16_di_rbits,
1499 .do_ = das16_do_wbits,
1500 .i8255_offset = 0x400,
1501 .i8254_offset = 0x0c,
1502 .size = 0x408,
1503 .id = 0x20,
1504 }, {
1505 .name = "das-1401",
1506 .ai = das16_ai_rinsn,
1507 .ai_nbits = 12,
1508 .ai_speed = 10000,
1509 .ai_pg = das16_pg_1601,
1510 .ao = NULL,
1511 .di = das16_di_rbits,
1512 .do_ = das16_do_wbits,
1513 .i8255_offset = 0x0,
1514 .i8254_offset = 0x0c,
1515 .size = 0x408,
1516 .id = 0xc0,
1517 }, {
1518 .name = "das-1402",
1519 .ai = das16_ai_rinsn,
1520 .ai_nbits = 12,
1521 .ai_speed = 10000,
1522 .ai_pg = das16_pg_1602,
1523 .ao = NULL,
1524 .di = das16_di_rbits,
1525 .do_ = das16_do_wbits,
1526 .i8255_offset = 0x0,
1527 .i8254_offset = 0x0c,
1528 .size = 0x408,
1529 .id = 0xc0,
1530 }, {
1531 .name = "das-1601",
1532 .ai = das16_ai_rinsn,
1533 .ai_nbits = 12,
1534 .ai_speed = 10000,
1535 .ai_pg = das16_pg_1601,
1536 .ao = das16_ao_winsn,
1537 .ao_nbits = 12,
1538 .di = das16_di_rbits,
1539 .do_ = das16_do_wbits,
1540 .i8255_offset = 0x400,
1541 .i8254_offset = 0x0c,
1542 .size = 0x408,
1543 .id = 0xc0,
1544 }, {
1545 .name = "das-1602",
1546 .ai = das16_ai_rinsn,
1547 .ai_nbits = 12,
1548 .ai_speed = 10000,
1549 .ai_pg = das16_pg_1602,
1550 .ao = das16_ao_winsn,
1551 .ao_nbits = 12,
1552 .di = das16_di_rbits,
1553 .do_ = das16_do_wbits,
1554 .i8255_offset = 0x400,
1555 .i8254_offset = 0x0c,
1556 .size = 0x408,
1557 .id = 0xc0,
1558 }, {
1559 .name = "cio-das1401/12",
1560 .ai = das16_ai_rinsn,
1561 .ai_nbits = 12,
1562 .ai_speed = 6250,
1563 .ai_pg = das16_pg_1601,
1564 .ao = NULL,
1565 .di = das16_di_rbits,
1566 .do_ = das16_do_wbits,
1567 .i8255_offset = 0,
1568 .i8254_offset = 0x0c,
1569 .size = 0x408,
1570 .id = 0xc0,
1571 }, {
1572 .name = "cio-das1402/12",
1573 .ai = das16_ai_rinsn,
1574 .ai_nbits = 12,
1575 .ai_speed = 6250,
1576 .ai_pg = das16_pg_1602,
1577 .ao = NULL,
1578 .di = das16_di_rbits,
1579 .do_ = das16_do_wbits,
1580 .i8255_offset = 0,
1581 .i8254_offset = 0x0c,
1582 .size = 0x408,
1583 .id = 0xc0,
1584 }, {
1585 .name = "cio-das1402/16",
1586 .ai = das16_ai_rinsn,
1587 .ai_nbits = 16,
1588 .ai_speed = 10000,
1589 .ai_pg = das16_pg_1602,
1590 .ao = NULL,
1591 .di = das16_di_rbits,
1592 .do_ = das16_do_wbits,
1593 .i8255_offset = 0,
1594 .i8254_offset = 0x0c,
1595 .size = 0x408,
1596 .id = 0xc0,
1597 }, {
1598 .name = "cio-das1601/12",
1599 .ai = das16_ai_rinsn,
1600 .ai_nbits = 12,
1601 .ai_speed = 6250,
1602 .ai_pg = das16_pg_1601,
1603 .ao = das16_ao_winsn,
1604 .ao_nbits = 12,
1605 .di = das16_di_rbits,
1606 .do_ = das16_do_wbits,
1607 .i8255_offset = 0x400,
1608 .i8254_offset = 0x0c,
1609 .size = 0x408,
1610 .id = 0xc0,
1611 }, {
1612 .name = "cio-das1602/12",
1613 .ai = das16_ai_rinsn,
1614 .ai_nbits = 12,
1615 .ai_speed = 10000,
1616 .ai_pg = das16_pg_1602,
1617 .ao = das16_ao_winsn,
1618 .ao_nbits = 12,
1619 .di = das16_di_rbits,
1620 .do_ = das16_do_wbits,
1621 .i8255_offset = 0x400,
1622 .i8254_offset = 0x0c,
1623 .size = 0x408,
1624 .id = 0xc0,
1625 }, {
1626 .name = "cio-das1602/16",
1627 .ai = das16_ai_rinsn,
1628 .ai_nbits = 16,
1629 .ai_speed = 10000,
1630 .ai_pg = das16_pg_1602,
1631 .ao = das16_ao_winsn,
1632 .ao_nbits = 12,
1633 .di = das16_di_rbits,
1634 .do_ = das16_do_wbits,
1635 .i8255_offset = 0x400,
1636 .i8254_offset = 0x0c,
1637 .size = 0x408,
1638 .id = 0xc0,
1639 }, {
1640 .name = "cio-das16/330",
1641 .ai = das16_ai_rinsn,
1642 .ai_nbits = 12,
1643 .ai_speed = 3030,
1644 .ai_pg = das16_pg_16jr,
1645 .ao = NULL,
1646 .di = das16_di_rbits,
1647 .do_ = das16_do_wbits,
1648 .i8255_offset = 0,
1649 .i8254_offset = 0x0c,
1650 .size = 0x14,
1651 .id = 0xf0,
1655 static struct comedi_driver das16_driver = {
1656 .driver_name = "das16",
1657 .module = THIS_MODULE,
1658 .attach = das16_attach,
1659 .detach = das16_detach,
1660 .board_name = &das16_boards[0].name,
1661 .num_names = ARRAY_SIZE(das16_boards),
1662 .offset = sizeof(das16_boards[0]),
1664 module_comedi_driver(das16_driver);
1666 MODULE_AUTHOR("Comedi http://www.comedi.org");
1667 MODULE_DESCRIPTION("Comedi low-level driver");
1668 MODULE_LICENSE("GPL");