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; /* master clock speed in ns */
447 unsigned int ctrl_reg;
448 unsigned long adc_byte_count; /* number of bytes remaining */
449 /* divisor dividing master clock to get conversion frequency */
450 unsigned int divisor1;
451 /* divisor dividing master clock to get conversion frequency */
452 unsigned int divisor2;
453 unsigned int dma_chan; /* dma channel */
454 uint16_t *dma_buffer[2];
455 dma_addr_t dma_buffer_addr[2];
456 unsigned int current_buffer;
457 unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
459 * user-defined analog input and output ranges
460 * defined from config options
462 struct comedi_lrange *user_ai_range_table;
463 struct comedi_lrange *user_ao_range_table;
465 struct timer_list timer; /* for timed interrupt */
468 unsigned long extra_iobase;
469 unsigned int can_burst:1;
472 static void das16_ai_enable(struct comedi_device *dev,
473 unsigned int mode, unsigned int src)
475 struct das16_private_struct *devpriv = dev->private;
477 devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
479 DAS16_CTRL_PACING_MASK);
480 devpriv->ctrl_reg |= mode;
483 devpriv->ctrl_reg |= DAS16_CTRL_EXT_PACER;
485 devpriv->ctrl_reg |= DAS16_CTRL_INT_PACER;
486 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
489 static void das16_ai_disable(struct comedi_device *dev)
491 struct das16_private_struct *devpriv = dev->private;
493 /* disable interrupts, dma and pacer clocked conversions */
494 devpriv->ctrl_reg &= ~(DAS16_CTRL_INTE |
496 DAS16_CTRL_PACING_MASK);
497 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
500 /* the pc104-das16jr (at least) has problems if the dma
501 transfer is interrupted in the middle of transferring
502 a 16 bit sample, so this function takes care to get
503 an even transfer count after disabling dma
506 static int disable_dma_on_even(struct comedi_device *dev)
508 struct das16_private_struct *devpriv = dev->private;
511 static const int disable_limit = 100;
512 static const int enable_timeout = 100;
514 disable_dma(devpriv->dma_chan);
515 residue = get_dma_residue(devpriv->dma_chan);
516 for (i = 0; i < disable_limit && (residue % 2); ++i) {
518 enable_dma(devpriv->dma_chan);
519 for (j = 0; j < enable_timeout; ++j) {
522 new_residue = get_dma_residue(devpriv->dma_chan);
523 if (new_residue != residue)
526 disable_dma(devpriv->dma_chan);
527 residue = get_dma_residue(devpriv->dma_chan);
529 if (i == disable_limit) {
530 dev_err(dev->class_dev,
531 "failed to get an even dma transfer, could be trouble\n");
536 static void das16_interrupt(struct comedi_device *dev)
538 struct das16_private_struct *devpriv = dev->private;
539 struct comedi_subdevice *s = dev->read_subdev;
540 struct comedi_async *async = s->async;
541 struct comedi_cmd *cmd = &async->cmd;
542 unsigned long spin_flags;
543 unsigned long dma_flags;
544 int num_bytes, residue;
547 spin_lock_irqsave(&dev->spinlock, spin_flags);
548 if (!(devpriv->ctrl_reg & DAS16_CTRL_DMAE)) {
549 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
553 dma_flags = claim_dma_lock();
554 clear_dma_ff(devpriv->dma_chan);
555 residue = disable_dma_on_even(dev);
557 /* figure out how many points to read */
558 if (residue > devpriv->dma_transfer_size) {
559 dev_err(dev->class_dev, "residue > transfer size!\n");
560 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
563 num_bytes = devpriv->dma_transfer_size - residue;
565 if (cmd->stop_src == TRIG_COUNT &&
566 num_bytes >= devpriv->adc_byte_count) {
567 num_bytes = devpriv->adc_byte_count;
568 async->events |= COMEDI_CB_EOA;
571 buffer_index = devpriv->current_buffer;
572 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
573 devpriv->adc_byte_count -= num_bytes;
576 if ((async->events & COMEDI_CB_EOA) == 0) {
577 set_dma_addr(devpriv->dma_chan,
578 devpriv->dma_buffer_addr[devpriv->current_buffer]);
579 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
580 enable_dma(devpriv->dma_chan);
582 release_dma_lock(dma_flags);
584 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
586 cfc_write_array_to_buffer(s,
587 devpriv->dma_buffer[buffer_index], num_bytes);
589 cfc_handle_events(dev, s);
592 static void das16_timer_interrupt(unsigned long arg)
594 struct comedi_device *dev = (struct comedi_device *)arg;
595 struct das16_private_struct *devpriv = dev->private;
597 das16_interrupt(dev);
599 if (devpriv->timer_running)
600 mod_timer(&devpriv->timer, jiffies + timer_period());
603 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
604 struct comedi_cmd *cmd)
606 const struct das16_board *board = comedi_board(dev);
607 struct das16_private_struct *devpriv = dev->private;
609 int gain, start_chan, i;
612 /* Step 1 : check if triggers are trivially valid */
614 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
617 if (devpriv->can_burst)
618 mask |= TRIG_TIMER | TRIG_EXT;
619 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
621 tmp = cmd->convert_src;
622 mask = TRIG_TIMER | TRIG_EXT;
623 if (devpriv->can_burst)
625 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
627 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
628 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
633 /* Step 2a : make sure trigger sources are unique */
635 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
636 err |= cfc_check_trigger_is_unique(cmd->convert_src);
637 err |= cfc_check_trigger_is_unique(cmd->stop_src);
639 /* Step 2b : and mutually compatible */
641 /* make sure scan_begin_src and convert_src dont conflict */
642 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
644 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
650 /* Step 3: check if arguments are trivially valid */
652 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
654 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
655 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
657 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
659 /* check against maximum frequency */
660 if (cmd->scan_begin_src == TRIG_TIMER)
661 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
662 board->ai_speed * cmd->chanlist_len);
664 if (cmd->convert_src == TRIG_TIMER)
665 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
668 if (cmd->stop_src == TRIG_NONE)
669 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
674 /* step 4: fix up arguments */
675 if (cmd->scan_begin_src == TRIG_TIMER) {
676 unsigned int tmp = cmd->scan_begin_arg;
677 /* set divisors, correct timing arguments */
678 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
679 &(devpriv->divisor1),
680 &(devpriv->divisor2),
681 &(cmd->scan_begin_arg),
682 cmd->flags & TRIG_ROUND_MASK);
683 err += (tmp != cmd->scan_begin_arg);
685 if (cmd->convert_src == TRIG_TIMER) {
686 unsigned int tmp = cmd->convert_arg;
687 /* set divisors, correct timing arguments */
688 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
689 &(devpriv->divisor1),
690 &(devpriv->divisor2),
692 cmd->flags & TRIG_ROUND_MASK);
693 err += (tmp != cmd->convert_arg);
698 /* check channel/gain list against card's limitations */
700 gain = CR_RANGE(cmd->chanlist[0]);
701 start_chan = CR_CHAN(cmd->chanlist[0]);
702 for (i = 1; i < cmd->chanlist_len; i++) {
703 if (CR_CHAN(cmd->chanlist[i]) !=
704 (start_chan + i) % s->n_chan) {
705 dev_err(dev->class_dev,
706 "entries in chanlist must be consecutive channels, counting upwards\n");
709 if (CR_RANGE(cmd->chanlist[i]) != gain) {
710 dev_err(dev->class_dev,
711 "entries in chanlist must all have the same gain\n");
722 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
725 struct das16_private_struct *devpriv = dev->private;
726 unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
728 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
729 &(devpriv->divisor2), &ns,
730 rounding_flags & TRIG_ROUND_MASK);
732 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
733 i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
734 i8254_load(timer_base, 0, 2, devpriv->divisor2, 2);
739 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
741 const struct das16_board *board = comedi_board(dev);
742 struct das16_private_struct *devpriv = dev->private;
743 struct comedi_async *async = s->async;
744 struct comedi_cmd *cmd = &async->cmd;
749 if (cmd->flags & TRIG_RT) {
750 dev_err(dev->class_dev,
751 "isa dma transfers cannot be performed with TRIG_RT, aborting\n");
755 devpriv->adc_byte_count =
756 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
758 if (devpriv->can_burst)
759 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
761 /* set scan limits */
762 byte = CR_CHAN(cmd->chanlist[0]);
763 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
764 outb(byte, dev->iobase + DAS16_MUX_REG);
766 /* set gain (this is also burst rate register but according to
767 * computer boards manual, burst rate does nothing, even on
769 if (board->ai_pg != das16_pg_none) {
770 range = CR_RANGE(cmd->chanlist[0]);
771 outb((das16_gainlists[board->ai_pg])[range],
772 dev->iobase + DAS16_GAIN_REG);
775 /* set counter mode and counts */
777 das16_set_pacer(dev, cmd->convert_arg,
778 cmd->flags & TRIG_ROUND_MASK);
780 /* enable counters */
782 if (devpriv->can_burst) {
783 if (cmd->convert_src == TRIG_NOW) {
784 outb(DAS1600_BURST_VAL,
785 dev->iobase + DAS1600_BURST_REG);
786 /* set burst length */
787 byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
789 outb(0, dev->iobase + DAS1600_BURST_REG);
792 outb(byte, dev->iobase + DAS16_PACER_REG);
794 /* set up dma transfer */
795 flags = claim_dma_lock();
796 disable_dma(devpriv->dma_chan);
797 /* clear flip-flop to make sure 2-byte registers for
798 * count and address get set correctly */
799 clear_dma_ff(devpriv->dma_chan);
800 devpriv->current_buffer = 0;
801 set_dma_addr(devpriv->dma_chan,
802 devpriv->dma_buffer_addr[devpriv->current_buffer]);
803 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
804 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
805 enable_dma(devpriv->dma_chan);
806 release_dma_lock(flags);
808 /* set up interrupt */
809 devpriv->timer_running = 1;
810 devpriv->timer.expires = jiffies + timer_period();
811 add_timer(&devpriv->timer);
813 das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src);
815 if (devpriv->can_burst)
816 outb(0, dev->iobase + DAS1600_CONV_REG);
821 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
823 struct das16_private_struct *devpriv = dev->private;
826 spin_lock_irqsave(&dev->spinlock, flags);
828 das16_ai_disable(dev);
829 disable_dma(devpriv->dma_chan);
831 /* disable SW timer */
832 if (devpriv->timer_running) {
833 devpriv->timer_running = 0;
834 del_timer(&devpriv->timer);
837 if (devpriv->can_burst)
838 outb(0, dev->iobase + DAS1600_BURST_REG);
840 spin_unlock_irqrestore(&dev->spinlock, flags);
845 static void das16_ai_munge(struct comedi_device *dev,
846 struct comedi_subdevice *s, void *array,
847 unsigned int num_bytes,
848 unsigned int start_chan_index)
850 unsigned int i, num_samples = num_bytes / sizeof(short);
853 for (i = 0; i < num_samples; i++) {
854 data[i] = le16_to_cpu(data[i]);
855 if (s->maxdata == 0x0fff)
857 data[i] &= s->maxdata;
861 static int das16_ai_wait_for_conv(struct comedi_device *dev,
862 unsigned int timeout)
867 for (i = 0; i < timeout; i++) {
868 status = inb(dev->iobase + DAS16_STATUS_REG);
869 if (!(status & DAS16_STATUS_BUSY))
875 static int das16_ai_insn_read(struct comedi_device *dev,
876 struct comedi_subdevice *s,
877 struct comedi_insn *insn,
880 const struct das16_board *board = comedi_board(dev);
881 unsigned int chan = CR_CHAN(insn->chanspec);
882 unsigned int range = CR_RANGE(insn->chanspec);
887 das16_ai_disable(dev);
889 /* set multiplexer */
890 outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG);
893 if (board->ai_pg != das16_pg_none) {
894 outb((das16_gainlists[board->ai_pg])[range],
895 dev->iobase + DAS16_GAIN_REG);
898 for (i = 0; i < insn->n; i++) {
899 /* trigger conversion */
900 outb_p(0, dev->iobase + DAS16_TRIG_REG);
902 ret = das16_ai_wait_for_conv(dev, 1000);
906 val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
907 val |= inb(dev->iobase + DAS16_AI_LSB_REG);
908 if (s->maxdata == 0x0fff)
918 static int das16_ao_insn_write(struct comedi_device *dev,
919 struct comedi_subdevice *s,
920 struct comedi_insn *insn,
923 unsigned int chan = CR_CHAN(insn->chanspec);
927 for (i = 0; i < insn->n; i++) {
931 outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
932 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
938 static int das16_di_insn_bits(struct comedi_device *dev,
939 struct comedi_subdevice *s,
940 struct comedi_insn *insn,
943 data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
948 static int das16_do_insn_bits(struct comedi_device *dev,
949 struct comedi_subdevice *s,
950 struct comedi_insn *insn,
953 unsigned int mask = data[0];
954 unsigned int bits = data[1];
958 s->state |= (bits & mask);
960 outb(s->state, dev->iobase + DAS16_DIO_REG);
968 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
970 const struct das16_board *board = comedi_board(dev);
973 /* diobits indicates boards */
974 diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
975 if (board->id != diobits) {
976 dev_err(dev->class_dev,
977 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
985 static void das16_reset(struct comedi_device *dev)
987 outb(0, dev->iobase + DAS16_STATUS_REG);
988 outb(0, dev->iobase + DAS16_CTRL_REG);
989 outb(0, dev->iobase + DAS16_PACER_REG);
990 outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg);
993 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
995 const struct das16_board *board = comedi_board(dev);
996 struct das16_private_struct *devpriv;
997 struct comedi_subdevice *s;
998 struct comedi_krange *user_ai_range;
999 struct comedi_krange *user_ao_range;
1000 unsigned int dma_chan = it->options[2];
1001 unsigned int status;
1004 /* check that clock setting is valid */
1005 if (it->options[3]) {
1006 if (it->options[3] != 0 &&
1007 it->options[3] != 1 && it->options[3] != 10) {
1008 dev_err(dev->class_dev,
1009 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1014 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1018 if (board->size < 0x400) {
1019 ret = comedi_request_region(dev, it->options[0], board->size);
1023 ret = comedi_request_region(dev, it->options[0], 0x10);
1026 /* Request an additional region for the 8255 */
1027 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1028 board->size & 0x3ff);
1031 devpriv->extra_iobase = dev->iobase + 0x400;
1032 devpriv->can_burst = 1;
1035 /* probe id bits to make sure they are consistent */
1036 if (das16_probe(dev, it))
1039 /* get master clock speed */
1040 if (devpriv->can_burst) {
1041 status = inb(dev->iobase + DAS1600_STATUS_REG);
1043 if (status & DAS1600_STATUS_CLK_10MHZ)
1044 devpriv->clockbase = 100;
1046 devpriv->clockbase = 1000;
1049 devpriv->clockbase = 1000 / it->options[3];
1051 devpriv->clockbase = 1000; /* 1 MHz default */
1054 /* initialize dma */
1055 if (dma_chan == 1 || dma_chan == 3) {
1056 unsigned long flags;
1059 if (request_dma(dma_chan, dev->board_name)) {
1060 dev_err(dev->class_dev,
1061 "failed to request dma channel %i\n",
1065 devpriv->dma_chan = dma_chan;
1067 /* allocate dma buffers */
1068 for (i = 0; i < 2; i++) {
1071 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
1072 &devpriv->dma_buffer_addr[i]);
1075 devpriv->dma_buffer[i] = p;
1078 flags = claim_dma_lock();
1079 disable_dma(devpriv->dma_chan);
1080 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1081 release_dma_lock(flags);
1083 init_timer(&(devpriv->timer));
1084 devpriv->timer.function = das16_timer_interrupt;
1085 devpriv->timer.data = (unsigned long)dev;
1088 /* get any user-defined input range */
1089 if (board->ai_pg == das16_pg_none &&
1090 (it->options[4] || it->options[5])) {
1091 /* allocate single-range range table */
1092 devpriv->user_ai_range_table =
1093 kmalloc(sizeof(struct comedi_lrange) +
1094 sizeof(struct comedi_krange), GFP_KERNEL);
1095 /* initialize ai range */
1096 devpriv->user_ai_range_table->length = 1;
1097 user_ai_range = devpriv->user_ai_range_table->range;
1098 user_ai_range->min = it->options[4];
1099 user_ai_range->max = it->options[5];
1100 user_ai_range->flags = UNIT_volt;
1102 /* get any user-defined output range */
1103 if (it->options[6] || it->options[7]) {
1104 /* allocate single-range range table */
1105 devpriv->user_ao_range_table =
1106 kmalloc(sizeof(struct comedi_lrange) +
1107 sizeof(struct comedi_krange), GFP_KERNEL);
1108 /* initialize ao range */
1109 devpriv->user_ao_range_table->length = 1;
1110 user_ao_range = devpriv->user_ao_range_table->range;
1111 user_ao_range->min = it->options[6];
1112 user_ao_range->max = it->options[7];
1113 user_ao_range->flags = UNIT_volt;
1116 ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1120 status = inb(dev->iobase + DAS16_STATUS_REG);
1122 /* Analog Input subdevice */
1123 s = &dev->subdevices[0];
1124 s->type = COMEDI_SUBD_AI;
1125 s->subdev_flags = SDF_READABLE;
1126 if (status & DAS16_STATUS_MUXBIT) {
1127 s->subdev_flags |= SDF_GROUND;
1130 s->subdev_flags |= SDF_DIFF;
1133 s->len_chanlist = s->n_chan;
1134 s->maxdata = board->ai_maxdata;
1135 if (devpriv->user_ai_range_table) { /* user defined ai range */
1136 s->range_table = devpriv->user_ai_range_table;
1137 } else if (status & DAS16_STATUS_UNIPOLAR) {
1138 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1140 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1142 s->insn_read = das16_ai_insn_read;
1143 if (devpriv->dma_chan) {
1144 dev->read_subdev = s;
1145 s->subdev_flags |= SDF_CMD_READ;
1146 s->do_cmdtest = das16_cmd_test;
1147 s->do_cmd = das16_cmd_exec;
1148 s->cancel = das16_cancel;
1149 s->munge = das16_ai_munge;
1152 /* Analog Output subdevice */
1153 s = &dev->subdevices[1];
1154 if (board->has_ao) {
1155 s->type = COMEDI_SUBD_AO;
1156 s->subdev_flags = SDF_WRITABLE;
1158 s->maxdata = 0x0fff;
1159 if (devpriv->user_ao_range_table)
1160 s->range_table = devpriv->user_ao_range_table;
1162 s->range_table = &range_unknown;
1164 s->insn_write = das16_ao_insn_write;
1166 s->type = COMEDI_SUBD_UNUSED;
1169 /* Digital Input subdevice */
1170 s = &dev->subdevices[2];
1171 s->type = COMEDI_SUBD_DI;
1172 s->subdev_flags = SDF_READABLE;
1175 s->range_table = &range_digital;
1176 s->insn_bits = das16_di_insn_bits;
1178 /* Digital Output subdevice */
1179 s = &dev->subdevices[3];
1180 s->type = COMEDI_SUBD_DO;
1181 s->subdev_flags = SDF_WRITABLE;
1184 s->range_table = &range_digital;
1185 s->insn_bits = das16_do_insn_bits;
1187 /* initialize digital output lines */
1188 outb(s->state, dev->iobase + DAS16_DIO_REG);
1190 /* 8255 Digital I/O subdevice */
1191 if (board->has_8255) {
1192 s = &dev->subdevices[4];
1193 ret = subdev_8255_init(dev, s, NULL,
1194 dev->iobase + board->i8255_offset);
1200 /* set the interrupt level */
1201 devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1202 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1204 if (devpriv->can_burst) {
1205 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1206 outb(0, dev->iobase + DAS1600_CONV_REG);
1207 outb(0, dev->iobase + DAS1600_BURST_REG);
1213 static void das16_detach(struct comedi_device *dev)
1215 const struct das16_board *board = comedi_board(dev);
1216 struct das16_private_struct *devpriv = dev->private;
1221 for (i = 0; i < 2; i++) {
1222 if (devpriv->dma_buffer[i])
1223 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1224 devpriv->dma_buffer[i],
1226 dma_buffer_addr[i]);
1228 if (devpriv->dma_chan)
1229 free_dma(devpriv->dma_chan);
1230 kfree(devpriv->user_ai_range_table);
1231 kfree(devpriv->user_ao_range_table);
1233 if (devpriv->extra_iobase)
1234 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1235 comedi_legacy_detach(dev);
1238 static struct comedi_driver das16_driver = {
1239 .driver_name = "das16",
1240 .module = THIS_MODULE,
1241 .attach = das16_attach,
1242 .detach = das16_detach,
1243 .board_name = &das16_boards[0].name,
1244 .num_names = ARRAY_SIZE(das16_boards),
1245 .offset = sizeof(das16_boards[0]),
1247 module_comedi_driver(das16_driver);
1249 MODULE_AUTHOR("Comedi http://www.comedi.org");
1250 MODULE_DESCRIPTION("Comedi low-level driver");
1251 MODULE_LICENSE("GPL");