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_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
94 #define DAS16_TRIG_REG 0x00
95 #define DAS16_AI_LSB_REG 0x00
96 #define DAS16_AI_MSB_REG 0x01
97 #define DAS16_MUX_REG 0x02
98 #define DAS16_DIO_REG 0x03
99 #define DAS16_AO_LSB_REG(x) ((x) ? 0x06 : 0x04)
100 #define DAS16_AO_MSB_REG(x) ((x) ? 0x07 : 0x05)
101 #define DAS16_STATUS_REG 0x08
102 #define DAS16_STATUS_BUSY (1 << 7)
103 #define DAS16_STATUS_UNIPOLAR (1 << 6)
104 #define DAS16_STATUS_MUXBIT (1 << 5)
105 #define DAS16_STATUS_INT (1 << 4)
106 #define DAS16_CTRL_REG 0x09
107 #define DAS16_CTRL_INTE (1 << 7)
108 #define DAS16_CTRL_IRQ(x) (((x) & 0x7) << 4)
109 #define DAS16_CTRL_DMAE (1 << 2)
110 #define DAS16_CTRL_PACING_MASK (3 << 0)
111 #define DAS16_CTRL_INT_PACER (3 << 0)
112 #define DAS16_CTRL_EXT_PACER (2 << 0)
113 #define DAS16_CTRL_SOFT_PACER (0 << 0)
114 #define DAS16_PACER_REG 0x0a
115 #define DAS16_PACER_BURST_LEN(x) (((x) & 0xf) << 4)
116 #define DAS16_PACER_CTR0 (1 << 1)
117 #define DAS16_PACER_TRIG0 (1 << 0)
118 #define DAS16_GAIN_REG 0x0b
119 #define DAS16_TIMER_BASE_REG 0x0c /* to 0x0f */
121 #define DAS1600_CONV_REG 0x404
122 #define DAS1600_CONV_DISABLE (1 << 6)
123 #define DAS1600_BURST_REG 0x405
124 #define DAS1600_BURST_VAL (1 << 6)
125 #define DAS1600_ENABLE_REG 0x406
126 #define DAS1600_ENABLE_VAL (1 << 6)
127 #define DAS1600_STATUS_REG 0x407
128 #define DAS1600_STATUS_BME (1 << 6)
129 #define DAS1600_STATUS_ME (1 << 5)
130 #define DAS1600_STATUS_CD (1 << 4)
131 #define DAS1600_STATUS_WS (1 << 1)
132 #define DAS1600_STATUS_CLK_10MHZ (1 << 0)
134 static const struct comedi_lrange range_das1x01_bip = {
143 static const struct comedi_lrange range_das1x01_unip = {
152 static const struct comedi_lrange range_das1x02_bip = {
161 static const struct comedi_lrange range_das1x02_unip = {
170 static const struct comedi_lrange range_das16jr = {
184 static const struct comedi_lrange range_das16jr_16 = {
197 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
198 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
199 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
208 static const int *const das16_gainlists[] = {
216 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
224 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
234 unsigned int ai_maxdata;
235 unsigned int ai_speed; /* max conversion speed in nanosec */
237 unsigned int has_ao:1;
238 unsigned int has_8255:1;
240 unsigned int i8255_offset;
246 static const struct das16_board das16_boards[] = {
249 .ai_maxdata = 0x0fff,
251 .ai_pg = das16_pg_none,
254 .i8255_offset = 0x10,
259 .ai_maxdata = 0x0fff,
261 .ai_pg = das16_pg_none,
264 .i8255_offset = 0x10,
269 .ai_maxdata = 0x0fff,
271 .ai_pg = das16_pg_none,
274 .i8255_offset = 0x10,
279 .ai_maxdata = 0x0fff,
281 .ai_pg = das16_pg_none,
284 .i8255_offset = 0x10,
288 .name = "cio-das16/f",
289 .ai_maxdata = 0x0fff,
291 .ai_pg = das16_pg_none,
294 .i8255_offset = 0x10,
298 .name = "cio-das16/jr",
299 .ai_maxdata = 0x0fff,
301 .ai_pg = das16_pg_16jr,
305 .name = "pc104-das16jr",
306 .ai_maxdata = 0x0fff,
308 .ai_pg = das16_pg_16jr,
312 .name = "cio-das16jr/16",
313 .ai_maxdata = 0xffff,
315 .ai_pg = das16_pg_16jr_16,
319 .name = "pc104-das16jr/16",
320 .ai_maxdata = 0xffff,
322 .ai_pg = das16_pg_16jr_16,
327 .ai_maxdata = 0x0fff,
329 .ai_pg = das16_pg_none,
331 .i8255_offset = 0x400,
336 .ai_maxdata = 0x0fff,
338 .ai_pg = das16_pg_none,
340 .i8255_offset = 0x400,
345 .ai_maxdata = 0x0fff,
347 .ai_pg = das16_pg_1601,
352 .ai_maxdata = 0x0fff,
354 .ai_pg = das16_pg_1602,
359 .ai_maxdata = 0x0fff,
361 .ai_pg = das16_pg_1601,
364 .i8255_offset = 0x400,
369 .ai_maxdata = 0x0fff,
371 .ai_pg = das16_pg_1602,
374 .i8255_offset = 0x400,
378 .name = "cio-das1401/12",
379 .ai_maxdata = 0x0fff,
381 .ai_pg = das16_pg_1601,
385 .name = "cio-das1402/12",
386 .ai_maxdata = 0x0fff,
388 .ai_pg = das16_pg_1602,
392 .name = "cio-das1402/16",
393 .ai_maxdata = 0xffff,
395 .ai_pg = das16_pg_1602,
399 .name = "cio-das1601/12",
400 .ai_maxdata = 0x0fff,
402 .ai_pg = das16_pg_1601,
405 .i8255_offset = 0x400,
409 .name = "cio-das1602/12",
410 .ai_maxdata = 0x0fff,
412 .ai_pg = das16_pg_1602,
415 .i8255_offset = 0x400,
419 .name = "cio-das1602/16",
420 .ai_maxdata = 0xffff,
422 .ai_pg = das16_pg_1602,
425 .i8255_offset = 0x400,
429 .name = "cio-das16/330",
430 .ai_maxdata = 0x0fff,
432 .ai_pg = das16_pg_16jr,
438 /* Period for timer interrupt in jiffies. It's a function
439 * to deal with possibility of dynamic HZ patches */
440 static inline int timer_period(void)
445 struct das16_private_struct {
446 unsigned int clockbase;
447 unsigned int ctrl_reg;
448 unsigned long adc_byte_count;
449 unsigned int divisor1;
450 unsigned int divisor2;
451 unsigned int dma_chan;
452 uint16_t *dma_buffer[2];
453 dma_addr_t dma_buffer_addr[2];
454 unsigned int current_buffer;
455 unsigned int dma_transfer_size;
456 struct comedi_lrange *user_ai_range_table;
457 struct comedi_lrange *user_ao_range_table;
458 struct timer_list timer;
460 unsigned long extra_iobase;
461 unsigned int can_burst:1;
464 static void das16_ai_enable(struct comedi_device *dev,
465 unsigned int mode, unsigned int src)
467 struct das16_private_struct *devpriv = dev->private;
469 devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
471 DAS16_CTRL_PACING_MASK);
472 devpriv->ctrl_reg |= mode;
475 devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
477 devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
478 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
481 static void das16_ai_disable(struct comedi_device *dev)
483 struct das16_private_struct *devpriv = dev->private;
485 /* disable interrupts, dma and pacer clocked conversions */
486 devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
488 DAS16_CTRL_PACING_MASK);
489 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
492 /* the pc104-das16jr (at least) has problems if the dma
493 transfer is interrupted in the middle of transferring
494 a 16 bit sample, so this function takes care to get
495 an even transfer count after disabling dma
498 static int disable_dma_on_even(struct comedi_device *dev)
500 struct das16_private_struct *devpriv = dev->private;
503 static const int disable_limit = 100;
504 static const int enable_timeout = 100;
506 disable_dma(devpriv->dma_chan);
507 residue = get_dma_residue(devpriv->dma_chan);
508 for (i = 0; i < disable_limit && (residue % 2); ++i) {
510 enable_dma(devpriv->dma_chan);
511 for (j = 0; j < enable_timeout; ++j) {
514 new_residue = get_dma_residue(devpriv->dma_chan);
515 if (new_residue != residue)
518 disable_dma(devpriv->dma_chan);
519 residue = get_dma_residue(devpriv->dma_chan);
521 if (i == disable_limit) {
522 dev_err(dev->class_dev,
523 "failed to get an even dma transfer, could be trouble\n");
528 static void das16_interrupt(struct comedi_device *dev)
530 struct das16_private_struct *devpriv = dev->private;
531 struct comedi_subdevice *s = dev->read_subdev;
532 struct comedi_async *async = s->async;
533 struct comedi_cmd *cmd = &async->cmd;
534 unsigned long spin_flags;
535 unsigned long dma_flags;
536 int num_bytes, residue;
539 spin_lock_irqsave(&dev->spinlock, spin_flags);
540 if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
541 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
545 dma_flags = claim_dma_lock();
546 clear_dma_ff(devpriv->dma_chan);
547 residue = disable_dma_on_even(dev);
549 /* figure out how many points to read */
550 if (residue > devpriv->dma_transfer_size) {
551 dev_err(dev->class_dev, "residue > transfer size!\n");
552 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
555 num_bytes = devpriv->dma_transfer_size - residue;
557 if (cmd->stop_src == TRIG_COUNT &&
558 num_bytes >= devpriv->adc_byte_count) {
559 num_bytes = devpriv->adc_byte_count;
560 async->events |= COMEDI_CB_EOA;
563 buffer_index = devpriv->current_buffer;
564 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
565 devpriv->adc_byte_count -= num_bytes;
568 if ((async->events & COMEDI_CB_EOA) == 0) {
569 set_dma_addr(devpriv->dma_chan,
570 devpriv->dma_buffer_addr[devpriv->current_buffer]);
571 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
572 enable_dma(devpriv->dma_chan);
574 release_dma_lock(dma_flags);
576 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
578 cfc_write_array_to_buffer(s,
579 devpriv->dma_buffer[buffer_index], num_bytes);
581 cfc_handle_events(dev, s);
584 static void das16_timer_interrupt(unsigned long arg)
586 struct comedi_device *dev = (struct comedi_device *)arg;
587 struct das16_private_struct *devpriv = dev->private;
589 das16_interrupt(dev);
591 if (devpriv->timer_running)
592 mod_timer(&devpriv->timer, jiffies + timer_period());
595 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
596 struct comedi_cmd *cmd)
598 const struct das16_board *board = comedi_board(dev);
599 struct das16_private_struct *devpriv = dev->private;
601 int gain, start_chan, i;
604 /* Step 1 : check if triggers are trivially valid */
606 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
609 if (devpriv->can_burst)
610 mask |= TRIG_TIMER | TRIG_EXT;
611 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
613 tmp = cmd->convert_src;
614 mask = TRIG_TIMER | TRIG_EXT;
615 if (devpriv->can_burst)
617 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
619 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
620 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
625 /* Step 2a : make sure trigger sources are unique */
627 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
628 err |= cfc_check_trigger_is_unique(cmd->convert_src);
629 err |= cfc_check_trigger_is_unique(cmd->stop_src);
631 /* Step 2b : and mutually compatible */
633 /* make sure scan_begin_src and convert_src dont conflict */
634 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
636 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
642 /* Step 3: check if arguments are trivially valid */
644 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
646 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
647 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
649 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
651 /* check against maximum frequency */
652 if (cmd->scan_begin_src == TRIG_TIMER)
653 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
654 board->ai_speed * cmd->chanlist_len);
656 if (cmd->convert_src == TRIG_TIMER)
657 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
660 if (cmd->stop_src == TRIG_NONE)
661 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
666 /* step 4: fix up arguments */
667 if (cmd->scan_begin_src == TRIG_TIMER) {
668 unsigned int tmp = cmd->scan_begin_arg;
669 /* set divisors, correct timing arguments */
670 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
671 &(devpriv->divisor1),
672 &(devpriv->divisor2),
673 &(cmd->scan_begin_arg),
674 cmd->flags & TRIG_ROUND_MASK);
675 err += (tmp != cmd->scan_begin_arg);
677 if (cmd->convert_src == TRIG_TIMER) {
678 unsigned int tmp = cmd->convert_arg;
679 /* set divisors, correct timing arguments */
680 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
681 &(devpriv->divisor1),
682 &(devpriv->divisor2),
684 cmd->flags & TRIG_ROUND_MASK);
685 err += (tmp != cmd->convert_arg);
690 /* check channel/gain list against card's limitations */
692 gain = CR_RANGE(cmd->chanlist[0]);
693 start_chan = CR_CHAN(cmd->chanlist[0]);
694 for (i = 1; i < cmd->chanlist_len; i++) {
695 if (CR_CHAN(cmd->chanlist[i]) !=
696 (start_chan + i) % s->n_chan) {
697 dev_err(dev->class_dev,
698 "entries in chanlist must be consecutive channels, counting upwards\n");
701 if (CR_RANGE(cmd->chanlist[i]) != gain) {
702 dev_err(dev->class_dev,
703 "entries in chanlist must all have the same gain\n");
714 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
717 struct das16_private_struct *devpriv = dev->private;
718 unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
720 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
721 &(devpriv->divisor2), &ns,
722 rounding_flags & TRIG_ROUND_MASK);
724 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
725 i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
726 i8254_load(timer_base, 0, 2, devpriv->divisor2, 2);
731 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
733 const struct das16_board *board = comedi_board(dev);
734 struct das16_private_struct *devpriv = dev->private;
735 struct comedi_async *async = s->async;
736 struct comedi_cmd *cmd = &async->cmd;
741 if (cmd->flags & TRIG_RT) {
742 dev_err(dev->class_dev,
743 "isa dma transfers cannot be performed with TRIG_RT, aborting\n");
747 devpriv->adc_byte_count =
748 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
750 if (devpriv->can_burst)
751 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
753 /* set scan limits */
754 byte = CR_CHAN(cmd->chanlist[0]);
755 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
756 outb(byte, dev->iobase + DAS16_MUX_REG);
758 /* set gain (this is also burst rate register but according to
759 * computer boards manual, burst rate does nothing, even on
761 if (board->ai_pg != das16_pg_none) {
762 range = CR_RANGE(cmd->chanlist[0]);
763 outb((das16_gainlists[board->ai_pg])[range],
764 dev->iobase + DAS16_GAIN_REG);
767 /* set counter mode and counts */
769 das16_set_pacer(dev, cmd->convert_arg,
770 cmd->flags & TRIG_ROUND_MASK);
772 /* enable counters */
774 if (devpriv->can_burst) {
775 if (cmd->convert_src == TRIG_NOW) {
776 outb(DAS1600_BURST_VAL,
777 dev->iobase + DAS1600_BURST_REG);
778 /* set burst length */
779 byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
781 outb(0, dev->iobase + DAS1600_BURST_REG);
784 outb(byte, dev->iobase + DAS16_PACER_REG);
786 /* set up dma transfer */
787 flags = claim_dma_lock();
788 disable_dma(devpriv->dma_chan);
789 /* clear flip-flop to make sure 2-byte registers for
790 * count and address get set correctly */
791 clear_dma_ff(devpriv->dma_chan);
792 devpriv->current_buffer = 0;
793 set_dma_addr(devpriv->dma_chan,
794 devpriv->dma_buffer_addr[devpriv->current_buffer]);
795 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
796 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
797 enable_dma(devpriv->dma_chan);
798 release_dma_lock(flags);
800 /* set up interrupt */
801 devpriv->timer_running = 1;
802 devpriv->timer.expires = jiffies + timer_period();
803 add_timer(&devpriv->timer);
805 das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src);
807 if (devpriv->can_burst)
808 outb(0, dev->iobase + DAS1600_CONV_REG);
813 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
815 struct das16_private_struct *devpriv = dev->private;
818 spin_lock_irqsave(&dev->spinlock, flags);
820 das16_ai_disable(dev);
821 disable_dma(devpriv->dma_chan);
823 /* disable SW timer */
824 if (devpriv->timer_running) {
825 devpriv->timer_running = 0;
826 del_timer(&devpriv->timer);
829 if (devpriv->can_burst)
830 outb(0, dev->iobase + DAS1600_BURST_REG);
832 spin_unlock_irqrestore(&dev->spinlock, flags);
837 static void das16_ai_munge(struct comedi_device *dev,
838 struct comedi_subdevice *s, void *array,
839 unsigned int num_bytes,
840 unsigned int start_chan_index)
842 unsigned int i, num_samples = num_bytes / sizeof(short);
845 for (i = 0; i < num_samples; i++) {
846 data[i] = le16_to_cpu(data[i]);
847 if (s->maxdata == 0x0fff)
849 data[i] &= s->maxdata;
853 static int das16_ai_wait_for_conv(struct comedi_device *dev,
854 unsigned int timeout)
859 for (i = 0; i < timeout; i++) {
860 status = inb(dev->iobase + DAS16_STATUS_REG);
861 if (!(status & DAS16_STATUS_BUSY))
867 static int das16_ai_insn_read(struct comedi_device *dev,
868 struct comedi_subdevice *s,
869 struct comedi_insn *insn,
872 const struct das16_board *board = comedi_board(dev);
873 unsigned int chan = CR_CHAN(insn->chanspec);
874 unsigned int range = CR_RANGE(insn->chanspec);
879 das16_ai_disable(dev);
881 /* set multiplexer */
882 outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG);
885 if (board->ai_pg != das16_pg_none) {
886 outb((das16_gainlists[board->ai_pg])[range],
887 dev->iobase + DAS16_GAIN_REG);
890 for (i = 0; i < insn->n; i++) {
891 /* trigger conversion */
892 outb_p(0, dev->iobase + DAS16_TRIG_REG);
894 ret = das16_ai_wait_for_conv(dev, 1000);
898 val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
899 val |= inb(dev->iobase + DAS16_AI_LSB_REG);
900 if (s->maxdata == 0x0fff)
910 static int das16_ao_insn_write(struct comedi_device *dev,
911 struct comedi_subdevice *s,
912 struct comedi_insn *insn,
915 unsigned int chan = CR_CHAN(insn->chanspec);
919 for (i = 0; i < insn->n; i++) {
923 outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
924 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
930 static int das16_di_insn_bits(struct comedi_device *dev,
931 struct comedi_subdevice *s,
932 struct comedi_insn *insn,
935 data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
940 static int das16_do_insn_bits(struct comedi_device *dev,
941 struct comedi_subdevice *s,
942 struct comedi_insn *insn,
945 unsigned int mask = data[0];
946 unsigned int bits = data[1];
950 s->state |= (bits & mask);
952 outb(s->state, dev->iobase + DAS16_DIO_REG);
960 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
962 const struct das16_board *board = comedi_board(dev);
965 /* diobits indicates boards */
966 diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
967 if (board->id != diobits) {
968 dev_err(dev->class_dev,
969 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
977 static void das16_reset(struct comedi_device *dev)
979 outb(0, dev->iobase + DAS16_STATUS_REG);
980 outb(0, dev->iobase + DAS16_CTRL_REG);
981 outb(0, dev->iobase + DAS16_PACER_REG);
982 outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg);
985 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
987 const struct das16_board *board = comedi_board(dev);
988 struct das16_private_struct *devpriv;
989 struct comedi_subdevice *s;
990 struct comedi_krange *user_ai_range;
991 struct comedi_krange *user_ao_range;
992 unsigned int dma_chan = it->options[2];
996 /* check that clock setting is valid */
997 if (it->options[3]) {
998 if (it->options[3] != 0 &&
999 it->options[3] != 1 && it->options[3] != 10) {
1000 dev_err(dev->class_dev,
1001 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1006 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1010 if (board->size < 0x400) {
1011 ret = comedi_request_region(dev, it->options[0], board->size);
1015 ret = comedi_request_region(dev, it->options[0], 0x10);
1018 /* Request an additional region for the 8255 */
1019 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1020 board->size & 0x3ff);
1023 devpriv->extra_iobase = dev->iobase + 0x400;
1024 devpriv->can_burst = 1;
1027 /* probe id bits to make sure they are consistent */
1028 if (das16_probe(dev, it))
1031 /* get master clock speed */
1032 if (devpriv->can_burst) {
1033 status = inb(dev->iobase + DAS1600_STATUS_REG);
1035 if (status & DAS1600_STATUS_CLK_10MHZ)
1036 devpriv->clockbase = 100;
1038 devpriv->clockbase = 1000;
1041 devpriv->clockbase = 1000 / it->options[3];
1043 devpriv->clockbase = 1000; /* 1 MHz default */
1046 /* initialize dma */
1047 if (dma_chan == 1 || dma_chan == 3) {
1048 unsigned long flags;
1051 if (request_dma(dma_chan, dev->board_name)) {
1052 dev_err(dev->class_dev,
1053 "failed to request dma channel %i\n",
1057 devpriv->dma_chan = dma_chan;
1059 /* allocate dma buffers */
1060 for (i = 0; i < 2; i++) {
1063 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
1064 &devpriv->dma_buffer_addr[i]);
1067 devpriv->dma_buffer[i] = p;
1070 flags = claim_dma_lock();
1071 disable_dma(devpriv->dma_chan);
1072 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1073 release_dma_lock(flags);
1075 init_timer(&(devpriv->timer));
1076 devpriv->timer.function = das16_timer_interrupt;
1077 devpriv->timer.data = (unsigned long)dev;
1080 /* get any user-defined input range */
1081 if (board->ai_pg == das16_pg_none &&
1082 (it->options[4] || it->options[5])) {
1083 /* allocate single-range range table */
1084 devpriv->user_ai_range_table =
1085 kmalloc(sizeof(struct comedi_lrange) +
1086 sizeof(struct comedi_krange), GFP_KERNEL);
1087 /* initialize ai range */
1088 devpriv->user_ai_range_table->length = 1;
1089 user_ai_range = devpriv->user_ai_range_table->range;
1090 user_ai_range->min = it->options[4];
1091 user_ai_range->max = it->options[5];
1092 user_ai_range->flags = UNIT_volt;
1094 /* get any user-defined output range */
1095 if (it->options[6] || it->options[7]) {
1096 /* allocate single-range range table */
1097 devpriv->user_ao_range_table =
1098 kmalloc(sizeof(struct comedi_lrange) +
1099 sizeof(struct comedi_krange), GFP_KERNEL);
1100 /* initialize ao range */
1101 devpriv->user_ao_range_table->length = 1;
1102 user_ao_range = devpriv->user_ao_range_table->range;
1103 user_ao_range->min = it->options[6];
1104 user_ao_range->max = it->options[7];
1105 user_ao_range->flags = UNIT_volt;
1108 ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1112 status = inb(dev->iobase + DAS16_STATUS_REG);
1114 /* Analog Input subdevice */
1115 s = &dev->subdevices[0];
1116 s->type = COMEDI_SUBD_AI;
1117 s->subdev_flags = SDF_READABLE;
1118 if (status & DAS16_STATUS_MUXBIT) {
1119 s->subdev_flags |= SDF_GROUND;
1122 s->subdev_flags |= SDF_DIFF;
1125 s->len_chanlist = s->n_chan;
1126 s->maxdata = board->ai_maxdata;
1127 if (devpriv->user_ai_range_table) { /* user defined ai range */
1128 s->range_table = devpriv->user_ai_range_table;
1129 } else if (status & DAS16_STATUS_UNIPOLAR) {
1130 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1132 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1134 s->insn_read = das16_ai_insn_read;
1135 if (devpriv->dma_chan) {
1136 dev->read_subdev = s;
1137 s->subdev_flags |= SDF_CMD_READ;
1138 s->do_cmdtest = das16_cmd_test;
1139 s->do_cmd = das16_cmd_exec;
1140 s->cancel = das16_cancel;
1141 s->munge = das16_ai_munge;
1144 /* Analog Output subdevice */
1145 s = &dev->subdevices[1];
1146 if (board->has_ao) {
1147 s->type = COMEDI_SUBD_AO;
1148 s->subdev_flags = SDF_WRITABLE;
1150 s->maxdata = 0x0fff;
1151 if (devpriv->user_ao_range_table)
1152 s->range_table = devpriv->user_ao_range_table;
1154 s->range_table = &range_unknown;
1156 s->insn_write = das16_ao_insn_write;
1158 s->type = COMEDI_SUBD_UNUSED;
1161 /* Digital Input subdevice */
1162 s = &dev->subdevices[2];
1163 s->type = COMEDI_SUBD_DI;
1164 s->subdev_flags = SDF_READABLE;
1167 s->range_table = &range_digital;
1168 s->insn_bits = das16_di_insn_bits;
1170 /* Digital Output subdevice */
1171 s = &dev->subdevices[3];
1172 s->type = COMEDI_SUBD_DO;
1173 s->subdev_flags = SDF_WRITABLE;
1176 s->range_table = &range_digital;
1177 s->insn_bits = das16_do_insn_bits;
1179 /* initialize digital output lines */
1180 outb(s->state, dev->iobase + DAS16_DIO_REG);
1182 /* 8255 Digital I/O subdevice */
1183 if (board->has_8255) {
1184 s = &dev->subdevices[4];
1185 ret = subdev_8255_init(dev, s, NULL,
1186 dev->iobase + board->i8255_offset);
1192 /* set the interrupt level */
1193 devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1194 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1196 if (devpriv->can_burst) {
1197 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1198 outb(0, dev->iobase + DAS1600_CONV_REG);
1199 outb(0, dev->iobase + DAS1600_BURST_REG);
1205 static void das16_detach(struct comedi_device *dev)
1207 const struct das16_board *board = comedi_board(dev);
1208 struct das16_private_struct *devpriv = dev->private;
1213 for (i = 0; i < 2; i++) {
1214 if (devpriv->dma_buffer[i])
1215 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1216 devpriv->dma_buffer[i],
1218 dma_buffer_addr[i]);
1220 if (devpriv->dma_chan)
1221 free_dma(devpriv->dma_chan);
1222 kfree(devpriv->user_ai_range_table);
1223 kfree(devpriv->user_ao_range_table);
1225 if (devpriv->extra_iobase)
1226 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1227 comedi_legacy_detach(dev);
1230 static struct comedi_driver das16_driver = {
1231 .driver_name = "das16",
1232 .module = THIS_MODULE,
1233 .attach = das16_attach,
1234 .detach = das16_detach,
1235 .board_name = &das16_boards[0].name,
1236 .num_names = ARRAY_SIZE(das16_boards),
1237 .offset = sizeof(das16_boards[0]),
1239 module_comedi_driver(das16_driver);
1241 MODULE_AUTHOR("Comedi http://www.comedi.org");
1242 MODULE_DESCRIPTION("Comedi driver for DAS16 compatible boards");
1243 MODULE_LICENSE("GPL");