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 comedi_error(dev, "failed to get an even dma transfer, "
531 "could be trouble.");
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 comedi_error(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) {
706 "entries in chanlist must be "
707 "consecutive channels, "
708 "counting upwards\n");
711 if (CR_RANGE(cmd->chanlist[i]) != gain) {
713 "entries in chanlist must all "
714 "have the same gain\n");
725 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
728 struct das16_private_struct *devpriv = dev->private;
729 unsigned long timer_base = dev->iobase + DAS16_TIMER_BASE_REG;
731 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
732 &(devpriv->divisor2), &ns,
733 rounding_flags & TRIG_ROUND_MASK);
735 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
736 i8254_load(timer_base, 0, 1, devpriv->divisor1, 2);
737 i8254_load(timer_base, 0, 2, devpriv->divisor2, 2);
742 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
744 const struct das16_board *board = comedi_board(dev);
745 struct das16_private_struct *devpriv = dev->private;
746 struct comedi_async *async = s->async;
747 struct comedi_cmd *cmd = &async->cmd;
752 if (cmd->flags & TRIG_RT) {
753 comedi_error(dev, "isa dma transfers cannot be performed with "
754 "TRIG_RT, aborting");
758 devpriv->adc_byte_count =
759 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
761 if (devpriv->can_burst)
762 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV_REG);
764 /* set scan limits */
765 byte = CR_CHAN(cmd->chanlist[0]);
766 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
767 outb(byte, dev->iobase + DAS16_MUX_REG);
769 /* set gain (this is also burst rate register but according to
770 * computer boards manual, burst rate does nothing, even on
772 if (board->ai_pg != das16_pg_none) {
773 range = CR_RANGE(cmd->chanlist[0]);
774 outb((das16_gainlists[board->ai_pg])[range],
775 dev->iobase + DAS16_GAIN_REG);
778 /* set counter mode and counts */
780 das16_set_pacer(dev, cmd->convert_arg,
781 cmd->flags & TRIG_ROUND_MASK);
783 /* enable counters */
785 if (devpriv->can_burst) {
786 if (cmd->convert_src == TRIG_NOW) {
787 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST_REG);
788 /* set burst length */
789 byte |= DAS16_PACER_BURST_LEN(cmd->chanlist_len - 1);
791 outb(0, dev->iobase + DAS1600_BURST_REG);
794 outb(byte, dev->iobase + DAS16_PACER_REG);
796 /* set up dma transfer */
797 flags = claim_dma_lock();
798 disable_dma(devpriv->dma_chan);
799 /* clear flip-flop to make sure 2-byte registers for
800 * count and address get set correctly */
801 clear_dma_ff(devpriv->dma_chan);
802 devpriv->current_buffer = 0;
803 set_dma_addr(devpriv->dma_chan,
804 devpriv->dma_buffer_addr[devpriv->current_buffer]);
805 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
806 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
807 enable_dma(devpriv->dma_chan);
808 release_dma_lock(flags);
810 /* set up interrupt */
811 devpriv->timer_running = 1;
812 devpriv->timer.expires = jiffies + timer_period();
813 add_timer(&devpriv->timer);
815 das16_ai_enable(dev, DAS16_CTRL_DMAE, cmd->convert_src);
817 if (devpriv->can_burst)
818 outb(0, dev->iobase + DAS1600_CONV_REG);
823 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
825 struct das16_private_struct *devpriv = dev->private;
828 spin_lock_irqsave(&dev->spinlock, flags);
830 das16_ai_disable(dev);
831 disable_dma(devpriv->dma_chan);
833 /* disable SW timer */
834 if (devpriv->timer_running) {
835 devpriv->timer_running = 0;
836 del_timer(&devpriv->timer);
839 if (devpriv->can_burst)
840 outb(0, dev->iobase + DAS1600_BURST_REG);
842 spin_unlock_irqrestore(&dev->spinlock, flags);
847 static void das16_ai_munge(struct comedi_device *dev,
848 struct comedi_subdevice *s, void *array,
849 unsigned int num_bytes,
850 unsigned int start_chan_index)
852 unsigned int i, num_samples = num_bytes / sizeof(short);
855 for (i = 0; i < num_samples; i++) {
856 data[i] = le16_to_cpu(data[i]);
857 if (s->maxdata == 0x0fff)
859 data[i] &= s->maxdata;
863 static int das16_ai_wait_for_conv(struct comedi_device *dev,
864 unsigned int timeout)
869 for (i = 0; i < timeout; i++) {
870 status = inb(dev->iobase + DAS16_STATUS_REG);
871 if (!(status & DAS16_STATUS_BUSY))
877 static int das16_ai_insn_read(struct comedi_device *dev,
878 struct comedi_subdevice *s,
879 struct comedi_insn *insn,
882 const struct das16_board *board = comedi_board(dev);
883 unsigned int chan = CR_CHAN(insn->chanspec);
884 unsigned int range = CR_RANGE(insn->chanspec);
889 das16_ai_disable(dev);
891 /* set multiplexer */
892 outb(chan | (chan << 4), dev->iobase + DAS16_MUX_REG);
895 if (board->ai_pg != das16_pg_none) {
896 outb((das16_gainlists[board->ai_pg])[range],
897 dev->iobase + DAS16_GAIN_REG);
900 for (i = 0; i < insn->n; i++) {
901 /* trigger conversion */
902 outb_p(0, dev->iobase + DAS16_TRIG_REG);
904 ret = das16_ai_wait_for_conv(dev, 1000);
908 val = inb(dev->iobase + DAS16_AI_MSB_REG) << 8;
909 val |= inb(dev->iobase + DAS16_AI_LSB_REG);
910 if (s->maxdata == 0x0fff)
920 static int das16_ao_insn_write(struct comedi_device *dev,
921 struct comedi_subdevice *s,
922 struct comedi_insn *insn,
925 unsigned int chan = CR_CHAN(insn->chanspec);
929 for (i = 0; i < insn->n; i++) {
933 outb(val & 0xff, dev->iobase + DAS16_AO_LSB_REG(chan));
934 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB_REG(chan));
940 static int das16_di_insn_bits(struct comedi_device *dev,
941 struct comedi_subdevice *s,
942 struct comedi_insn *insn,
945 data[1] = inb(dev->iobase + DAS16_DIO_REG) & 0xf;
950 static int das16_do_insn_bits(struct comedi_device *dev,
951 struct comedi_subdevice *s,
952 struct comedi_insn *insn,
955 unsigned int mask = data[0];
956 unsigned int bits = data[1];
960 s->state |= (bits & mask);
962 outb(s->state, dev->iobase + DAS16_DIO_REG);
970 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
972 const struct das16_board *board = comedi_board(dev);
975 /* diobits indicates boards */
976 diobits = inb(dev->iobase + DAS16_DIO_REG) & 0xf0;
977 if (board->id != diobits) {
978 dev_err(dev->class_dev,
979 "requested board's id bits are incorrect (0x%x != 0x%x)\n",
987 static void das16_reset(struct comedi_device *dev)
989 outb(0, dev->iobase + DAS16_STATUS_REG);
990 outb(0, dev->iobase + DAS16_CTRL_REG);
991 outb(0, dev->iobase + DAS16_PACER_REG);
992 outb(0, dev->iobase + DAS16_TIMER_BASE_REG + i8254_control_reg);
995 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
997 const struct das16_board *board = comedi_board(dev);
998 struct das16_private_struct *devpriv;
999 struct comedi_subdevice *s;
1000 struct comedi_krange *user_ai_range;
1001 struct comedi_krange *user_ao_range;
1002 unsigned int dma_chan = it->options[2];
1003 unsigned int status;
1006 /* check that clock setting is valid */
1007 if (it->options[3]) {
1008 if (it->options[3] != 0 &&
1009 it->options[3] != 1 && it->options[3] != 10) {
1010 dev_err(dev->class_dev,
1011 "Invalid option. Master clock must be set to 1 or 10 (MHz)\n");
1016 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1020 if (board->size < 0x400) {
1021 ret = comedi_request_region(dev, it->options[0], board->size);
1025 ret = comedi_request_region(dev, it->options[0], 0x10);
1028 /* Request an additional region for the 8255 */
1029 ret = __comedi_request_region(dev, dev->iobase + 0x400,
1030 board->size & 0x3ff);
1033 devpriv->extra_iobase = dev->iobase + 0x400;
1034 devpriv->can_burst = 1;
1037 /* probe id bits to make sure they are consistent */
1038 if (das16_probe(dev, it))
1041 /* get master clock speed */
1042 if (devpriv->can_burst) {
1043 status = inb(dev->iobase + DAS1600_STATUS_REG);
1045 if (status & DAS1600_STATUS_CLK_10MHZ)
1046 devpriv->clockbase = 100;
1048 devpriv->clockbase = 1000;
1051 devpriv->clockbase = 1000 / it->options[3];
1053 devpriv->clockbase = 1000; /* 1 MHz default */
1056 /* initialize dma */
1057 if (dma_chan == 1 || dma_chan == 3) {
1058 unsigned long flags;
1061 if (request_dma(dma_chan, dev->board_name)) {
1062 dev_err(dev->class_dev,
1063 "failed to request dma channel %i\n",
1067 devpriv->dma_chan = dma_chan;
1069 /* allocate dma buffers */
1070 for (i = 0; i < 2; i++) {
1073 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
1074 &devpriv->dma_buffer_addr[i]);
1077 devpriv->dma_buffer[i] = p;
1080 flags = claim_dma_lock();
1081 disable_dma(devpriv->dma_chan);
1082 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1083 release_dma_lock(flags);
1085 init_timer(&(devpriv->timer));
1086 devpriv->timer.function = das16_timer_interrupt;
1087 devpriv->timer.data = (unsigned long)dev;
1090 /* get any user-defined input range */
1091 if (board->ai_pg == das16_pg_none &&
1092 (it->options[4] || it->options[5])) {
1093 /* allocate single-range range table */
1094 devpriv->user_ai_range_table =
1095 kmalloc(sizeof(struct comedi_lrange) +
1096 sizeof(struct comedi_krange), GFP_KERNEL);
1097 /* initialize ai range */
1098 devpriv->user_ai_range_table->length = 1;
1099 user_ai_range = devpriv->user_ai_range_table->range;
1100 user_ai_range->min = it->options[4];
1101 user_ai_range->max = it->options[5];
1102 user_ai_range->flags = UNIT_volt;
1104 /* get any user-defined output range */
1105 if (it->options[6] || it->options[7]) {
1106 /* allocate single-range range table */
1107 devpriv->user_ao_range_table =
1108 kmalloc(sizeof(struct comedi_lrange) +
1109 sizeof(struct comedi_krange), GFP_KERNEL);
1110 /* initialize ao range */
1111 devpriv->user_ao_range_table->length = 1;
1112 user_ao_range = devpriv->user_ao_range_table->range;
1113 user_ao_range->min = it->options[6];
1114 user_ao_range->max = it->options[7];
1115 user_ao_range->flags = UNIT_volt;
1118 ret = comedi_alloc_subdevices(dev, 4 + board->has_8255);
1122 status = inb(dev->iobase + DAS16_STATUS_REG);
1124 /* Analog Input subdevice */
1125 s = &dev->subdevices[0];
1126 s->type = COMEDI_SUBD_AI;
1127 s->subdev_flags = SDF_READABLE;
1128 if (status & DAS16_STATUS_MUXBIT) {
1129 s->subdev_flags |= SDF_GROUND;
1132 s->subdev_flags |= SDF_DIFF;
1135 s->len_chanlist = s->n_chan;
1136 s->maxdata = board->ai_maxdata;
1137 if (devpriv->user_ai_range_table) { /* user defined ai range */
1138 s->range_table = devpriv->user_ai_range_table;
1139 } else if (status & DAS16_STATUS_UNIPOLAR) {
1140 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1142 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1144 s->insn_read = das16_ai_insn_read;
1145 if (devpriv->dma_chan) {
1146 dev->read_subdev = s;
1147 s->subdev_flags |= SDF_CMD_READ;
1148 s->do_cmdtest = das16_cmd_test;
1149 s->do_cmd = das16_cmd_exec;
1150 s->cancel = das16_cancel;
1151 s->munge = das16_ai_munge;
1154 /* Analog Output subdevice */
1155 s = &dev->subdevices[1];
1156 if (board->has_ao) {
1157 s->type = COMEDI_SUBD_AO;
1158 s->subdev_flags = SDF_WRITABLE;
1160 s->maxdata = 0x0fff;
1161 if (devpriv->user_ao_range_table)
1162 s->range_table = devpriv->user_ao_range_table;
1164 s->range_table = &range_unknown;
1166 s->insn_write = das16_ao_insn_write;
1168 s->type = COMEDI_SUBD_UNUSED;
1171 /* Digital Input subdevice */
1172 s = &dev->subdevices[2];
1173 s->type = COMEDI_SUBD_DI;
1174 s->subdev_flags = SDF_READABLE;
1177 s->range_table = &range_digital;
1178 s->insn_bits = das16_di_insn_bits;
1180 /* Digital Output subdevice */
1181 s = &dev->subdevices[3];
1182 s->type = COMEDI_SUBD_DO;
1183 s->subdev_flags = SDF_WRITABLE;
1186 s->range_table = &range_digital;
1187 s->insn_bits = das16_do_insn_bits;
1189 /* initialize digital output lines */
1190 outb(s->state, dev->iobase + DAS16_DIO_REG);
1192 /* 8255 Digital I/O subdevice */
1193 if (board->has_8255) {
1194 s = &dev->subdevices[4];
1195 ret = subdev_8255_init(dev, s, NULL,
1196 dev->iobase + board->i8255_offset);
1202 /* set the interrupt level */
1203 devpriv->ctrl_reg = DAS16_CTRL_IRQ(dev->irq);
1204 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CTRL_REG);
1206 if (devpriv->can_burst) {
1207 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE_REG);
1208 outb(0, dev->iobase + DAS1600_CONV_REG);
1209 outb(0, dev->iobase + DAS1600_BURST_REG);
1215 static void das16_detach(struct comedi_device *dev)
1217 const struct das16_board *board = comedi_board(dev);
1218 struct das16_private_struct *devpriv = dev->private;
1223 for (i = 0; i < 2; i++) {
1224 if (devpriv->dma_buffer[i])
1225 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1226 devpriv->dma_buffer[i],
1228 dma_buffer_addr[i]);
1230 if (devpriv->dma_chan)
1231 free_dma(devpriv->dma_chan);
1232 kfree(devpriv->user_ai_range_table);
1233 kfree(devpriv->user_ao_range_table);
1235 if (devpriv->extra_iobase)
1236 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1237 comedi_legacy_detach(dev);
1240 static struct comedi_driver das16_driver = {
1241 .driver_name = "das16",
1242 .module = THIS_MODULE,
1243 .attach = das16_attach,
1244 .detach = das16_detach,
1245 .board_name = &das16_boards[0].name,
1246 .num_names = ARRAY_SIZE(das16_boards),
1247 .offset = sizeof(das16_boards[0]),
1249 module_comedi_driver(das16_driver);
1251 MODULE_AUTHOR("Comedi http://www.comedi.org");
1252 MODULE_DESCRIPTION("Comedi low-level driver");
1253 MODULE_LICENSE("GPL");