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.
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),
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)
38 A rewrite of the das16 and das1600 drivers.
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
48 [5] - analog input range highest voltage in microvolts (optional,
49 only useful if board does not have software programmable
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.
67 4919.PDF (das1400, 1600)
69 4923.PDF (das1200, 1400, 1600)
71 Computer boards manuals also available from their website
72 www.measurementcomputing.com
76 #include <linux/module.h>
77 #include <linux/delay.h>
78 #include <linux/pci.h>
79 #include <linux/interrupt.h>
83 #include "../comedidev.h"
87 #include "comedi_fc.h"
89 #define DAS16_SIZE 20 /* number of ioports */
90 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
98 0 a/d bits 0-3 start 12 bit
99 1 a/d bits 4-11 unused
106 8 status eoc uni/bip interrupt reset
107 9 dma, int, trig ctrl set dma, int
108 a pacer control unused
120 0 a/d bits 0-3 start 12 bit
121 1 a/d bits 4-11 unused
125 8 status eoc uni/bip interrupt reset
126 9 dma, int, trig ctrl set dma, int
127 a pacer control unused
128 b gain status gain control
138 0 a/d bits 0-7 start 16 bit
139 1 a/d bits 8-15 unused
143 8 status eoc uni/bip interrupt reset
144 9 dma, int, trig ctrl set dma, int
145 a pacer control unused
146 b gain status gain control
157 0 a/d bits 0-3 start 12 bit
158 1 a/d bits 4-11 unused
165 8 status eoc uni/bip interrupt reset
166 9 dma, int, trig ctrl set dma, int
167 a pacer control unused
168 b gain status gain control
171 404 unused conversion enable
172 405 unused burst enable
173 406 unused das1600 enable
178 /* size in bytes of a sample from board */
179 static const int sample_size = 2;
182 #define DAS16_AI_LSB 0
183 #define DAS16_AI_MSB 1
186 #define DAS16_AO_LSB(x) ((x) ? 6 : 4)
187 #define DAS16_AO_MSB(x) ((x) ? 7 : 5)
188 #define DAS16_STATUS 8
190 #define UNIPOLAR (1<<6)
191 #define DAS16_MUXBIT (1<<5)
192 #define DAS16_INT (1<<4)
193 #define DAS16_CONTROL 9
194 #define DAS16_INTE (1<<7)
195 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
196 #define DMA_ENABLE (1<<2)
197 #define PACING_MASK 0x3
198 #define INT_PACER 0x03
199 #define EXT_PACER 0x02
200 #define DAS16_SOFT 0x00
201 #define DAS16_PACER 0x0A
202 #define DAS16_CTR0 (1<<1)
203 #define DAS16_TRIG0 (1<<0)
204 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
205 #define DAS16_GAIN 0x0B
206 #define DAS16_CNTR0_DATA 0x0C
207 #define DAS16_CNTR1_DATA 0x0D
208 #define DAS16_CNTR2_DATA 0x0E
209 #define DAS16_CNTR_CONTROL 0x0F
210 #define DAS16_TERM_CNT 0x00
211 #define DAS16_ONE_SHOT 0x02
212 #define DAS16_RATE_GEN 0x04
213 #define DAS16_CNTR_LSB_MSB 0x30
214 #define DAS16_CNTR0 0x00
215 #define DAS16_CNTR1 0x40
216 #define DAS16_CNTR2 0x80
218 #define DAS1600_CONV 0x404
219 #define DAS1600_CONV_DISABLE 0x40
220 #define DAS1600_BURST 0x405
221 #define DAS1600_BURST_VAL 0x40
222 #define DAS1600_ENABLE 0x406
223 #define DAS1600_ENABLE_VAL 0x40
224 #define DAS1600_STATUS_B 0x407
225 #define DAS1600_BME 0x40
226 #define DAS1600_ME 0x20
227 #define DAS1600_CD 0x10
228 #define DAS1600_WS 0x02
229 #define DAS1600_CLK_10MHZ 0x01
231 static const struct comedi_lrange range_das1x01_bip = {
240 static const struct comedi_lrange range_das1x01_unip = {
249 static const struct comedi_lrange range_das1x02_bip = {
258 static const struct comedi_lrange range_das1x02_unip = {
267 static const struct comedi_lrange range_das16jr = {
281 static const struct comedi_lrange range_das16jr_16 = {
294 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
295 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
296 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
305 static const int *const das16_gainlists[] = {
313 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
321 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
331 unsigned int ai_maxdata;
332 unsigned int ai_speed; /* max conversion speed in nanosec */
334 unsigned int has_ao:1;
336 unsigned int i8255_offset;
337 unsigned int i8254_offset;
343 #define DAS16_TIMEOUT 1000
345 /* Period for timer interrupt in jiffies. It's a function
346 * to deal with possibility of dynamic HZ patches */
347 static inline int timer_period(void)
352 struct das16_private_struct {
353 unsigned int clockbase; /* master clock speed in ns */
354 unsigned int control_state; /* dma, interrupt and trigger control bits */
355 unsigned long adc_byte_count; /* number of bytes remaining */
356 /* divisor dividing master clock to get conversion frequency */
357 unsigned int divisor1;
358 /* divisor dividing master clock to get conversion frequency */
359 unsigned int divisor2;
360 unsigned int dma_chan; /* dma channel */
361 uint16_t *dma_buffer[2];
362 dma_addr_t dma_buffer_addr[2];
363 unsigned int current_buffer;
364 unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
366 * user-defined analog input and output ranges
367 * defined from config options
369 struct comedi_lrange *user_ai_range_table;
370 struct comedi_lrange *user_ao_range_table;
372 struct timer_list timer; /* for timed interrupt */
375 unsigned long extra_iobase;
376 unsigned int can_burst:1;
379 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
380 struct comedi_cmd *cmd)
382 const struct das16_board *board = comedi_board(dev);
383 struct das16_private_struct *devpriv = dev->private;
385 int gain, start_chan, i;
388 /* Step 1 : check if triggers are trivially valid */
390 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
393 if (devpriv->can_burst)
394 mask |= TRIG_TIMER | TRIG_EXT;
395 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
397 tmp = cmd->convert_src;
398 mask = TRIG_TIMER | TRIG_EXT;
399 if (devpriv->can_burst)
401 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
403 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
404 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
409 /* Step 2a : make sure trigger sources are unique */
411 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
412 err |= cfc_check_trigger_is_unique(cmd->convert_src);
413 err |= cfc_check_trigger_is_unique(cmd->stop_src);
415 /* Step 2b : and mutually compatible */
417 /* make sure scan_begin_src and convert_src dont conflict */
418 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
420 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
426 /* Step 3: check if arguments are trivially valid */
428 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
430 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
431 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
433 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
435 /* check against maximum frequency */
436 if (cmd->scan_begin_src == TRIG_TIMER)
437 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
438 board->ai_speed * cmd->chanlist_len);
440 if (cmd->convert_src == TRIG_TIMER)
441 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
444 if (cmd->stop_src == TRIG_NONE)
445 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
450 /* step 4: fix up arguments */
451 if (cmd->scan_begin_src == TRIG_TIMER) {
452 unsigned int tmp = cmd->scan_begin_arg;
453 /* set divisors, correct timing arguments */
454 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
455 &(devpriv->divisor1),
456 &(devpriv->divisor2),
457 &(cmd->scan_begin_arg),
458 cmd->flags & TRIG_ROUND_MASK);
459 err += (tmp != cmd->scan_begin_arg);
461 if (cmd->convert_src == TRIG_TIMER) {
462 unsigned int tmp = cmd->convert_arg;
463 /* set divisors, correct timing arguments */
464 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
465 &(devpriv->divisor1),
466 &(devpriv->divisor2),
468 cmd->flags & TRIG_ROUND_MASK);
469 err += (tmp != cmd->convert_arg);
474 /* check channel/gain list against card's limitations */
476 gain = CR_RANGE(cmd->chanlist[0]);
477 start_chan = CR_CHAN(cmd->chanlist[0]);
478 for (i = 1; i < cmd->chanlist_len; i++) {
479 if (CR_CHAN(cmd->chanlist[i]) !=
480 (start_chan + i) % s->n_chan) {
482 "entries in chanlist must be "
483 "consecutive channels, "
484 "counting upwards\n");
487 if (CR_RANGE(cmd->chanlist[i]) != gain) {
489 "entries in chanlist must all "
490 "have the same gain\n");
501 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
504 struct das16_private_struct *devpriv = dev->private;
506 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
507 &(devpriv->divisor2), &ns,
508 rounding_flags & TRIG_ROUND_MASK);
510 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
511 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
512 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
517 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
519 const struct das16_board *board = comedi_board(dev);
520 struct das16_private_struct *devpriv = dev->private;
521 struct comedi_async *async = s->async;
522 struct comedi_cmd *cmd = &async->cmd;
527 if (cmd->flags & TRIG_RT) {
528 comedi_error(dev, "isa dma transfers cannot be performed with "
529 "TRIG_RT, aborting");
533 devpriv->adc_byte_count =
534 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
536 if (devpriv->can_burst)
537 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
539 /* set scan limits */
540 byte = CR_CHAN(cmd->chanlist[0]);
541 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
542 outb(byte, dev->iobase + DAS16_MUX);
544 /* set gain (this is also burst rate register but according to
545 * computer boards manual, burst rate does nothing, even on
547 if (board->ai_pg != das16_pg_none) {
548 range = CR_RANGE(cmd->chanlist[0]);
549 outb((das16_gainlists[board->ai_pg])[range],
550 dev->iobase + DAS16_GAIN);
553 /* set counter mode and counts */
555 das16_set_pacer(dev, cmd->convert_arg,
556 cmd->flags & TRIG_ROUND_MASK);
558 /* enable counters */
560 if (devpriv->can_burst) {
561 if (cmd->convert_src == TRIG_NOW) {
562 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
563 /* set burst length */
564 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
566 outb(0, dev->iobase + DAS1600_BURST);
569 outb(byte, dev->iobase + DAS16_PACER);
571 /* set up dma transfer */
572 flags = claim_dma_lock();
573 disable_dma(devpriv->dma_chan);
574 /* clear flip-flop to make sure 2-byte registers for
575 * count and address get set correctly */
576 clear_dma_ff(devpriv->dma_chan);
577 devpriv->current_buffer = 0;
578 set_dma_addr(devpriv->dma_chan,
579 devpriv->dma_buffer_addr[devpriv->current_buffer]);
580 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
581 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
582 enable_dma(devpriv->dma_chan);
583 release_dma_lock(flags);
585 /* set up interrupt */
586 devpriv->timer_running = 1;
587 devpriv->timer.expires = jiffies + timer_period();
588 add_timer(&devpriv->timer);
589 devpriv->control_state &= ~DAS16_INTE;
590 devpriv->control_state |= DMA_ENABLE;
591 devpriv->control_state &= ~PACING_MASK;
592 if (cmd->convert_src == TRIG_EXT)
593 devpriv->control_state |= EXT_PACER;
595 devpriv->control_state |= INT_PACER;
596 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
598 if (devpriv->can_burst)
599 outb(0, dev->iobase + DAS1600_CONV);
605 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
607 struct das16_private_struct *devpriv = dev->private;
610 spin_lock_irqsave(&dev->spinlock, flags);
611 /* disable interrupts, dma and pacer clocked conversions */
612 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
613 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
614 disable_dma(devpriv->dma_chan);
616 /* disable SW timer */
617 if (devpriv->timer_running) {
618 devpriv->timer_running = 0;
619 del_timer(&devpriv->timer);
622 if (devpriv->can_burst)
623 outb(0, dev->iobase + DAS1600_BURST);
625 spin_unlock_irqrestore(&dev->spinlock, flags);
630 static void das16_reset(struct comedi_device *dev)
632 outb(0, dev->iobase + DAS16_STATUS);
633 outb(0, dev->iobase + DAS16_CONTROL);
634 outb(0, dev->iobase + DAS16_PACER);
635 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
638 static int das16_ai_insn_read(struct comedi_device *dev,
639 struct comedi_subdevice *s,
640 struct comedi_insn *insn,
643 const struct das16_board *board = comedi_board(dev);
644 struct das16_private_struct *devpriv = dev->private;
649 /* disable interrupts and pacing */
650 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
651 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
653 /* set multiplexer */
654 chan = CR_CHAN(insn->chanspec);
655 chan |= CR_CHAN(insn->chanspec) << 4;
656 outb(chan, dev->iobase + DAS16_MUX);
659 if (board->ai_pg != das16_pg_none) {
660 range = CR_RANGE(insn->chanspec);
661 outb((das16_gainlists[board->ai_pg])[range],
662 dev->iobase + DAS16_GAIN);
665 for (n = 0; n < insn->n; n++) {
668 /* trigger conversion */
669 outb_p(0, dev->iobase + DAS16_TRIG);
671 for (i = 0; i < DAS16_TIMEOUT; i++) {
672 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
675 if (i == DAS16_TIMEOUT) {
676 printk("das16: timeout\n");
680 val = inb(dev->iobase + DAS16_AI_MSB) << 8;
681 val |= inb(dev->iobase + DAS16_AI_LSB);
682 if (s->maxdata == 0x0fff)
692 static int das16_di_insn_bits(struct comedi_device *dev,
693 struct comedi_subdevice *s,
694 struct comedi_insn *insn,
697 data[1] = inb(dev->iobase + DAS16_DIO) & 0xf;
702 static int das16_do_insn_bits(struct comedi_device *dev,
703 struct comedi_subdevice *s,
704 struct comedi_insn *insn,
707 unsigned int mask = data[0];
708 unsigned int bits = data[1];
712 s->state |= (bits & mask);
714 outb(s->state, dev->iobase + DAS16_DIO);
722 static int das16_ao_insn_write(struct comedi_device *dev,
723 struct comedi_subdevice *s,
724 struct comedi_insn *insn,
727 unsigned int chan = CR_CHAN(insn->chanspec);
731 for (i = 0; i < insn->n; i++) {
735 outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan));
736 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan));
742 /* the pc104-das16jr (at least) has problems if the dma
743 transfer is interrupted in the middle of transferring
744 a 16 bit sample, so this function takes care to get
745 an even transfer count after disabling dma
748 static int disable_dma_on_even(struct comedi_device *dev)
750 struct das16_private_struct *devpriv = dev->private;
753 static const int disable_limit = 100;
754 static const int enable_timeout = 100;
756 disable_dma(devpriv->dma_chan);
757 residue = get_dma_residue(devpriv->dma_chan);
758 for (i = 0; i < disable_limit && (residue % 2); ++i) {
760 enable_dma(devpriv->dma_chan);
761 for (j = 0; j < enable_timeout; ++j) {
764 new_residue = get_dma_residue(devpriv->dma_chan);
765 if (new_residue != residue)
768 disable_dma(devpriv->dma_chan);
769 residue = get_dma_residue(devpriv->dma_chan);
771 if (i == disable_limit) {
772 comedi_error(dev, "failed to get an even dma transfer, "
773 "could be trouble.");
778 static void das16_interrupt(struct comedi_device *dev)
780 struct das16_private_struct *devpriv = dev->private;
781 unsigned long dma_flags, spin_flags;
782 struct comedi_subdevice *s = dev->read_subdev;
783 struct comedi_async *async;
784 struct comedi_cmd *cmd;
785 int num_bytes, residue;
788 if (!dev->attached) {
789 comedi_error(dev, "premature interrupt");
792 /* initialize async here to make sure it is not NULL */
796 spin_lock_irqsave(&dev->spinlock, spin_flags);
797 if ((devpriv->control_state & DMA_ENABLE) == 0) {
798 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
802 dma_flags = claim_dma_lock();
803 clear_dma_ff(devpriv->dma_chan);
804 residue = disable_dma_on_even(dev);
806 /* figure out how many points to read */
807 if (residue > devpriv->dma_transfer_size) {
808 comedi_error(dev, "residue > transfer size!\n");
809 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
812 num_bytes = devpriv->dma_transfer_size - residue;
814 if (cmd->stop_src == TRIG_COUNT &&
815 num_bytes >= devpriv->adc_byte_count) {
816 num_bytes = devpriv->adc_byte_count;
817 async->events |= COMEDI_CB_EOA;
820 buffer_index = devpriv->current_buffer;
821 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
822 devpriv->adc_byte_count -= num_bytes;
825 if ((async->events & COMEDI_CB_EOA) == 0) {
826 set_dma_addr(devpriv->dma_chan,
827 devpriv->dma_buffer_addr[devpriv->current_buffer]);
828 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
829 enable_dma(devpriv->dma_chan);
831 release_dma_lock(dma_flags);
833 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
835 cfc_write_array_to_buffer(s,
836 devpriv->dma_buffer[buffer_index], num_bytes);
838 cfc_handle_events(dev, s);
841 static void das16_timer_interrupt(unsigned long arg)
843 struct comedi_device *dev = (struct comedi_device *)arg;
844 struct das16_private_struct *devpriv = dev->private;
846 das16_interrupt(dev);
848 if (devpriv->timer_running)
849 mod_timer(&devpriv->timer, jiffies + timer_period());
852 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
854 const struct das16_board *board = comedi_board(dev);
857 /* diobits indicates boards */
858 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
860 printk(KERN_INFO " id bits are 0x%02x\n", diobits);
861 if (board->id != diobits) {
862 printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
869 static int das1600_mode_detect(struct comedi_device *dev)
871 struct das16_private_struct *devpriv = dev->private;
874 status = inb(dev->iobase + DAS1600_STATUS_B);
876 if (status & DAS1600_CLK_10MHZ) {
877 devpriv->clockbase = 100;
878 printk(KERN_INFO " 10MHz pacer clock\n");
880 devpriv->clockbase = 1000;
881 printk(KERN_INFO " 1MHz pacer clock\n");
887 static void das16_ai_munge(struct comedi_device *dev,
888 struct comedi_subdevice *s, void *array,
889 unsigned int num_bytes,
890 unsigned int start_chan_index)
892 unsigned int i, num_samples = num_bytes / sizeof(short);
895 for (i = 0; i < num_samples; i++) {
896 data[i] = le16_to_cpu(data[i]);
897 if (s->maxdata == 0x0fff)
899 data[i] &= s->maxdata;
909 * 3 Clock speed (in MHz)
911 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
913 const struct das16_board *board = comedi_board(dev);
914 struct das16_private_struct *devpriv;
915 struct comedi_subdevice *s;
916 struct comedi_krange *user_ai_range;
917 struct comedi_krange *user_ao_range;
918 unsigned int dma_chan = it->options[2];
922 /* check that clock setting is valid */
923 if (it->options[3]) {
924 if (it->options[3] != 0 &&
925 it->options[3] != 1 && it->options[3] != 10) {
927 ("\n Invalid option. Master clock must be set "
928 "to 1 or 10 (MHz)\n");
933 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
937 if (board->size < 0x400) {
938 ret = comedi_request_region(dev, it->options[0], board->size);
942 ret = comedi_request_region(dev, it->options[0], 0x10);
945 /* Request an additional region for the 8255 */
946 ret = __comedi_request_region(dev, dev->iobase + 0x400,
947 board->size & 0x3ff);
950 devpriv->extra_iobase = dev->iobase + 0x400;
951 devpriv->can_burst = 1;
954 /* probe id bits to make sure they are consistent */
955 if (das16_probe(dev, it)) {
956 printk(KERN_ERR " id bits do not match selected board, aborting\n");
960 /* get master clock speed */
961 if (devpriv->can_burst) {
962 das1600_mode_detect(dev);
965 devpriv->clockbase = 1000 / it->options[3];
967 devpriv->clockbase = 1000; /* 1 MHz default */
971 if (dma_chan == 1 || dma_chan == 3) {
975 if (request_dma(dma_chan, dev->board_name)) {
976 dev_err(dev->class_dev,
977 "failed to request dma channel %i\n",
981 devpriv->dma_chan = dma_chan;
983 /* allocate dma buffers */
984 for (i = 0; i < 2; i++) {
987 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
988 &devpriv->dma_buffer_addr[i]);
991 devpriv->dma_buffer[i] = p;
994 flags = claim_dma_lock();
995 disable_dma(devpriv->dma_chan);
996 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
997 release_dma_lock(flags);
999 init_timer(&(devpriv->timer));
1000 devpriv->timer.function = das16_timer_interrupt;
1001 devpriv->timer.data = (unsigned long)dev;
1004 /* get any user-defined input range */
1005 if (board->ai_pg == das16_pg_none &&
1006 (it->options[4] || it->options[5])) {
1007 /* allocate single-range range table */
1008 devpriv->user_ai_range_table =
1009 kmalloc(sizeof(struct comedi_lrange) +
1010 sizeof(struct comedi_krange), GFP_KERNEL);
1011 /* initialize ai range */
1012 devpriv->user_ai_range_table->length = 1;
1013 user_ai_range = devpriv->user_ai_range_table->range;
1014 user_ai_range->min = it->options[4];
1015 user_ai_range->max = it->options[5];
1016 user_ai_range->flags = UNIT_volt;
1018 /* get any user-defined output range */
1019 if (it->options[6] || it->options[7]) {
1020 /* allocate single-range range table */
1021 devpriv->user_ao_range_table =
1022 kmalloc(sizeof(struct comedi_lrange) +
1023 sizeof(struct comedi_krange), GFP_KERNEL);
1024 /* initialize ao range */
1025 devpriv->user_ao_range_table->length = 1;
1026 user_ao_range = devpriv->user_ao_range_table->range;
1027 user_ao_range->min = it->options[6];
1028 user_ao_range->max = it->options[7];
1029 user_ao_range->flags = UNIT_volt;
1032 ret = comedi_alloc_subdevices(dev, 5);
1036 status = inb(dev->iobase + DAS16_STATUS);
1038 /* Analog Input subdevice */
1039 s = &dev->subdevices[0];
1040 s->type = COMEDI_SUBD_AI;
1041 s->subdev_flags = SDF_READABLE;
1042 if (status & DAS16_MUXBIT) {
1043 s->subdev_flags |= SDF_GROUND;
1046 s->subdev_flags |= SDF_DIFF;
1049 s->len_chanlist = s->n_chan;
1050 s->maxdata = board->ai_maxdata;
1051 if (devpriv->user_ai_range_table) { /* user defined ai range */
1052 s->range_table = devpriv->user_ai_range_table;
1053 } else if (status & UNIPOLAR) {
1054 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1056 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1058 s->insn_read = das16_ai_insn_read;
1059 if (devpriv->dma_chan) {
1060 dev->read_subdev = s;
1061 s->subdev_flags |= SDF_CMD_READ;
1062 s->do_cmdtest = das16_cmd_test;
1063 s->do_cmd = das16_cmd_exec;
1064 s->cancel = das16_cancel;
1065 s->munge = das16_ai_munge;
1068 /* Analog Output subdevice */
1069 s = &dev->subdevices[1];
1070 if (board->has_ao) {
1071 s->type = COMEDI_SUBD_AO;
1072 s->subdev_flags = SDF_WRITABLE;
1074 s->maxdata = 0x0fff;
1075 if (devpriv->user_ao_range_table)
1076 s->range_table = devpriv->user_ao_range_table;
1078 s->range_table = &range_unknown;
1080 s->insn_write = das16_ao_insn_write;
1082 s->type = COMEDI_SUBD_UNUSED;
1085 /* Digital Input subdevice */
1086 s = &dev->subdevices[2];
1087 s->type = COMEDI_SUBD_DI;
1088 s->subdev_flags = SDF_READABLE;
1091 s->range_table = &range_digital;
1092 s->insn_bits = das16_di_insn_bits;
1094 /* Digital Output subdevice */
1095 s = &dev->subdevices[3];
1096 s->type = COMEDI_SUBD_DO;
1097 s->subdev_flags = SDF_WRITABLE;
1100 s->range_table = &range_digital;
1101 s->insn_bits = das16_do_insn_bits;
1103 /* initialize digital output lines */
1104 outb(s->state, dev->iobase + DAS16_DIO);
1106 s = &dev->subdevices[4];
1108 if (board->i8255_offset != 0) {
1109 subdev_8255_init(dev, s, NULL, (dev->iobase +
1110 board->i8255_offset));
1112 s->type = COMEDI_SUBD_UNUSED;
1116 /* set the interrupt level */
1117 devpriv->control_state = DAS16_IRQ(dev->irq);
1118 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1120 if (devpriv->can_burst) {
1121 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1122 outb(0, dev->iobase + DAS1600_CONV);
1123 outb(0, dev->iobase + DAS1600_BURST);
1129 static void das16_detach(struct comedi_device *dev)
1131 const struct das16_board *board = comedi_board(dev);
1132 struct das16_private_struct *devpriv = dev->private;
1137 for (i = 0; i < 2; i++) {
1138 if (devpriv->dma_buffer[i])
1139 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1140 devpriv->dma_buffer[i],
1142 dma_buffer_addr[i]);
1144 if (devpriv->dma_chan)
1145 free_dma(devpriv->dma_chan);
1146 kfree(devpriv->user_ai_range_table);
1147 kfree(devpriv->user_ao_range_table);
1149 if (devpriv->extra_iobase)
1150 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1151 comedi_legacy_detach(dev);
1154 static const struct das16_board das16_boards[] = {
1157 .ai_maxdata = 0x0fff,
1159 .ai_pg = das16_pg_none,
1161 .i8255_offset = 0x10,
1162 .i8254_offset = 0x0c,
1167 .ai_maxdata = 0x0fff,
1169 .ai_pg = das16_pg_none,
1171 .i8255_offset = 0x10,
1172 .i8254_offset = 0x0c,
1177 .ai_maxdata = 0x0fff,
1179 .ai_pg = das16_pg_none,
1181 .i8255_offset = 0x10,
1182 .i8254_offset = 0x0c,
1186 .name = "cio-das16",
1187 .ai_maxdata = 0x0fff,
1189 .ai_pg = das16_pg_none,
1191 .i8255_offset = 0x10,
1192 .i8254_offset = 0x0c,
1196 .name = "cio-das16/f",
1197 .ai_maxdata = 0x0fff,
1199 .ai_pg = das16_pg_none,
1201 .i8255_offset = 0x10,
1202 .i8254_offset = 0x0c,
1206 .name = "cio-das16/jr",
1207 .ai_maxdata = 0x0fff,
1209 .ai_pg = das16_pg_16jr,
1211 .i8254_offset = 0x0c,
1215 .name = "pc104-das16jr",
1216 .ai_maxdata = 0x0fff,
1218 .ai_pg = das16_pg_16jr,
1220 .i8254_offset = 0x0c,
1224 .name = "cio-das16jr/16",
1225 .ai_maxdata = 0xffff,
1227 .ai_pg = das16_pg_16jr_16,
1229 .i8254_offset = 0x0c,
1233 .name = "pc104-das16jr/16",
1234 .ai_maxdata = 0xffff,
1236 .ai_pg = das16_pg_16jr_16,
1238 .i8254_offset = 0x0c,
1243 .ai_maxdata = 0x0fff,
1245 .ai_pg = das16_pg_none,
1246 .i8255_offset = 0x400,
1247 .i8254_offset = 0x0c,
1252 .ai_maxdata = 0x0fff,
1254 .ai_pg = das16_pg_none,
1255 .i8255_offset = 0x400,
1256 .i8254_offset = 0x0c,
1261 .ai_maxdata = 0x0fff,
1263 .ai_pg = das16_pg_1601,
1264 .i8255_offset = 0x0,
1265 .i8254_offset = 0x0c,
1270 .ai_maxdata = 0x0fff,
1272 .ai_pg = das16_pg_1602,
1273 .i8255_offset = 0x0,
1274 .i8254_offset = 0x0c,
1279 .ai_maxdata = 0x0fff,
1281 .ai_pg = das16_pg_1601,
1283 .i8255_offset = 0x400,
1284 .i8254_offset = 0x0c,
1289 .ai_maxdata = 0x0fff,
1291 .ai_pg = das16_pg_1602,
1293 .i8255_offset = 0x400,
1294 .i8254_offset = 0x0c,
1298 .name = "cio-das1401/12",
1299 .ai_maxdata = 0x0fff,
1301 .ai_pg = das16_pg_1601,
1303 .i8254_offset = 0x0c,
1307 .name = "cio-das1402/12",
1308 .ai_maxdata = 0x0fff,
1310 .ai_pg = das16_pg_1602,
1312 .i8254_offset = 0x0c,
1316 .name = "cio-das1402/16",
1317 .ai_maxdata = 0xffff,
1319 .ai_pg = das16_pg_1602,
1321 .i8254_offset = 0x0c,
1325 .name = "cio-das1601/12",
1326 .ai_maxdata = 0x0fff,
1328 .ai_pg = das16_pg_1601,
1330 .i8255_offset = 0x400,
1331 .i8254_offset = 0x0c,
1335 .name = "cio-das1602/12",
1336 .ai_maxdata = 0x0fff,
1338 .ai_pg = das16_pg_1602,
1340 .i8255_offset = 0x400,
1341 .i8254_offset = 0x0c,
1345 .name = "cio-das1602/16",
1346 .ai_maxdata = 0xffff,
1348 .ai_pg = das16_pg_1602,
1350 .i8255_offset = 0x400,
1351 .i8254_offset = 0x0c,
1355 .name = "cio-das16/330",
1356 .ai_maxdata = 0x0fff,
1358 .ai_pg = das16_pg_16jr,
1360 .i8254_offset = 0x0c,
1366 static struct comedi_driver das16_driver = {
1367 .driver_name = "das16",
1368 .module = THIS_MODULE,
1369 .attach = das16_attach,
1370 .detach = das16_detach,
1371 .board_name = &das16_boards[0].name,
1372 .num_names = ARRAY_SIZE(das16_boards),
1373 .offset = sizeof(das16_boards[0]),
1375 module_comedi_driver(das16_driver);
1377 MODULE_AUTHOR("Comedi http://www.comedi.org");
1378 MODULE_DESCRIPTION("Comedi low-level driver");
1379 MODULE_LICENSE("GPL");