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"
93 #define DEBUG_PRINT(format, args...) \
94 printk(KERN_DEBUG "das16: " format, ## args)
96 #define DEBUG_PRINT(format, args...)
99 #define DAS16_SIZE 20 /* number of ioports */
100 #define DAS16_DMA_SIZE 0xff00 /* size in bytes of allocated dma buffer */
108 0 a/d bits 0-3 start 12 bit
109 1 a/d bits 4-11 unused
116 8 status eoc uni/bip interrupt reset
117 9 dma, int, trig ctrl set dma, int
118 a pacer control unused
130 0 a/d bits 0-3 start 12 bit
131 1 a/d bits 4-11 unused
135 8 status eoc uni/bip interrupt reset
136 9 dma, int, trig ctrl set dma, int
137 a pacer control unused
138 b gain status gain control
148 0 a/d bits 0-7 start 16 bit
149 1 a/d bits 8-15 unused
153 8 status eoc uni/bip interrupt reset
154 9 dma, int, trig ctrl set dma, int
155 a pacer control unused
156 b gain status gain control
167 0 a/d bits 0-3 start 12 bit
168 1 a/d bits 4-11 unused
175 8 status eoc uni/bip interrupt reset
176 9 dma, int, trig ctrl set dma, int
177 a pacer control unused
178 b gain status gain control
181 404 unused conversion enable
182 405 unused burst enable
183 406 unused das1600 enable
188 /* size in bytes of a sample from board */
189 static const int sample_size = 2;
192 #define DAS16_AI_LSB 0
193 #define DAS16_AI_MSB 1
196 #define DAS16_AO_LSB(x) ((x) ? 6 : 4)
197 #define DAS16_AO_MSB(x) ((x) ? 7 : 5)
198 #define DAS16_STATUS 8
200 #define UNIPOLAR (1<<6)
201 #define DAS16_MUXBIT (1<<5)
202 #define DAS16_INT (1<<4)
203 #define DAS16_CONTROL 9
204 #define DAS16_INTE (1<<7)
205 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
206 #define DMA_ENABLE (1<<2)
207 #define PACING_MASK 0x3
208 #define INT_PACER 0x03
209 #define EXT_PACER 0x02
210 #define DAS16_SOFT 0x00
211 #define DAS16_PACER 0x0A
212 #define DAS16_CTR0 (1<<1)
213 #define DAS16_TRIG0 (1<<0)
214 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
215 #define DAS16_GAIN 0x0B
216 #define DAS16_CNTR0_DATA 0x0C
217 #define DAS16_CNTR1_DATA 0x0D
218 #define DAS16_CNTR2_DATA 0x0E
219 #define DAS16_CNTR_CONTROL 0x0F
220 #define DAS16_TERM_CNT 0x00
221 #define DAS16_ONE_SHOT 0x02
222 #define DAS16_RATE_GEN 0x04
223 #define DAS16_CNTR_LSB_MSB 0x30
224 #define DAS16_CNTR0 0x00
225 #define DAS16_CNTR1 0x40
226 #define DAS16_CNTR2 0x80
228 #define DAS1600_CONV 0x404
229 #define DAS1600_CONV_DISABLE 0x40
230 #define DAS1600_BURST 0x405
231 #define DAS1600_BURST_VAL 0x40
232 #define DAS1600_ENABLE 0x406
233 #define DAS1600_ENABLE_VAL 0x40
234 #define DAS1600_STATUS_B 0x407
235 #define DAS1600_BME 0x40
236 #define DAS1600_ME 0x20
237 #define DAS1600_CD 0x10
238 #define DAS1600_WS 0x02
239 #define DAS1600_CLK_10MHZ 0x01
241 static const struct comedi_lrange range_das1x01_bip = { 4, {
249 static const struct comedi_lrange range_das1x01_unip = { 4, {
257 static const struct comedi_lrange range_das1x02_bip = { 4, {
265 static const struct comedi_lrange range_das1x02_unip = { 4, {
273 static const struct comedi_lrange range_das16jr = { 9, {
274 /* also used by 16/330 */
287 static const struct comedi_lrange range_das16jr_16 = { 8, {
299 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
300 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
301 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
310 static const int *const das16_gainlists[] = {
318 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
326 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
336 unsigned have_byte:1;
342 unsigned int ai_nbits;
343 unsigned int ai_speed; /* max conversion speed in nanosec */
346 unsigned int ao_nbits;
350 unsigned int i8255_offset;
351 unsigned int i8254_offset;
357 #define DAS16_TIMEOUT 1000
359 /* Period for timer interrupt in jiffies. It's a function
360 * to deal with possibility of dynamic HZ patches */
361 static inline int timer_period(void)
366 struct das16_private_struct {
367 unsigned int ai_unipolar; /* unipolar flag */
368 unsigned int ai_singleended; /* single ended flag */
369 unsigned int clockbase; /* master clock speed in ns */
370 volatile unsigned int control_state; /* dma, interrupt and trigger control bits */
371 volatile unsigned long adc_byte_count; /* number of bytes remaining */
372 /* divisor dividing master clock to get conversion frequency */
373 unsigned int divisor1;
374 /* divisor dividing master clock to get conversion frequency */
375 unsigned int divisor2;
376 unsigned int dma_chan; /* dma channel */
377 uint16_t *dma_buffer[2];
378 dma_addr_t dma_buffer_addr[2];
379 unsigned int current_buffer;
380 volatile unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
382 * user-defined analog input and output ranges
383 * defined from config options
385 struct comedi_lrange *user_ai_range_table;
386 struct comedi_lrange *user_ao_range_table;
388 struct timer_list timer; /* for timed interrupt */
389 volatile short timer_running;
391 unsigned long extra_iobase;
394 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
395 struct comedi_cmd *cmd)
397 const struct das16_board *board = comedi_board(dev);
398 struct das16_private_struct *devpriv = dev->private;
400 int gain, start_chan, i;
403 /* Step 1 : check if triggers are trivially valid */
405 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
408 /* if board supports burst mode */
409 if (board->size > 0x400)
410 mask |= TRIG_TIMER | TRIG_EXT;
411 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
413 tmp = cmd->convert_src;
414 mask = TRIG_TIMER | TRIG_EXT;
415 /* if board supports burst mode */
416 if (board->size > 0x400)
418 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
420 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
421 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
426 /* Step 2a : make sure trigger sources are unique */
428 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
429 err |= cfc_check_trigger_is_unique(cmd->convert_src);
430 err |= cfc_check_trigger_is_unique(cmd->stop_src);
432 /* Step 2b : and mutually compatible */
434 /* make sure scan_begin_src and convert_src dont conflict */
435 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
437 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
443 /* Step 3: check if arguments are trivially valid */
445 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
447 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
448 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
450 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
452 /* check against maximum frequency */
453 if (cmd->scan_begin_src == TRIG_TIMER)
454 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
455 board->ai_speed * cmd->chanlist_len);
457 if (cmd->convert_src == TRIG_TIMER)
458 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
461 if (cmd->stop_src == TRIG_NONE)
462 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
467 /* step 4: fix up arguments */
468 if (cmd->scan_begin_src == TRIG_TIMER) {
469 unsigned int tmp = cmd->scan_begin_arg;
470 /* set divisors, correct timing arguments */
471 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
472 &(devpriv->divisor1),
473 &(devpriv->divisor2),
474 &(cmd->scan_begin_arg),
475 cmd->flags & TRIG_ROUND_MASK);
476 err += (tmp != cmd->scan_begin_arg);
478 if (cmd->convert_src == TRIG_TIMER) {
479 unsigned int tmp = cmd->convert_arg;
480 /* set divisors, correct timing arguments */
481 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
482 &(devpriv->divisor1),
483 &(devpriv->divisor2),
485 cmd->flags & TRIG_ROUND_MASK);
486 err += (tmp != cmd->convert_arg);
491 /* check channel/gain list against card's limitations */
493 gain = CR_RANGE(cmd->chanlist[0]);
494 start_chan = CR_CHAN(cmd->chanlist[0]);
495 for (i = 1; i < cmd->chanlist_len; i++) {
496 if (CR_CHAN(cmd->chanlist[i]) !=
497 (start_chan + i) % s->n_chan) {
499 "entries in chanlist must be "
500 "consecutive channels, "
501 "counting upwards\n");
504 if (CR_RANGE(cmd->chanlist[i]) != gain) {
506 "entries in chanlist must all "
507 "have the same gain\n");
518 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
521 struct das16_private_struct *devpriv = dev->private;
523 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
524 &(devpriv->divisor2), &ns,
525 rounding_flags & TRIG_ROUND_MASK);
527 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
528 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
529 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
534 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
536 const struct das16_board *board = comedi_board(dev);
537 struct das16_private_struct *devpriv = dev->private;
538 struct comedi_async *async = s->async;
539 struct comedi_cmd *cmd = &async->cmd;
544 if (cmd->flags & TRIG_RT) {
545 comedi_error(dev, "isa dma transfers cannot be performed with "
546 "TRIG_RT, aborting");
550 devpriv->adc_byte_count =
551 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
553 /* disable conversions for das1600 mode */
554 if (board->size > 0x400)
555 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
557 /* set scan limits */
558 byte = CR_CHAN(cmd->chanlist[0]);
559 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
560 outb(byte, dev->iobase + DAS16_MUX);
562 /* set gain (this is also burst rate register but according to
563 * computer boards manual, burst rate does nothing, even on
565 if (board->ai_pg != das16_pg_none) {
566 range = CR_RANGE(cmd->chanlist[0]);
567 outb((das16_gainlists[board->ai_pg])[range],
568 dev->iobase + DAS16_GAIN);
571 /* set counter mode and counts */
573 das16_set_pacer(dev, cmd->convert_arg,
574 cmd->flags & TRIG_ROUND_MASK);
575 DEBUG_PRINT("pacer period: %d ns\n", cmd->convert_arg);
577 /* enable counters */
579 /* Enable burst mode if appropriate. */
580 if (board->size > 0x400) {
581 if (cmd->convert_src == TRIG_NOW) {
582 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
583 /* set burst length */
584 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
586 outb(0, dev->iobase + DAS1600_BURST);
589 outb(byte, dev->iobase + DAS16_PACER);
591 /* set up dma transfer */
592 flags = claim_dma_lock();
593 disable_dma(devpriv->dma_chan);
594 /* clear flip-flop to make sure 2-byte registers for
595 * count and address get set correctly */
596 clear_dma_ff(devpriv->dma_chan);
597 devpriv->current_buffer = 0;
598 set_dma_addr(devpriv->dma_chan,
599 devpriv->dma_buffer_addr[devpriv->current_buffer]);
600 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
601 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
602 enable_dma(devpriv->dma_chan);
603 release_dma_lock(flags);
605 /* set up interrupt */
606 devpriv->timer_running = 1;
607 devpriv->timer.expires = jiffies + timer_period();
608 add_timer(&devpriv->timer);
609 devpriv->control_state &= ~DAS16_INTE;
610 devpriv->control_state |= DMA_ENABLE;
611 devpriv->control_state &= ~PACING_MASK;
612 if (cmd->convert_src == TRIG_EXT)
613 devpriv->control_state |= EXT_PACER;
615 devpriv->control_state |= INT_PACER;
616 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
618 /* Enable conversions if using das1600 mode */
619 if (board->size > 0x400)
620 outb(0, dev->iobase + DAS1600_CONV);
626 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
628 const struct das16_board *board = comedi_board(dev);
629 struct das16_private_struct *devpriv = dev->private;
632 spin_lock_irqsave(&dev->spinlock, flags);
633 /* disable interrupts, dma and pacer clocked conversions */
634 devpriv->control_state &= ~DAS16_INTE & ~PACING_MASK & ~DMA_ENABLE;
635 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
636 if (devpriv->dma_chan)
637 disable_dma(devpriv->dma_chan);
639 /* disable SW timer */
640 if (devpriv->timer_running) {
641 devpriv->timer_running = 0;
642 del_timer(&devpriv->timer);
645 /* disable burst mode */
646 if (board->size > 0x400)
647 outb(0, dev->iobase + DAS1600_BURST);
650 spin_unlock_irqrestore(&dev->spinlock, flags);
655 static void das16_reset(struct comedi_device *dev)
657 outb(0, dev->iobase + DAS16_STATUS);
658 outb(0, dev->iobase + DAS16_CONTROL);
659 outb(0, dev->iobase + DAS16_PACER);
660 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
663 static int das16_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
664 struct comedi_insn *insn, unsigned int *data)
666 const struct das16_board *board = comedi_board(dev);
667 struct das16_private_struct *devpriv = dev->private;
673 /* disable interrupts and pacing */
674 devpriv->control_state &= ~DAS16_INTE & ~DMA_ENABLE & ~PACING_MASK;
675 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
677 /* set multiplexer */
678 chan = CR_CHAN(insn->chanspec);
679 chan |= CR_CHAN(insn->chanspec) << 4;
680 outb(chan, dev->iobase + DAS16_MUX);
683 if (board->ai_pg != das16_pg_none) {
684 range = CR_RANGE(insn->chanspec);
685 outb((das16_gainlists[board->ai_pg])[range],
686 dev->iobase + DAS16_GAIN);
689 for (n = 0; n < insn->n; n++) {
690 /* trigger conversion */
691 outb_p(0, dev->iobase + DAS16_TRIG);
693 for (i = 0; i < DAS16_TIMEOUT; i++) {
694 if (!(inb(dev->iobase + DAS16_STATUS) & BUSY))
697 if (i == DAS16_TIMEOUT) {
698 printk("das16: timeout\n");
701 msb = inb(dev->iobase + DAS16_AI_MSB);
702 lsb = inb(dev->iobase + DAS16_AI_LSB);
703 if (board->ai_nbits == 12)
704 data[n] = ((lsb >> 4) & 0xf) | (msb << 4);
706 data[n] = lsb | (msb << 8);
713 static int das16_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
714 struct comedi_insn *insn, unsigned int *data)
718 bits = inb(dev->iobase + DAS16_DIO) & 0xf;
725 static int das16_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
726 struct comedi_insn *insn, unsigned int *data)
730 /* only set bits that have been masked */
733 /* zero bits that have been masked */
735 /* set masked bits */
736 wbits |= data[0] & data[1];
740 outb(s->state, dev->iobase + DAS16_DIO);
745 static int das16_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
746 struct comedi_insn *insn, unsigned int *data)
748 const struct das16_board *board = comedi_board(dev);
753 chan = CR_CHAN(insn->chanspec);
755 for (i = 0; i < insn->n; i++) {
756 if (board->ao_nbits == 12) {
757 lsb = (data[i] << 4) & 0xff;
758 msb = (data[i] >> 4) & 0xff;
760 lsb = data[i] & 0xff;
761 msb = (data[i] >> 8) & 0xff;
763 outb(lsb, dev->iobase + DAS16_AO_LSB(chan));
764 outb(msb, dev->iobase + DAS16_AO_MSB(chan));
770 /* the pc104-das16jr (at least) has problems if the dma
771 transfer is interrupted in the middle of transferring
772 a 16 bit sample, so this function takes care to get
773 an even transfer count after disabling dma
776 static int disable_dma_on_even(struct comedi_device *dev)
778 struct das16_private_struct *devpriv = dev->private;
781 static const int disable_limit = 100;
782 static const int enable_timeout = 100;
784 disable_dma(devpriv->dma_chan);
785 residue = get_dma_residue(devpriv->dma_chan);
786 for (i = 0; i < disable_limit && (residue % 2); ++i) {
788 enable_dma(devpriv->dma_chan);
789 for (j = 0; j < enable_timeout; ++j) {
792 new_residue = get_dma_residue(devpriv->dma_chan);
793 if (new_residue != residue)
796 disable_dma(devpriv->dma_chan);
797 residue = get_dma_residue(devpriv->dma_chan);
799 if (i == disable_limit) {
800 comedi_error(dev, "failed to get an even dma transfer, "
801 "could be trouble.");
806 static void das16_interrupt(struct comedi_device *dev)
808 struct das16_private_struct *devpriv = dev->private;
809 unsigned long dma_flags, spin_flags;
810 struct comedi_subdevice *s = dev->read_subdev;
811 struct comedi_async *async;
812 struct comedi_cmd *cmd;
813 int num_bytes, residue;
816 if (!dev->attached) {
817 comedi_error(dev, "premature interrupt");
820 /* initialize async here to make sure it is not NULL */
824 if (devpriv->dma_chan == 0) {
825 comedi_error(dev, "interrupt with no dma channel?");
829 spin_lock_irqsave(&dev->spinlock, spin_flags);
830 if ((devpriv->control_state & DMA_ENABLE) == 0) {
831 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
832 DEBUG_PRINT("interrupt while dma disabled?\n");
836 dma_flags = claim_dma_lock();
837 clear_dma_ff(devpriv->dma_chan);
838 residue = disable_dma_on_even(dev);
840 /* figure out how many points to read */
841 if (residue > devpriv->dma_transfer_size) {
842 comedi_error(dev, "residue > transfer size!\n");
843 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
846 num_bytes = devpriv->dma_transfer_size - residue;
848 if (cmd->stop_src == TRIG_COUNT &&
849 num_bytes >= devpriv->adc_byte_count) {
850 num_bytes = devpriv->adc_byte_count;
851 async->events |= COMEDI_CB_EOA;
854 buffer_index = devpriv->current_buffer;
855 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
856 devpriv->adc_byte_count -= num_bytes;
859 if ((async->events & COMEDI_CB_EOA) == 0) {
860 set_dma_addr(devpriv->dma_chan,
861 devpriv->dma_buffer_addr[devpriv->current_buffer]);
862 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
863 enable_dma(devpriv->dma_chan);
865 release_dma_lock(dma_flags);
867 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
869 cfc_write_array_to_buffer(s,
870 devpriv->dma_buffer[buffer_index], num_bytes);
872 cfc_handle_events(dev, s);
875 static void das16_timer_interrupt(unsigned long arg)
877 struct comedi_device *dev = (struct comedi_device *)arg;
878 struct das16_private_struct *devpriv = dev->private;
880 das16_interrupt(dev);
882 if (devpriv->timer_running)
883 mod_timer(&devpriv->timer, jiffies + timer_period());
886 static void reg_dump(struct comedi_device *dev)
888 DEBUG_PRINT("********DAS1600 REGISTER DUMP********\n");
889 DEBUG_PRINT("DAS16_MUX: %x\n", inb(dev->iobase + DAS16_MUX));
890 DEBUG_PRINT("DAS16_DIO: %x\n", inb(dev->iobase + DAS16_DIO));
891 DEBUG_PRINT("DAS16_STATUS: %x\n", inb(dev->iobase + DAS16_STATUS));
892 DEBUG_PRINT("DAS16_CONTROL: %x\n", inb(dev->iobase + DAS16_CONTROL));
893 DEBUG_PRINT("DAS16_PACER: %x\n", inb(dev->iobase + DAS16_PACER));
894 DEBUG_PRINT("DAS16_GAIN: %x\n", inb(dev->iobase + DAS16_GAIN));
895 DEBUG_PRINT("DAS16_CNTR_CONTROL: %x\n",
896 inb(dev->iobase + DAS16_CNTR_CONTROL));
897 DEBUG_PRINT("DAS1600_CONV: %x\n", inb(dev->iobase + DAS1600_CONV));
898 DEBUG_PRINT("DAS1600_BURST: %x\n", inb(dev->iobase + DAS1600_BURST));
899 DEBUG_PRINT("DAS1600_ENABLE: %x\n", inb(dev->iobase + DAS1600_ENABLE));
900 DEBUG_PRINT("DAS1600_STATUS_B: %x\n",
901 inb(dev->iobase + DAS1600_STATUS_B));
904 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
906 const struct das16_board *board = comedi_board(dev);
907 struct das16_private_struct *devpriv = dev->private;
911 /* status is available on all boards */
913 status = inb(dev->iobase + DAS16_STATUS);
915 if ((status & UNIPOLAR))
916 devpriv->ai_unipolar = 1;
918 devpriv->ai_unipolar = 0;
921 if ((status & DAS16_MUXBIT))
922 devpriv->ai_singleended = 1;
924 devpriv->ai_singleended = 0;
927 /* diobits indicates boards */
929 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
931 printk(KERN_INFO " id bits are 0x%02x\n", diobits);
932 if (board->id != diobits) {
933 printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
940 static int das1600_mode_detect(struct comedi_device *dev)
942 struct das16_private_struct *devpriv = dev->private;
945 status = inb(dev->iobase + DAS1600_STATUS_B);
947 if (status & DAS1600_CLK_10MHZ) {
948 devpriv->clockbase = 100;
949 printk(KERN_INFO " 10MHz pacer clock\n");
951 devpriv->clockbase = 1000;
952 printk(KERN_INFO " 1MHz pacer clock\n");
960 static void das16_ai_munge(struct comedi_device *dev,
961 struct comedi_subdevice *s, void *array,
962 unsigned int num_bytes,
963 unsigned int start_chan_index)
965 const struct das16_board *board = comedi_board(dev);
966 unsigned int i, num_samples = num_bytes / sizeof(short);
969 for (i = 0; i < num_samples; i++) {
970 data[i] = le16_to_cpu(data[i]);
971 if (board->ai_nbits == 12)
972 data[i] = (data[i] >> 4) & 0xfff;
983 * 3 Clock speed (in MHz)
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;
991 unsigned int dma_chan;
993 struct comedi_krange *user_ai_range, *user_ao_range;
995 /* check that clock setting is valid */
996 if (it->options[3]) {
997 if (it->options[3] != 0 &&
998 it->options[3] != 1 && it->options[3] != 10) {
1000 ("\n Invalid option. Master clock must be set "
1001 "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;
1026 /* probe id bits to make sure they are consistent */
1027 if (das16_probe(dev, it)) {
1028 printk(KERN_ERR " id bits do not match selected board, aborting\n");
1032 /* get master clock speed */
1033 if (board->size < 0x400) {
1035 devpriv->clockbase = 1000 / it->options[3];
1037 devpriv->clockbase = 1000; /* 1 MHz default */
1039 das1600_mode_detect(dev);
1042 /* initialize dma */
1043 dma_chan = it->options[2];
1044 if (dma_chan == 1 || dma_chan == 3) {
1045 /* allocate dma buffers */
1047 for (i = 0; i < 2; i++) {
1048 devpriv->dma_buffer[i] = pci_alloc_consistent(
1049 NULL, DAS16_DMA_SIZE,
1050 &devpriv->dma_buffer_addr[i]);
1052 if (devpriv->dma_buffer[i] == NULL)
1055 if (request_dma(dma_chan, dev->board_name)) {
1056 printk(KERN_ERR " failed to allocate dma channel %i\n",
1060 devpriv->dma_chan = dma_chan;
1061 flags = claim_dma_lock();
1062 disable_dma(devpriv->dma_chan);
1063 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
1064 release_dma_lock(flags);
1065 printk(KERN_INFO " ( dma = %u)\n", dma_chan);
1066 } else if (dma_chan == 0) {
1067 printk(KERN_INFO " ( no dma )\n");
1069 printk(KERN_ERR " invalid dma channel\n");
1073 /* get any user-defined input range */
1074 if (board->ai_pg == das16_pg_none &&
1075 (it->options[4] || it->options[5])) {
1076 /* allocate single-range range table */
1077 devpriv->user_ai_range_table =
1078 kmalloc(sizeof(struct comedi_lrange) +
1079 sizeof(struct comedi_krange), GFP_KERNEL);
1080 /* initialize ai range */
1081 devpriv->user_ai_range_table->length = 1;
1082 user_ai_range = devpriv->user_ai_range_table->range;
1083 user_ai_range->min = it->options[4];
1084 user_ai_range->max = it->options[5];
1085 user_ai_range->flags = UNIT_volt;
1087 /* get any user-defined output range */
1088 if (it->options[6] || it->options[7]) {
1089 /* allocate single-range range table */
1090 devpriv->user_ao_range_table =
1091 kmalloc(sizeof(struct comedi_lrange) +
1092 sizeof(struct comedi_krange), GFP_KERNEL);
1093 /* initialize ao range */
1094 devpriv->user_ao_range_table->length = 1;
1095 user_ao_range = devpriv->user_ao_range_table->range;
1096 user_ao_range->min = it->options[6];
1097 user_ao_range->max = it->options[7];
1098 user_ao_range->flags = UNIT_volt;
1101 init_timer(&(devpriv->timer));
1102 devpriv->timer.function = das16_timer_interrupt;
1103 devpriv->timer.data = (unsigned long)dev;
1105 ret = comedi_alloc_subdevices(dev, 5);
1109 s = &dev->subdevices[0];
1110 dev->read_subdev = s;
1113 s->type = COMEDI_SUBD_AI;
1114 s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
1115 if (devpriv->ai_singleended) {
1117 s->len_chanlist = 16;
1118 s->subdev_flags |= SDF_GROUND;
1121 s->len_chanlist = 8;
1122 s->subdev_flags |= SDF_DIFF;
1124 s->maxdata = (1 << board->ai_nbits) - 1;
1125 if (devpriv->user_ai_range_table) { /* user defined ai range */
1126 s->range_table = devpriv->user_ai_range_table;
1127 } else if (devpriv->ai_unipolar) {
1128 s->range_table = das16_ai_uni_lranges[board->ai_pg];
1130 s->range_table = das16_ai_bip_lranges[board->ai_pg];
1132 s->insn_read = board->ai;
1133 s->do_cmdtest = das16_cmd_test;
1134 s->do_cmd = das16_cmd_exec;
1135 s->cancel = das16_cancel;
1136 s->munge = das16_ai_munge;
1138 s->type = COMEDI_SUBD_UNUSED;
1141 s = &dev->subdevices[1];
1144 s->type = COMEDI_SUBD_AO;
1145 s->subdev_flags = SDF_WRITABLE;
1147 s->maxdata = (1 << board->ao_nbits) - 1;
1148 /* user defined ao range */
1149 if (devpriv->user_ao_range_table)
1150 s->range_table = devpriv->user_ao_range_table;
1152 s->range_table = &range_unknown;
1154 s->insn_write = board->ao;
1156 s->type = COMEDI_SUBD_UNUSED;
1159 s = &dev->subdevices[2];
1162 s->type = COMEDI_SUBD_DI;
1163 s->subdev_flags = SDF_READABLE;
1166 s->range_table = &range_digital;
1167 s->insn_bits = board->di;
1169 s->type = COMEDI_SUBD_UNUSED;
1172 s = &dev->subdevices[3];
1175 s->type = COMEDI_SUBD_DO;
1176 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1179 s->range_table = &range_digital;
1180 s->insn_bits = board->do_;
1181 /* initialize digital output lines */
1182 outb(s->state, dev->iobase + DAS16_DIO);
1184 s->type = COMEDI_SUBD_UNUSED;
1187 s = &dev->subdevices[4];
1189 if (board->i8255_offset != 0) {
1190 subdev_8255_init(dev, s, NULL, (dev->iobase +
1191 board->i8255_offset));
1193 s->type = COMEDI_SUBD_UNUSED;
1197 /* set the interrupt level */
1198 devpriv->control_state = DAS16_IRQ(dev->irq);
1199 outb(devpriv->control_state, dev->iobase + DAS16_CONTROL);
1201 /* turn on das1600 mode if available */
1202 if (board->size > 0x400) {
1203 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1204 outb(0, dev->iobase + DAS1600_CONV);
1205 outb(0, dev->iobase + DAS1600_BURST);
1211 static void das16_detach(struct comedi_device *dev)
1213 const struct das16_board *board = comedi_board(dev);
1214 struct das16_private_struct *devpriv = dev->private;
1219 for (i = 0; i < 2; i++) {
1220 if (devpriv->dma_buffer[i])
1221 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1222 devpriv->dma_buffer[i],
1224 dma_buffer_addr[i]);
1226 if (devpriv->dma_chan)
1227 free_dma(devpriv->dma_chan);
1228 kfree(devpriv->user_ai_range_table);
1229 kfree(devpriv->user_ao_range_table);
1231 if (devpriv->extra_iobase)
1232 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1233 comedi_legacy_detach(dev);
1236 static const struct das16_board das16_boards[] = {
1239 .ai = das16_ai_rinsn,
1242 .ai_pg = das16_pg_none,
1243 .ao = das16_ao_winsn,
1245 .di = das16_di_rbits,
1246 .do_ = das16_do_wbits,
1247 .i8255_offset = 0x10,
1248 .i8254_offset = 0x0c,
1253 .ai = das16_ai_rinsn,
1256 .ai_pg = das16_pg_none,
1257 .ao = das16_ao_winsn,
1259 .di = das16_di_rbits,
1260 .do_ = das16_do_wbits,
1261 .i8255_offset = 0x10,
1262 .i8254_offset = 0x0c,
1267 .ai = das16_ai_rinsn,
1270 .ai_pg = das16_pg_none,
1271 .ao = das16_ao_winsn,
1273 .di = das16_di_rbits,
1274 .do_ = das16_do_wbits,
1275 .i8255_offset = 0x10,
1276 .i8254_offset = 0x0c,
1280 .name = "cio-das16",
1281 .ai = das16_ai_rinsn,
1284 .ai_pg = das16_pg_none,
1285 .ao = das16_ao_winsn,
1287 .di = das16_di_rbits,
1288 .do_ = das16_do_wbits,
1289 .i8255_offset = 0x10,
1290 .i8254_offset = 0x0c,
1294 .name = "cio-das16/f",
1295 .ai = das16_ai_rinsn,
1298 .ai_pg = das16_pg_none,
1299 .ao = das16_ao_winsn,
1301 .di = das16_di_rbits,
1302 .do_ = das16_do_wbits,
1303 .i8255_offset = 0x10,
1304 .i8254_offset = 0x0c,
1308 .name = "cio-das16/jr",
1309 .ai = das16_ai_rinsn,
1312 .ai_pg = das16_pg_16jr,
1314 .di = das16_di_rbits,
1315 .do_ = das16_do_wbits,
1317 .i8254_offset = 0x0c,
1321 .name = "pc104-das16jr",
1322 .ai = das16_ai_rinsn,
1325 .ai_pg = das16_pg_16jr,
1327 .di = das16_di_rbits,
1328 .do_ = das16_do_wbits,
1330 .i8254_offset = 0x0c,
1334 .name = "cio-das16jr/16",
1335 .ai = das16_ai_rinsn,
1338 .ai_pg = das16_pg_16jr_16,
1340 .di = das16_di_rbits,
1341 .do_ = das16_do_wbits,
1343 .i8254_offset = 0x0c,
1347 .name = "pc104-das16jr/16",
1348 .ai = das16_ai_rinsn,
1351 .ai_pg = das16_pg_16jr_16,
1353 .di = das16_di_rbits,
1354 .do_ = das16_do_wbits,
1356 .i8254_offset = 0x0c,
1361 .ai = das16_ai_rinsn,
1364 .ai_pg = das16_pg_none,
1366 .di = das16_di_rbits,
1367 .do_ = das16_do_wbits,
1368 .i8255_offset = 0x400,
1369 .i8254_offset = 0x0c,
1374 .ai = das16_ai_rinsn,
1377 .ai_pg = das16_pg_none,
1379 .di = das16_di_rbits,
1380 .do_ = das16_do_wbits,
1381 .i8255_offset = 0x400,
1382 .i8254_offset = 0x0c,
1387 .ai = das16_ai_rinsn,
1390 .ai_pg = das16_pg_1601,
1392 .di = das16_di_rbits,
1393 .do_ = das16_do_wbits,
1394 .i8255_offset = 0x0,
1395 .i8254_offset = 0x0c,
1400 .ai = das16_ai_rinsn,
1403 .ai_pg = das16_pg_1602,
1405 .di = das16_di_rbits,
1406 .do_ = das16_do_wbits,
1407 .i8255_offset = 0x0,
1408 .i8254_offset = 0x0c,
1413 .ai = das16_ai_rinsn,
1416 .ai_pg = das16_pg_1601,
1417 .ao = das16_ao_winsn,
1419 .di = das16_di_rbits,
1420 .do_ = das16_do_wbits,
1421 .i8255_offset = 0x400,
1422 .i8254_offset = 0x0c,
1427 .ai = das16_ai_rinsn,
1430 .ai_pg = das16_pg_1602,
1431 .ao = das16_ao_winsn,
1433 .di = das16_di_rbits,
1434 .do_ = das16_do_wbits,
1435 .i8255_offset = 0x400,
1436 .i8254_offset = 0x0c,
1440 .name = "cio-das1401/12",
1441 .ai = das16_ai_rinsn,
1444 .ai_pg = das16_pg_1601,
1446 .di = das16_di_rbits,
1447 .do_ = das16_do_wbits,
1449 .i8254_offset = 0x0c,
1453 .name = "cio-das1402/12",
1454 .ai = das16_ai_rinsn,
1457 .ai_pg = das16_pg_1602,
1459 .di = das16_di_rbits,
1460 .do_ = das16_do_wbits,
1462 .i8254_offset = 0x0c,
1466 .name = "cio-das1402/16",
1467 .ai = das16_ai_rinsn,
1470 .ai_pg = das16_pg_1602,
1472 .di = das16_di_rbits,
1473 .do_ = das16_do_wbits,
1475 .i8254_offset = 0x0c,
1479 .name = "cio-das1601/12",
1480 .ai = das16_ai_rinsn,
1483 .ai_pg = das16_pg_1601,
1484 .ao = das16_ao_winsn,
1486 .di = das16_di_rbits,
1487 .do_ = das16_do_wbits,
1488 .i8255_offset = 0x400,
1489 .i8254_offset = 0x0c,
1493 .name = "cio-das1602/12",
1494 .ai = das16_ai_rinsn,
1497 .ai_pg = das16_pg_1602,
1498 .ao = das16_ao_winsn,
1500 .di = das16_di_rbits,
1501 .do_ = das16_do_wbits,
1502 .i8255_offset = 0x400,
1503 .i8254_offset = 0x0c,
1507 .name = "cio-das1602/16",
1508 .ai = das16_ai_rinsn,
1511 .ai_pg = das16_pg_1602,
1512 .ao = das16_ao_winsn,
1514 .di = das16_di_rbits,
1515 .do_ = das16_do_wbits,
1516 .i8255_offset = 0x400,
1517 .i8254_offset = 0x0c,
1521 .name = "cio-das16/330",
1522 .ai = das16_ai_rinsn,
1525 .ai_pg = das16_pg_16jr,
1527 .di = das16_di_rbits,
1528 .do_ = das16_do_wbits,
1530 .i8254_offset = 0x0c,
1536 static struct comedi_driver das16_driver = {
1537 .driver_name = "das16",
1538 .module = THIS_MODULE,
1539 .attach = das16_attach,
1540 .detach = das16_detach,
1541 .board_name = &das16_boards[0].name,
1542 .num_names = ARRAY_SIZE(das16_boards),
1543 .offset = sizeof(das16_boards[0]),
1545 module_comedi_driver(das16_driver);
1547 MODULE_AUTHOR("Comedi http://www.comedi.org");
1548 MODULE_DESCRIPTION("Comedi low-level driver");
1549 MODULE_LICENSE("GPL");