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 */
95 #define DAS16_AI_LSB 0
96 #define DAS16_AI_MSB 1
99 #define DAS16_AO_LSB(x) ((x) ? 6 : 4)
100 #define DAS16_AO_MSB(x) ((x) ? 7 : 5)
101 #define DAS16_STATUS 8
103 #define UNIPOLAR (1<<6)
104 #define DAS16_MUXBIT (1<<5)
105 #define DAS16_INT (1<<4)
106 #define DAS16_CONTROL 9
107 #define DAS16_INTE (1<<7)
108 #define DAS16_IRQ(x) (((x) & 0x7) << 4)
109 #define DMA_ENABLE (1<<2)
110 #define PACING_MASK 0x3
111 #define INT_PACER 0x03
112 #define EXT_PACER 0x02
113 #define DAS16_SOFT 0x00
114 #define DAS16_PACER 0x0A
115 #define DAS16_CTR0 (1<<1)
116 #define DAS16_TRIG0 (1<<0)
117 #define BURST_LEN_BITS(x) (((x) & 0xf) << 4)
118 #define DAS16_GAIN 0x0B
119 #define DAS16_CNTR0_DATA 0x0C
120 #define DAS16_CNTR1_DATA 0x0D
121 #define DAS16_CNTR2_DATA 0x0E
122 #define DAS16_CNTR_CONTROL 0x0F
123 #define DAS16_TERM_CNT 0x00
124 #define DAS16_ONE_SHOT 0x02
125 #define DAS16_RATE_GEN 0x04
126 #define DAS16_CNTR_LSB_MSB 0x30
127 #define DAS16_CNTR0 0x00
128 #define DAS16_CNTR1 0x40
129 #define DAS16_CNTR2 0x80
131 #define DAS1600_CONV 0x404
132 #define DAS1600_CONV_DISABLE 0x40
133 #define DAS1600_BURST 0x405
134 #define DAS1600_BURST_VAL 0x40
135 #define DAS1600_ENABLE 0x406
136 #define DAS1600_ENABLE_VAL 0x40
137 #define DAS1600_STATUS_B 0x407
138 #define DAS1600_BME 0x40
139 #define DAS1600_ME 0x20
140 #define DAS1600_CD 0x10
141 #define DAS1600_WS 0x02
142 #define DAS1600_CLK_10MHZ 0x01
144 static const struct comedi_lrange range_das1x01_bip = {
153 static const struct comedi_lrange range_das1x01_unip = {
162 static const struct comedi_lrange range_das1x02_bip = {
171 static const struct comedi_lrange range_das1x02_unip = {
180 static const struct comedi_lrange range_das16jr = {
194 static const struct comedi_lrange range_das16jr_16 = {
207 static const int das16jr_gainlist[] = { 8, 0, 1, 2, 3, 4, 5, 6, 7 };
208 static const int das16jr_16_gainlist[] = { 0, 1, 2, 3, 4, 5, 6, 7 };
209 static const int das1600_gainlist[] = { 0, 1, 2, 3 };
218 static const int *const das16_gainlists[] = {
226 static const struct comedi_lrange *const das16_ai_uni_lranges[] = {
234 static const struct comedi_lrange *const das16_ai_bip_lranges[] = {
244 unsigned int ai_maxdata;
245 unsigned int ai_speed; /* max conversion speed in nanosec */
247 unsigned int has_ao:1;
249 unsigned int i8255_offset;
250 unsigned int i8254_offset;
256 /* Period for timer interrupt in jiffies. It's a function
257 * to deal with possibility of dynamic HZ patches */
258 static inline int timer_period(void)
263 struct das16_private_struct {
264 unsigned int clockbase; /* master clock speed in ns */
265 unsigned int ctrl_reg;
266 unsigned long adc_byte_count; /* number of bytes remaining */
267 /* divisor dividing master clock to get conversion frequency */
268 unsigned int divisor1;
269 /* divisor dividing master clock to get conversion frequency */
270 unsigned int divisor2;
271 unsigned int dma_chan; /* dma channel */
272 uint16_t *dma_buffer[2];
273 dma_addr_t dma_buffer_addr[2];
274 unsigned int current_buffer;
275 unsigned int dma_transfer_size; /* target number of bytes to transfer per dma shot */
277 * user-defined analog input and output ranges
278 * defined from config options
280 struct comedi_lrange *user_ai_range_table;
281 struct comedi_lrange *user_ao_range_table;
283 struct timer_list timer; /* for timed interrupt */
286 unsigned long extra_iobase;
287 unsigned int can_burst:1;
290 static void das16_ai_enable(struct comedi_device *dev,
291 unsigned int mode, unsigned int src)
293 struct das16_private_struct *devpriv = dev->private;
295 devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK);
296 devpriv->ctrl_reg |= mode;
299 devpriv->ctrl_reg |= EXT_PACER;
301 devpriv->ctrl_reg |= INT_PACER;
302 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL);
305 static void das16_ai_disable(struct comedi_device *dev)
307 struct das16_private_struct *devpriv = dev->private;
309 /* disable interrupts, dma and pacer clocked conversions */
310 devpriv->ctrl_reg &= ~(DAS16_INTE | DMA_ENABLE | PACING_MASK);
311 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL);
314 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
315 struct comedi_cmd *cmd)
317 const struct das16_board *board = comedi_board(dev);
318 struct das16_private_struct *devpriv = dev->private;
320 int gain, start_chan, i;
323 /* Step 1 : check if triggers are trivially valid */
325 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
328 if (devpriv->can_burst)
329 mask |= TRIG_TIMER | TRIG_EXT;
330 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
332 tmp = cmd->convert_src;
333 mask = TRIG_TIMER | TRIG_EXT;
334 if (devpriv->can_burst)
336 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
338 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
339 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
344 /* Step 2a : make sure trigger sources are unique */
346 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
347 err |= cfc_check_trigger_is_unique(cmd->convert_src);
348 err |= cfc_check_trigger_is_unique(cmd->stop_src);
350 /* Step 2b : and mutually compatible */
352 /* make sure scan_begin_src and convert_src dont conflict */
353 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
355 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
361 /* Step 3: check if arguments are trivially valid */
363 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
365 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
366 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
368 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
370 /* check against maximum frequency */
371 if (cmd->scan_begin_src == TRIG_TIMER)
372 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
373 board->ai_speed * cmd->chanlist_len);
375 if (cmd->convert_src == TRIG_TIMER)
376 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
379 if (cmd->stop_src == TRIG_NONE)
380 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
385 /* step 4: fix up arguments */
386 if (cmd->scan_begin_src == TRIG_TIMER) {
387 unsigned int tmp = cmd->scan_begin_arg;
388 /* set divisors, correct timing arguments */
389 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
390 &(devpriv->divisor1),
391 &(devpriv->divisor2),
392 &(cmd->scan_begin_arg),
393 cmd->flags & TRIG_ROUND_MASK);
394 err += (tmp != cmd->scan_begin_arg);
396 if (cmd->convert_src == TRIG_TIMER) {
397 unsigned int tmp = cmd->convert_arg;
398 /* set divisors, correct timing arguments */
399 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
400 &(devpriv->divisor1),
401 &(devpriv->divisor2),
403 cmd->flags & TRIG_ROUND_MASK);
404 err += (tmp != cmd->convert_arg);
409 /* check channel/gain list against card's limitations */
411 gain = CR_RANGE(cmd->chanlist[0]);
412 start_chan = CR_CHAN(cmd->chanlist[0]);
413 for (i = 1; i < cmd->chanlist_len; i++) {
414 if (CR_CHAN(cmd->chanlist[i]) !=
415 (start_chan + i) % s->n_chan) {
417 "entries in chanlist must be "
418 "consecutive channels, "
419 "counting upwards\n");
422 if (CR_RANGE(cmd->chanlist[i]) != gain) {
424 "entries in chanlist must all "
425 "have the same gain\n");
436 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
439 struct das16_private_struct *devpriv = dev->private;
441 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
442 &(devpriv->divisor2), &ns,
443 rounding_flags & TRIG_ROUND_MASK);
445 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
446 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
447 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
452 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
454 const struct das16_board *board = comedi_board(dev);
455 struct das16_private_struct *devpriv = dev->private;
456 struct comedi_async *async = s->async;
457 struct comedi_cmd *cmd = &async->cmd;
462 if (cmd->flags & TRIG_RT) {
463 comedi_error(dev, "isa dma transfers cannot be performed with "
464 "TRIG_RT, aborting");
468 devpriv->adc_byte_count =
469 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
471 if (devpriv->can_burst)
472 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
474 /* set scan limits */
475 byte = CR_CHAN(cmd->chanlist[0]);
476 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
477 outb(byte, dev->iobase + DAS16_MUX);
479 /* set gain (this is also burst rate register but according to
480 * computer boards manual, burst rate does nothing, even on
482 if (board->ai_pg != das16_pg_none) {
483 range = CR_RANGE(cmd->chanlist[0]);
484 outb((das16_gainlists[board->ai_pg])[range],
485 dev->iobase + DAS16_GAIN);
488 /* set counter mode and counts */
490 das16_set_pacer(dev, cmd->convert_arg,
491 cmd->flags & TRIG_ROUND_MASK);
493 /* enable counters */
495 if (devpriv->can_burst) {
496 if (cmd->convert_src == TRIG_NOW) {
497 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
498 /* set burst length */
499 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
501 outb(0, dev->iobase + DAS1600_BURST);
504 outb(byte, dev->iobase + DAS16_PACER);
506 /* set up dma transfer */
507 flags = claim_dma_lock();
508 disable_dma(devpriv->dma_chan);
509 /* clear flip-flop to make sure 2-byte registers for
510 * count and address get set correctly */
511 clear_dma_ff(devpriv->dma_chan);
512 devpriv->current_buffer = 0;
513 set_dma_addr(devpriv->dma_chan,
514 devpriv->dma_buffer_addr[devpriv->current_buffer]);
515 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
516 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
517 enable_dma(devpriv->dma_chan);
518 release_dma_lock(flags);
520 /* set up interrupt */
521 devpriv->timer_running = 1;
522 devpriv->timer.expires = jiffies + timer_period();
523 add_timer(&devpriv->timer);
525 das16_ai_enable(dev, DMA_ENABLE, cmd->convert_src);
527 if (devpriv->can_burst)
528 outb(0, dev->iobase + DAS1600_CONV);
533 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
535 struct das16_private_struct *devpriv = dev->private;
538 spin_lock_irqsave(&dev->spinlock, flags);
540 das16_ai_disable(dev);
541 disable_dma(devpriv->dma_chan);
543 /* disable SW timer */
544 if (devpriv->timer_running) {
545 devpriv->timer_running = 0;
546 del_timer(&devpriv->timer);
549 if (devpriv->can_burst)
550 outb(0, dev->iobase + DAS1600_BURST);
552 spin_unlock_irqrestore(&dev->spinlock, flags);
557 static void das16_reset(struct comedi_device *dev)
559 outb(0, dev->iobase + DAS16_STATUS);
560 outb(0, dev->iobase + DAS16_CONTROL);
561 outb(0, dev->iobase + DAS16_PACER);
562 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
565 static int das16_ai_wait_for_conv(struct comedi_device *dev,
566 unsigned int timeout)
571 for (i = 0; i < timeout; i++) {
572 status = inb(dev->iobase + DAS16_STATUS);
573 if (!(status & BUSY))
579 static int das16_ai_insn_read(struct comedi_device *dev,
580 struct comedi_subdevice *s,
581 struct comedi_insn *insn,
584 const struct das16_board *board = comedi_board(dev);
585 unsigned int chan = CR_CHAN(insn->chanspec);
586 unsigned int range = CR_RANGE(insn->chanspec);
591 das16_ai_disable(dev);
593 /* set multiplexer */
594 outb(chan | (chan << 4), dev->iobase + DAS16_MUX);
597 if (board->ai_pg != das16_pg_none) {
598 outb((das16_gainlists[board->ai_pg])[range],
599 dev->iobase + DAS16_GAIN);
602 for (i = 0; i < insn->n; i++) {
603 /* trigger conversion */
604 outb_p(0, dev->iobase + DAS16_TRIG);
606 ret = das16_ai_wait_for_conv(dev, 1000);
610 val = inb(dev->iobase + DAS16_AI_MSB) << 8;
611 val |= inb(dev->iobase + DAS16_AI_LSB);
612 if (s->maxdata == 0x0fff)
622 static int das16_di_insn_bits(struct comedi_device *dev,
623 struct comedi_subdevice *s,
624 struct comedi_insn *insn,
627 data[1] = inb(dev->iobase + DAS16_DIO) & 0xf;
632 static int das16_do_insn_bits(struct comedi_device *dev,
633 struct comedi_subdevice *s,
634 struct comedi_insn *insn,
637 unsigned int mask = data[0];
638 unsigned int bits = data[1];
642 s->state |= (bits & mask);
644 outb(s->state, dev->iobase + DAS16_DIO);
652 static int das16_ao_insn_write(struct comedi_device *dev,
653 struct comedi_subdevice *s,
654 struct comedi_insn *insn,
657 unsigned int chan = CR_CHAN(insn->chanspec);
661 for (i = 0; i < insn->n; i++) {
665 outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan));
666 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan));
672 /* the pc104-das16jr (at least) has problems if the dma
673 transfer is interrupted in the middle of transferring
674 a 16 bit sample, so this function takes care to get
675 an even transfer count after disabling dma
678 static int disable_dma_on_even(struct comedi_device *dev)
680 struct das16_private_struct *devpriv = dev->private;
683 static const int disable_limit = 100;
684 static const int enable_timeout = 100;
686 disable_dma(devpriv->dma_chan);
687 residue = get_dma_residue(devpriv->dma_chan);
688 for (i = 0; i < disable_limit && (residue % 2); ++i) {
690 enable_dma(devpriv->dma_chan);
691 for (j = 0; j < enable_timeout; ++j) {
694 new_residue = get_dma_residue(devpriv->dma_chan);
695 if (new_residue != residue)
698 disable_dma(devpriv->dma_chan);
699 residue = get_dma_residue(devpriv->dma_chan);
701 if (i == disable_limit) {
702 comedi_error(dev, "failed to get an even dma transfer, "
703 "could be trouble.");
708 static void das16_interrupt(struct comedi_device *dev)
710 struct das16_private_struct *devpriv = dev->private;
711 unsigned long dma_flags, spin_flags;
712 struct comedi_subdevice *s = dev->read_subdev;
713 struct comedi_async *async;
714 struct comedi_cmd *cmd;
715 int num_bytes, residue;
718 if (!dev->attached) {
719 comedi_error(dev, "premature interrupt");
722 /* initialize async here to make sure it is not NULL */
726 spin_lock_irqsave(&dev->spinlock, spin_flags);
727 if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) {
728 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
732 dma_flags = claim_dma_lock();
733 clear_dma_ff(devpriv->dma_chan);
734 residue = disable_dma_on_even(dev);
736 /* figure out how many points to read */
737 if (residue > devpriv->dma_transfer_size) {
738 comedi_error(dev, "residue > transfer size!\n");
739 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
742 num_bytes = devpriv->dma_transfer_size - residue;
744 if (cmd->stop_src == TRIG_COUNT &&
745 num_bytes >= devpriv->adc_byte_count) {
746 num_bytes = devpriv->adc_byte_count;
747 async->events |= COMEDI_CB_EOA;
750 buffer_index = devpriv->current_buffer;
751 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
752 devpriv->adc_byte_count -= num_bytes;
755 if ((async->events & COMEDI_CB_EOA) == 0) {
756 set_dma_addr(devpriv->dma_chan,
757 devpriv->dma_buffer_addr[devpriv->current_buffer]);
758 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
759 enable_dma(devpriv->dma_chan);
761 release_dma_lock(dma_flags);
763 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
765 cfc_write_array_to_buffer(s,
766 devpriv->dma_buffer[buffer_index], num_bytes);
768 cfc_handle_events(dev, s);
771 static void das16_timer_interrupt(unsigned long arg)
773 struct comedi_device *dev = (struct comedi_device *)arg;
774 struct das16_private_struct *devpriv = dev->private;
776 das16_interrupt(dev);
778 if (devpriv->timer_running)
779 mod_timer(&devpriv->timer, jiffies + timer_period());
782 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
784 const struct das16_board *board = comedi_board(dev);
787 /* diobits indicates boards */
788 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
790 printk(KERN_INFO " id bits are 0x%02x\n", diobits);
791 if (board->id != diobits) {
792 printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
799 static int das1600_mode_detect(struct comedi_device *dev)
801 struct das16_private_struct *devpriv = dev->private;
804 status = inb(dev->iobase + DAS1600_STATUS_B);
806 if (status & DAS1600_CLK_10MHZ) {
807 devpriv->clockbase = 100;
808 printk(KERN_INFO " 10MHz pacer clock\n");
810 devpriv->clockbase = 1000;
811 printk(KERN_INFO " 1MHz pacer clock\n");
817 static void das16_ai_munge(struct comedi_device *dev,
818 struct comedi_subdevice *s, void *array,
819 unsigned int num_bytes,
820 unsigned int start_chan_index)
822 unsigned int i, num_samples = num_bytes / sizeof(short);
825 for (i = 0; i < num_samples; i++) {
826 data[i] = le16_to_cpu(data[i]);
827 if (s->maxdata == 0x0fff)
829 data[i] &= s->maxdata;
839 * 3 Clock speed (in MHz)
841 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
843 const struct das16_board *board = comedi_board(dev);
844 struct das16_private_struct *devpriv;
845 struct comedi_subdevice *s;
846 struct comedi_krange *user_ai_range;
847 struct comedi_krange *user_ao_range;
848 unsigned int dma_chan = it->options[2];
852 /* check that clock setting is valid */
853 if (it->options[3]) {
854 if (it->options[3] != 0 &&
855 it->options[3] != 1 && it->options[3] != 10) {
857 ("\n Invalid option. Master clock must be set "
858 "to 1 or 10 (MHz)\n");
863 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
867 if (board->size < 0x400) {
868 ret = comedi_request_region(dev, it->options[0], board->size);
872 ret = comedi_request_region(dev, it->options[0], 0x10);
875 /* Request an additional region for the 8255 */
876 ret = __comedi_request_region(dev, dev->iobase + 0x400,
877 board->size & 0x3ff);
880 devpriv->extra_iobase = dev->iobase + 0x400;
881 devpriv->can_burst = 1;
884 /* probe id bits to make sure they are consistent */
885 if (das16_probe(dev, it)) {
886 printk(KERN_ERR " id bits do not match selected board, aborting\n");
890 /* get master clock speed */
891 if (devpriv->can_burst) {
892 das1600_mode_detect(dev);
895 devpriv->clockbase = 1000 / it->options[3];
897 devpriv->clockbase = 1000; /* 1 MHz default */
901 if (dma_chan == 1 || dma_chan == 3) {
905 if (request_dma(dma_chan, dev->board_name)) {
906 dev_err(dev->class_dev,
907 "failed to request dma channel %i\n",
911 devpriv->dma_chan = dma_chan;
913 /* allocate dma buffers */
914 for (i = 0; i < 2; i++) {
917 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
918 &devpriv->dma_buffer_addr[i]);
921 devpriv->dma_buffer[i] = p;
924 flags = claim_dma_lock();
925 disable_dma(devpriv->dma_chan);
926 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
927 release_dma_lock(flags);
929 init_timer(&(devpriv->timer));
930 devpriv->timer.function = das16_timer_interrupt;
931 devpriv->timer.data = (unsigned long)dev;
934 /* get any user-defined input range */
935 if (board->ai_pg == das16_pg_none &&
936 (it->options[4] || it->options[5])) {
937 /* allocate single-range range table */
938 devpriv->user_ai_range_table =
939 kmalloc(sizeof(struct comedi_lrange) +
940 sizeof(struct comedi_krange), GFP_KERNEL);
941 /* initialize ai range */
942 devpriv->user_ai_range_table->length = 1;
943 user_ai_range = devpriv->user_ai_range_table->range;
944 user_ai_range->min = it->options[4];
945 user_ai_range->max = it->options[5];
946 user_ai_range->flags = UNIT_volt;
948 /* get any user-defined output range */
949 if (it->options[6] || it->options[7]) {
950 /* allocate single-range range table */
951 devpriv->user_ao_range_table =
952 kmalloc(sizeof(struct comedi_lrange) +
953 sizeof(struct comedi_krange), GFP_KERNEL);
954 /* initialize ao range */
955 devpriv->user_ao_range_table->length = 1;
956 user_ao_range = devpriv->user_ao_range_table->range;
957 user_ao_range->min = it->options[6];
958 user_ao_range->max = it->options[7];
959 user_ao_range->flags = UNIT_volt;
962 ret = comedi_alloc_subdevices(dev, 5);
966 status = inb(dev->iobase + DAS16_STATUS);
968 /* Analog Input subdevice */
969 s = &dev->subdevices[0];
970 s->type = COMEDI_SUBD_AI;
971 s->subdev_flags = SDF_READABLE;
972 if (status & DAS16_MUXBIT) {
973 s->subdev_flags |= SDF_GROUND;
976 s->subdev_flags |= SDF_DIFF;
979 s->len_chanlist = s->n_chan;
980 s->maxdata = board->ai_maxdata;
981 if (devpriv->user_ai_range_table) { /* user defined ai range */
982 s->range_table = devpriv->user_ai_range_table;
983 } else if (status & UNIPOLAR) {
984 s->range_table = das16_ai_uni_lranges[board->ai_pg];
986 s->range_table = das16_ai_bip_lranges[board->ai_pg];
988 s->insn_read = das16_ai_insn_read;
989 if (devpriv->dma_chan) {
990 dev->read_subdev = s;
991 s->subdev_flags |= SDF_CMD_READ;
992 s->do_cmdtest = das16_cmd_test;
993 s->do_cmd = das16_cmd_exec;
994 s->cancel = das16_cancel;
995 s->munge = das16_ai_munge;
998 /* Analog Output subdevice */
999 s = &dev->subdevices[1];
1000 if (board->has_ao) {
1001 s->type = COMEDI_SUBD_AO;
1002 s->subdev_flags = SDF_WRITABLE;
1004 s->maxdata = 0x0fff;
1005 if (devpriv->user_ao_range_table)
1006 s->range_table = devpriv->user_ao_range_table;
1008 s->range_table = &range_unknown;
1010 s->insn_write = das16_ao_insn_write;
1012 s->type = COMEDI_SUBD_UNUSED;
1015 /* Digital Input subdevice */
1016 s = &dev->subdevices[2];
1017 s->type = COMEDI_SUBD_DI;
1018 s->subdev_flags = SDF_READABLE;
1021 s->range_table = &range_digital;
1022 s->insn_bits = das16_di_insn_bits;
1024 /* Digital Output subdevice */
1025 s = &dev->subdevices[3];
1026 s->type = COMEDI_SUBD_DO;
1027 s->subdev_flags = SDF_WRITABLE;
1030 s->range_table = &range_digital;
1031 s->insn_bits = das16_do_insn_bits;
1033 /* initialize digital output lines */
1034 outb(s->state, dev->iobase + DAS16_DIO);
1036 s = &dev->subdevices[4];
1038 if (board->i8255_offset != 0) {
1039 subdev_8255_init(dev, s, NULL, (dev->iobase +
1040 board->i8255_offset));
1042 s->type = COMEDI_SUBD_UNUSED;
1046 /* set the interrupt level */
1047 devpriv->ctrl_reg = DAS16_IRQ(dev->irq);
1048 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL);
1050 if (devpriv->can_burst) {
1051 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1052 outb(0, dev->iobase + DAS1600_CONV);
1053 outb(0, dev->iobase + DAS1600_BURST);
1059 static void das16_detach(struct comedi_device *dev)
1061 const struct das16_board *board = comedi_board(dev);
1062 struct das16_private_struct *devpriv = dev->private;
1067 for (i = 0; i < 2; i++) {
1068 if (devpriv->dma_buffer[i])
1069 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1070 devpriv->dma_buffer[i],
1072 dma_buffer_addr[i]);
1074 if (devpriv->dma_chan)
1075 free_dma(devpriv->dma_chan);
1076 kfree(devpriv->user_ai_range_table);
1077 kfree(devpriv->user_ao_range_table);
1079 if (devpriv->extra_iobase)
1080 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1081 comedi_legacy_detach(dev);
1084 static const struct das16_board das16_boards[] = {
1087 .ai_maxdata = 0x0fff,
1089 .ai_pg = das16_pg_none,
1091 .i8255_offset = 0x10,
1092 .i8254_offset = 0x0c,
1097 .ai_maxdata = 0x0fff,
1099 .ai_pg = das16_pg_none,
1101 .i8255_offset = 0x10,
1102 .i8254_offset = 0x0c,
1107 .ai_maxdata = 0x0fff,
1109 .ai_pg = das16_pg_none,
1111 .i8255_offset = 0x10,
1112 .i8254_offset = 0x0c,
1116 .name = "cio-das16",
1117 .ai_maxdata = 0x0fff,
1119 .ai_pg = das16_pg_none,
1121 .i8255_offset = 0x10,
1122 .i8254_offset = 0x0c,
1126 .name = "cio-das16/f",
1127 .ai_maxdata = 0x0fff,
1129 .ai_pg = das16_pg_none,
1131 .i8255_offset = 0x10,
1132 .i8254_offset = 0x0c,
1136 .name = "cio-das16/jr",
1137 .ai_maxdata = 0x0fff,
1139 .ai_pg = das16_pg_16jr,
1141 .i8254_offset = 0x0c,
1145 .name = "pc104-das16jr",
1146 .ai_maxdata = 0x0fff,
1148 .ai_pg = das16_pg_16jr,
1150 .i8254_offset = 0x0c,
1154 .name = "cio-das16jr/16",
1155 .ai_maxdata = 0xffff,
1157 .ai_pg = das16_pg_16jr_16,
1159 .i8254_offset = 0x0c,
1163 .name = "pc104-das16jr/16",
1164 .ai_maxdata = 0xffff,
1166 .ai_pg = das16_pg_16jr_16,
1168 .i8254_offset = 0x0c,
1173 .ai_maxdata = 0x0fff,
1175 .ai_pg = das16_pg_none,
1176 .i8255_offset = 0x400,
1177 .i8254_offset = 0x0c,
1182 .ai_maxdata = 0x0fff,
1184 .ai_pg = das16_pg_none,
1185 .i8255_offset = 0x400,
1186 .i8254_offset = 0x0c,
1191 .ai_maxdata = 0x0fff,
1193 .ai_pg = das16_pg_1601,
1194 .i8255_offset = 0x0,
1195 .i8254_offset = 0x0c,
1200 .ai_maxdata = 0x0fff,
1202 .ai_pg = das16_pg_1602,
1203 .i8255_offset = 0x0,
1204 .i8254_offset = 0x0c,
1209 .ai_maxdata = 0x0fff,
1211 .ai_pg = das16_pg_1601,
1213 .i8255_offset = 0x400,
1214 .i8254_offset = 0x0c,
1219 .ai_maxdata = 0x0fff,
1221 .ai_pg = das16_pg_1602,
1223 .i8255_offset = 0x400,
1224 .i8254_offset = 0x0c,
1228 .name = "cio-das1401/12",
1229 .ai_maxdata = 0x0fff,
1231 .ai_pg = das16_pg_1601,
1233 .i8254_offset = 0x0c,
1237 .name = "cio-das1402/12",
1238 .ai_maxdata = 0x0fff,
1240 .ai_pg = das16_pg_1602,
1242 .i8254_offset = 0x0c,
1246 .name = "cio-das1402/16",
1247 .ai_maxdata = 0xffff,
1249 .ai_pg = das16_pg_1602,
1251 .i8254_offset = 0x0c,
1255 .name = "cio-das1601/12",
1256 .ai_maxdata = 0x0fff,
1258 .ai_pg = das16_pg_1601,
1260 .i8255_offset = 0x400,
1261 .i8254_offset = 0x0c,
1265 .name = "cio-das1602/12",
1266 .ai_maxdata = 0x0fff,
1268 .ai_pg = das16_pg_1602,
1270 .i8255_offset = 0x400,
1271 .i8254_offset = 0x0c,
1275 .name = "cio-das1602/16",
1276 .ai_maxdata = 0xffff,
1278 .ai_pg = das16_pg_1602,
1280 .i8255_offset = 0x400,
1281 .i8254_offset = 0x0c,
1285 .name = "cio-das16/330",
1286 .ai_maxdata = 0x0fff,
1288 .ai_pg = das16_pg_16jr,
1290 .i8254_offset = 0x0c,
1296 static struct comedi_driver das16_driver = {
1297 .driver_name = "das16",
1298 .module = THIS_MODULE,
1299 .attach = das16_attach,
1300 .detach = das16_detach,
1301 .board_name = &das16_boards[0].name,
1302 .num_names = ARRAY_SIZE(das16_boards),
1303 .offset = sizeof(das16_boards[0]),
1305 module_comedi_driver(das16_driver);
1307 MODULE_AUTHOR("Comedi http://www.comedi.org");
1308 MODULE_DESCRIPTION("Comedi low-level driver");
1309 MODULE_LICENSE("GPL");