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 /* the pc104-das16jr (at least) has problems if the dma
315 transfer is interrupted in the middle of transferring
316 a 16 bit sample, so this function takes care to get
317 an even transfer count after disabling dma
320 static int disable_dma_on_even(struct comedi_device *dev)
322 struct das16_private_struct *devpriv = dev->private;
325 static const int disable_limit = 100;
326 static const int enable_timeout = 100;
328 disable_dma(devpriv->dma_chan);
329 residue = get_dma_residue(devpriv->dma_chan);
330 for (i = 0; i < disable_limit && (residue % 2); ++i) {
332 enable_dma(devpriv->dma_chan);
333 for (j = 0; j < enable_timeout; ++j) {
336 new_residue = get_dma_residue(devpriv->dma_chan);
337 if (new_residue != residue)
340 disable_dma(devpriv->dma_chan);
341 residue = get_dma_residue(devpriv->dma_chan);
343 if (i == disable_limit) {
344 comedi_error(dev, "failed to get an even dma transfer, "
345 "could be trouble.");
350 static void das16_interrupt(struct comedi_device *dev)
352 struct das16_private_struct *devpriv = dev->private;
353 unsigned long dma_flags, spin_flags;
354 struct comedi_subdevice *s = dev->read_subdev;
355 struct comedi_async *async;
356 struct comedi_cmd *cmd;
357 int num_bytes, residue;
360 if (!dev->attached) {
361 comedi_error(dev, "premature interrupt");
364 /* initialize async here to make sure it is not NULL */
368 spin_lock_irqsave(&dev->spinlock, spin_flags);
369 if ((devpriv->ctrl_reg & DMA_ENABLE) == 0) {
370 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
374 dma_flags = claim_dma_lock();
375 clear_dma_ff(devpriv->dma_chan);
376 residue = disable_dma_on_even(dev);
378 /* figure out how many points to read */
379 if (residue > devpriv->dma_transfer_size) {
380 comedi_error(dev, "residue > transfer size!\n");
381 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
384 num_bytes = devpriv->dma_transfer_size - residue;
386 if (cmd->stop_src == TRIG_COUNT &&
387 num_bytes >= devpriv->adc_byte_count) {
388 num_bytes = devpriv->adc_byte_count;
389 async->events |= COMEDI_CB_EOA;
392 buffer_index = devpriv->current_buffer;
393 devpriv->current_buffer = (devpriv->current_buffer + 1) % 2;
394 devpriv->adc_byte_count -= num_bytes;
397 if ((async->events & COMEDI_CB_EOA) == 0) {
398 set_dma_addr(devpriv->dma_chan,
399 devpriv->dma_buffer_addr[devpriv->current_buffer]);
400 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
401 enable_dma(devpriv->dma_chan);
403 release_dma_lock(dma_flags);
405 spin_unlock_irqrestore(&dev->spinlock, spin_flags);
407 cfc_write_array_to_buffer(s,
408 devpriv->dma_buffer[buffer_index], num_bytes);
410 cfc_handle_events(dev, s);
413 static void das16_timer_interrupt(unsigned long arg)
415 struct comedi_device *dev = (struct comedi_device *)arg;
416 struct das16_private_struct *devpriv = dev->private;
418 das16_interrupt(dev);
420 if (devpriv->timer_running)
421 mod_timer(&devpriv->timer, jiffies + timer_period());
424 static int das16_cmd_test(struct comedi_device *dev, struct comedi_subdevice *s,
425 struct comedi_cmd *cmd)
427 const struct das16_board *board = comedi_board(dev);
428 struct das16_private_struct *devpriv = dev->private;
430 int gain, start_chan, i;
433 /* Step 1 : check if triggers are trivially valid */
435 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
438 if (devpriv->can_burst)
439 mask |= TRIG_TIMER | TRIG_EXT;
440 err |= cfc_check_trigger_src(&cmd->scan_begin_src, mask);
442 tmp = cmd->convert_src;
443 mask = TRIG_TIMER | TRIG_EXT;
444 if (devpriv->can_burst)
446 err |= cfc_check_trigger_src(&cmd->convert_src, mask);
448 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
449 err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
454 /* Step 2a : make sure trigger sources are unique */
456 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
457 err |= cfc_check_trigger_is_unique(cmd->convert_src);
458 err |= cfc_check_trigger_is_unique(cmd->stop_src);
460 /* Step 2b : and mutually compatible */
462 /* make sure scan_begin_src and convert_src dont conflict */
463 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
465 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
471 /* Step 3: check if arguments are trivially valid */
473 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
475 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */
476 err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
478 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
480 /* check against maximum frequency */
481 if (cmd->scan_begin_src == TRIG_TIMER)
482 err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg,
483 board->ai_speed * cmd->chanlist_len);
485 if (cmd->convert_src == TRIG_TIMER)
486 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
489 if (cmd->stop_src == TRIG_NONE)
490 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
495 /* step 4: fix up arguments */
496 if (cmd->scan_begin_src == TRIG_TIMER) {
497 unsigned int tmp = cmd->scan_begin_arg;
498 /* set divisors, correct timing arguments */
499 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
500 &(devpriv->divisor1),
501 &(devpriv->divisor2),
502 &(cmd->scan_begin_arg),
503 cmd->flags & TRIG_ROUND_MASK);
504 err += (tmp != cmd->scan_begin_arg);
506 if (cmd->convert_src == TRIG_TIMER) {
507 unsigned int tmp = cmd->convert_arg;
508 /* set divisors, correct timing arguments */
509 i8253_cascade_ns_to_timer_2div(devpriv->clockbase,
510 &(devpriv->divisor1),
511 &(devpriv->divisor2),
513 cmd->flags & TRIG_ROUND_MASK);
514 err += (tmp != cmd->convert_arg);
519 /* check channel/gain list against card's limitations */
521 gain = CR_RANGE(cmd->chanlist[0]);
522 start_chan = CR_CHAN(cmd->chanlist[0]);
523 for (i = 1; i < cmd->chanlist_len; i++) {
524 if (CR_CHAN(cmd->chanlist[i]) !=
525 (start_chan + i) % s->n_chan) {
527 "entries in chanlist must be "
528 "consecutive channels, "
529 "counting upwards\n");
532 if (CR_RANGE(cmd->chanlist[i]) != gain) {
534 "entries in chanlist must all "
535 "have the same gain\n");
546 static unsigned int das16_set_pacer(struct comedi_device *dev, unsigned int ns,
549 struct das16_private_struct *devpriv = dev->private;
551 i8253_cascade_ns_to_timer_2div(devpriv->clockbase, &(devpriv->divisor1),
552 &(devpriv->divisor2), &ns,
553 rounding_flags & TRIG_ROUND_MASK);
555 /* Write the values of ctr1 and ctr2 into counters 1 and 2 */
556 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 1, devpriv->divisor1, 2);
557 i8254_load(dev->iobase + DAS16_CNTR0_DATA, 0, 2, devpriv->divisor2, 2);
562 static int das16_cmd_exec(struct comedi_device *dev, struct comedi_subdevice *s)
564 const struct das16_board *board = comedi_board(dev);
565 struct das16_private_struct *devpriv = dev->private;
566 struct comedi_async *async = s->async;
567 struct comedi_cmd *cmd = &async->cmd;
572 if (cmd->flags & TRIG_RT) {
573 comedi_error(dev, "isa dma transfers cannot be performed with "
574 "TRIG_RT, aborting");
578 devpriv->adc_byte_count =
579 cmd->stop_arg * cmd->chanlist_len * sizeof(uint16_t);
581 if (devpriv->can_burst)
582 outb(DAS1600_CONV_DISABLE, dev->iobase + DAS1600_CONV);
584 /* set scan limits */
585 byte = CR_CHAN(cmd->chanlist[0]);
586 byte |= CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1]) << 4;
587 outb(byte, dev->iobase + DAS16_MUX);
589 /* set gain (this is also burst rate register but according to
590 * computer boards manual, burst rate does nothing, even on
592 if (board->ai_pg != das16_pg_none) {
593 range = CR_RANGE(cmd->chanlist[0]);
594 outb((das16_gainlists[board->ai_pg])[range],
595 dev->iobase + DAS16_GAIN);
598 /* set counter mode and counts */
600 das16_set_pacer(dev, cmd->convert_arg,
601 cmd->flags & TRIG_ROUND_MASK);
603 /* enable counters */
605 if (devpriv->can_burst) {
606 if (cmd->convert_src == TRIG_NOW) {
607 outb(DAS1600_BURST_VAL, dev->iobase + DAS1600_BURST);
608 /* set burst length */
609 byte |= BURST_LEN_BITS(cmd->chanlist_len - 1);
611 outb(0, dev->iobase + DAS1600_BURST);
614 outb(byte, dev->iobase + DAS16_PACER);
616 /* set up dma transfer */
617 flags = claim_dma_lock();
618 disable_dma(devpriv->dma_chan);
619 /* clear flip-flop to make sure 2-byte registers for
620 * count and address get set correctly */
621 clear_dma_ff(devpriv->dma_chan);
622 devpriv->current_buffer = 0;
623 set_dma_addr(devpriv->dma_chan,
624 devpriv->dma_buffer_addr[devpriv->current_buffer]);
625 devpriv->dma_transfer_size = DAS16_DMA_SIZE;
626 set_dma_count(devpriv->dma_chan, devpriv->dma_transfer_size);
627 enable_dma(devpriv->dma_chan);
628 release_dma_lock(flags);
630 /* set up interrupt */
631 devpriv->timer_running = 1;
632 devpriv->timer.expires = jiffies + timer_period();
633 add_timer(&devpriv->timer);
635 das16_ai_enable(dev, DMA_ENABLE, cmd->convert_src);
637 if (devpriv->can_burst)
638 outb(0, dev->iobase + DAS1600_CONV);
643 static int das16_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
645 struct das16_private_struct *devpriv = dev->private;
648 spin_lock_irqsave(&dev->spinlock, flags);
650 das16_ai_disable(dev);
651 disable_dma(devpriv->dma_chan);
653 /* disable SW timer */
654 if (devpriv->timer_running) {
655 devpriv->timer_running = 0;
656 del_timer(&devpriv->timer);
659 if (devpriv->can_burst)
660 outb(0, dev->iobase + DAS1600_BURST);
662 spin_unlock_irqrestore(&dev->spinlock, flags);
667 static void das16_ai_munge(struct comedi_device *dev,
668 struct comedi_subdevice *s, void *array,
669 unsigned int num_bytes,
670 unsigned int start_chan_index)
672 unsigned int i, num_samples = num_bytes / sizeof(short);
675 for (i = 0; i < num_samples; i++) {
676 data[i] = le16_to_cpu(data[i]);
677 if (s->maxdata == 0x0fff)
679 data[i] &= s->maxdata;
683 static int das16_ai_wait_for_conv(struct comedi_device *dev,
684 unsigned int timeout)
689 for (i = 0; i < timeout; i++) {
690 status = inb(dev->iobase + DAS16_STATUS);
691 if (!(status & BUSY))
697 static int das16_ai_insn_read(struct comedi_device *dev,
698 struct comedi_subdevice *s,
699 struct comedi_insn *insn,
702 const struct das16_board *board = comedi_board(dev);
703 unsigned int chan = CR_CHAN(insn->chanspec);
704 unsigned int range = CR_RANGE(insn->chanspec);
709 das16_ai_disable(dev);
711 /* set multiplexer */
712 outb(chan | (chan << 4), dev->iobase + DAS16_MUX);
715 if (board->ai_pg != das16_pg_none) {
716 outb((das16_gainlists[board->ai_pg])[range],
717 dev->iobase + DAS16_GAIN);
720 for (i = 0; i < insn->n; i++) {
721 /* trigger conversion */
722 outb_p(0, dev->iobase + DAS16_TRIG);
724 ret = das16_ai_wait_for_conv(dev, 1000);
728 val = inb(dev->iobase + DAS16_AI_MSB) << 8;
729 val |= inb(dev->iobase + DAS16_AI_LSB);
730 if (s->maxdata == 0x0fff)
740 static int das16_ao_insn_write(struct comedi_device *dev,
741 struct comedi_subdevice *s,
742 struct comedi_insn *insn,
745 unsigned int chan = CR_CHAN(insn->chanspec);
749 for (i = 0; i < insn->n; i++) {
753 outb(val & 0xff, dev->iobase + DAS16_AO_LSB(chan));
754 outb((val >> 8) & 0xff, dev->iobase + DAS16_AO_MSB(chan));
760 static int das16_di_insn_bits(struct comedi_device *dev,
761 struct comedi_subdevice *s,
762 struct comedi_insn *insn,
765 data[1] = inb(dev->iobase + DAS16_DIO) & 0xf;
770 static int das16_do_insn_bits(struct comedi_device *dev,
771 struct comedi_subdevice *s,
772 struct comedi_insn *insn,
775 unsigned int mask = data[0];
776 unsigned int bits = data[1];
780 s->state |= (bits & mask);
782 outb(s->state, dev->iobase + DAS16_DIO);
790 static int das16_probe(struct comedi_device *dev, struct comedi_devconfig *it)
792 const struct das16_board *board = comedi_board(dev);
795 /* diobits indicates boards */
796 diobits = inb(dev->iobase + DAS16_DIO) & 0xf0;
798 printk(KERN_INFO " id bits are 0x%02x\n", diobits);
799 if (board->id != diobits) {
800 printk(KERN_INFO " requested board's id bits are 0x%x (ignore)\n",
807 static int das1600_mode_detect(struct comedi_device *dev)
809 struct das16_private_struct *devpriv = dev->private;
812 status = inb(dev->iobase + DAS1600_STATUS_B);
814 if (status & DAS1600_CLK_10MHZ) {
815 devpriv->clockbase = 100;
816 printk(KERN_INFO " 10MHz pacer clock\n");
818 devpriv->clockbase = 1000;
819 printk(KERN_INFO " 1MHz pacer clock\n");
825 static void das16_reset(struct comedi_device *dev)
827 outb(0, dev->iobase + DAS16_STATUS);
828 outb(0, dev->iobase + DAS16_CONTROL);
829 outb(0, dev->iobase + DAS16_PACER);
830 outb(0, dev->iobase + DAS16_CNTR_CONTROL);
833 static int das16_attach(struct comedi_device *dev, struct comedi_devconfig *it)
835 const struct das16_board *board = comedi_board(dev);
836 struct das16_private_struct *devpriv;
837 struct comedi_subdevice *s;
838 struct comedi_krange *user_ai_range;
839 struct comedi_krange *user_ao_range;
840 unsigned int dma_chan = it->options[2];
844 /* check that clock setting is valid */
845 if (it->options[3]) {
846 if (it->options[3] != 0 &&
847 it->options[3] != 1 && it->options[3] != 10) {
849 ("\n Invalid option. Master clock must be set "
850 "to 1 or 10 (MHz)\n");
855 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
859 if (board->size < 0x400) {
860 ret = comedi_request_region(dev, it->options[0], board->size);
864 ret = comedi_request_region(dev, it->options[0], 0x10);
867 /* Request an additional region for the 8255 */
868 ret = __comedi_request_region(dev, dev->iobase + 0x400,
869 board->size & 0x3ff);
872 devpriv->extra_iobase = dev->iobase + 0x400;
873 devpriv->can_burst = 1;
876 /* probe id bits to make sure they are consistent */
877 if (das16_probe(dev, it)) {
878 printk(KERN_ERR " id bits do not match selected board, aborting\n");
882 /* get master clock speed */
883 if (devpriv->can_burst) {
884 das1600_mode_detect(dev);
887 devpriv->clockbase = 1000 / it->options[3];
889 devpriv->clockbase = 1000; /* 1 MHz default */
893 if (dma_chan == 1 || dma_chan == 3) {
897 if (request_dma(dma_chan, dev->board_name)) {
898 dev_err(dev->class_dev,
899 "failed to request dma channel %i\n",
903 devpriv->dma_chan = dma_chan;
905 /* allocate dma buffers */
906 for (i = 0; i < 2; i++) {
909 p = pci_alloc_consistent(NULL, DAS16_DMA_SIZE,
910 &devpriv->dma_buffer_addr[i]);
913 devpriv->dma_buffer[i] = p;
916 flags = claim_dma_lock();
917 disable_dma(devpriv->dma_chan);
918 set_dma_mode(devpriv->dma_chan, DMA_MODE_READ);
919 release_dma_lock(flags);
921 init_timer(&(devpriv->timer));
922 devpriv->timer.function = das16_timer_interrupt;
923 devpriv->timer.data = (unsigned long)dev;
926 /* get any user-defined input range */
927 if (board->ai_pg == das16_pg_none &&
928 (it->options[4] || it->options[5])) {
929 /* allocate single-range range table */
930 devpriv->user_ai_range_table =
931 kmalloc(sizeof(struct comedi_lrange) +
932 sizeof(struct comedi_krange), GFP_KERNEL);
933 /* initialize ai range */
934 devpriv->user_ai_range_table->length = 1;
935 user_ai_range = devpriv->user_ai_range_table->range;
936 user_ai_range->min = it->options[4];
937 user_ai_range->max = it->options[5];
938 user_ai_range->flags = UNIT_volt;
940 /* get any user-defined output range */
941 if (it->options[6] || it->options[7]) {
942 /* allocate single-range range table */
943 devpriv->user_ao_range_table =
944 kmalloc(sizeof(struct comedi_lrange) +
945 sizeof(struct comedi_krange), GFP_KERNEL);
946 /* initialize ao range */
947 devpriv->user_ao_range_table->length = 1;
948 user_ao_range = devpriv->user_ao_range_table->range;
949 user_ao_range->min = it->options[6];
950 user_ao_range->max = it->options[7];
951 user_ao_range->flags = UNIT_volt;
954 ret = comedi_alloc_subdevices(dev, 5);
958 status = inb(dev->iobase + DAS16_STATUS);
960 /* Analog Input subdevice */
961 s = &dev->subdevices[0];
962 s->type = COMEDI_SUBD_AI;
963 s->subdev_flags = SDF_READABLE;
964 if (status & DAS16_MUXBIT) {
965 s->subdev_flags |= SDF_GROUND;
968 s->subdev_flags |= SDF_DIFF;
971 s->len_chanlist = s->n_chan;
972 s->maxdata = board->ai_maxdata;
973 if (devpriv->user_ai_range_table) { /* user defined ai range */
974 s->range_table = devpriv->user_ai_range_table;
975 } else if (status & UNIPOLAR) {
976 s->range_table = das16_ai_uni_lranges[board->ai_pg];
978 s->range_table = das16_ai_bip_lranges[board->ai_pg];
980 s->insn_read = das16_ai_insn_read;
981 if (devpriv->dma_chan) {
982 dev->read_subdev = s;
983 s->subdev_flags |= SDF_CMD_READ;
984 s->do_cmdtest = das16_cmd_test;
985 s->do_cmd = das16_cmd_exec;
986 s->cancel = das16_cancel;
987 s->munge = das16_ai_munge;
990 /* Analog Output subdevice */
991 s = &dev->subdevices[1];
993 s->type = COMEDI_SUBD_AO;
994 s->subdev_flags = SDF_WRITABLE;
997 if (devpriv->user_ao_range_table)
998 s->range_table = devpriv->user_ao_range_table;
1000 s->range_table = &range_unknown;
1002 s->insn_write = das16_ao_insn_write;
1004 s->type = COMEDI_SUBD_UNUSED;
1007 /* Digital Input subdevice */
1008 s = &dev->subdevices[2];
1009 s->type = COMEDI_SUBD_DI;
1010 s->subdev_flags = SDF_READABLE;
1013 s->range_table = &range_digital;
1014 s->insn_bits = das16_di_insn_bits;
1016 /* Digital Output subdevice */
1017 s = &dev->subdevices[3];
1018 s->type = COMEDI_SUBD_DO;
1019 s->subdev_flags = SDF_WRITABLE;
1022 s->range_table = &range_digital;
1023 s->insn_bits = das16_do_insn_bits;
1025 /* initialize digital output lines */
1026 outb(s->state, dev->iobase + DAS16_DIO);
1028 s = &dev->subdevices[4];
1030 if (board->i8255_offset != 0) {
1031 subdev_8255_init(dev, s, NULL, (dev->iobase +
1032 board->i8255_offset));
1034 s->type = COMEDI_SUBD_UNUSED;
1038 /* set the interrupt level */
1039 devpriv->ctrl_reg = DAS16_IRQ(dev->irq);
1040 outb(devpriv->ctrl_reg, dev->iobase + DAS16_CONTROL);
1042 if (devpriv->can_burst) {
1043 outb(DAS1600_ENABLE_VAL, dev->iobase + DAS1600_ENABLE);
1044 outb(0, dev->iobase + DAS1600_CONV);
1045 outb(0, dev->iobase + DAS1600_BURST);
1051 static void das16_detach(struct comedi_device *dev)
1053 const struct das16_board *board = comedi_board(dev);
1054 struct das16_private_struct *devpriv = dev->private;
1059 for (i = 0; i < 2; i++) {
1060 if (devpriv->dma_buffer[i])
1061 pci_free_consistent(NULL, DAS16_DMA_SIZE,
1062 devpriv->dma_buffer[i],
1064 dma_buffer_addr[i]);
1066 if (devpriv->dma_chan)
1067 free_dma(devpriv->dma_chan);
1068 kfree(devpriv->user_ai_range_table);
1069 kfree(devpriv->user_ao_range_table);
1071 if (devpriv->extra_iobase)
1072 release_region(devpriv->extra_iobase, board->size & 0x3ff);
1073 comedi_legacy_detach(dev);
1076 static const struct das16_board das16_boards[] = {
1079 .ai_maxdata = 0x0fff,
1081 .ai_pg = das16_pg_none,
1083 .i8255_offset = 0x10,
1084 .i8254_offset = 0x0c,
1089 .ai_maxdata = 0x0fff,
1091 .ai_pg = das16_pg_none,
1093 .i8255_offset = 0x10,
1094 .i8254_offset = 0x0c,
1099 .ai_maxdata = 0x0fff,
1101 .ai_pg = das16_pg_none,
1103 .i8255_offset = 0x10,
1104 .i8254_offset = 0x0c,
1108 .name = "cio-das16",
1109 .ai_maxdata = 0x0fff,
1111 .ai_pg = das16_pg_none,
1113 .i8255_offset = 0x10,
1114 .i8254_offset = 0x0c,
1118 .name = "cio-das16/f",
1119 .ai_maxdata = 0x0fff,
1121 .ai_pg = das16_pg_none,
1123 .i8255_offset = 0x10,
1124 .i8254_offset = 0x0c,
1128 .name = "cio-das16/jr",
1129 .ai_maxdata = 0x0fff,
1131 .ai_pg = das16_pg_16jr,
1133 .i8254_offset = 0x0c,
1137 .name = "pc104-das16jr",
1138 .ai_maxdata = 0x0fff,
1140 .ai_pg = das16_pg_16jr,
1142 .i8254_offset = 0x0c,
1146 .name = "cio-das16jr/16",
1147 .ai_maxdata = 0xffff,
1149 .ai_pg = das16_pg_16jr_16,
1151 .i8254_offset = 0x0c,
1155 .name = "pc104-das16jr/16",
1156 .ai_maxdata = 0xffff,
1158 .ai_pg = das16_pg_16jr_16,
1160 .i8254_offset = 0x0c,
1165 .ai_maxdata = 0x0fff,
1167 .ai_pg = das16_pg_none,
1168 .i8255_offset = 0x400,
1169 .i8254_offset = 0x0c,
1174 .ai_maxdata = 0x0fff,
1176 .ai_pg = das16_pg_none,
1177 .i8255_offset = 0x400,
1178 .i8254_offset = 0x0c,
1183 .ai_maxdata = 0x0fff,
1185 .ai_pg = das16_pg_1601,
1186 .i8255_offset = 0x0,
1187 .i8254_offset = 0x0c,
1192 .ai_maxdata = 0x0fff,
1194 .ai_pg = das16_pg_1602,
1195 .i8255_offset = 0x0,
1196 .i8254_offset = 0x0c,
1201 .ai_maxdata = 0x0fff,
1203 .ai_pg = das16_pg_1601,
1205 .i8255_offset = 0x400,
1206 .i8254_offset = 0x0c,
1211 .ai_maxdata = 0x0fff,
1213 .ai_pg = das16_pg_1602,
1215 .i8255_offset = 0x400,
1216 .i8254_offset = 0x0c,
1220 .name = "cio-das1401/12",
1221 .ai_maxdata = 0x0fff,
1223 .ai_pg = das16_pg_1601,
1225 .i8254_offset = 0x0c,
1229 .name = "cio-das1402/12",
1230 .ai_maxdata = 0x0fff,
1232 .ai_pg = das16_pg_1602,
1234 .i8254_offset = 0x0c,
1238 .name = "cio-das1402/16",
1239 .ai_maxdata = 0xffff,
1241 .ai_pg = das16_pg_1602,
1243 .i8254_offset = 0x0c,
1247 .name = "cio-das1601/12",
1248 .ai_maxdata = 0x0fff,
1250 .ai_pg = das16_pg_1601,
1252 .i8255_offset = 0x400,
1253 .i8254_offset = 0x0c,
1257 .name = "cio-das1602/12",
1258 .ai_maxdata = 0x0fff,
1260 .ai_pg = das16_pg_1602,
1262 .i8255_offset = 0x400,
1263 .i8254_offset = 0x0c,
1267 .name = "cio-das1602/16",
1268 .ai_maxdata = 0xffff,
1270 .ai_pg = das16_pg_1602,
1272 .i8255_offset = 0x400,
1273 .i8254_offset = 0x0c,
1277 .name = "cio-das16/330",
1278 .ai_maxdata = 0x0fff,
1280 .ai_pg = das16_pg_16jr,
1282 .i8254_offset = 0x0c,
1288 static struct comedi_driver das16_driver = {
1289 .driver_name = "das16",
1290 .module = THIS_MODULE,
1291 .attach = das16_attach,
1292 .detach = das16_detach,
1293 .board_name = &das16_boards[0].name,
1294 .num_names = ARRAY_SIZE(das16_boards),
1295 .offset = sizeof(das16_boards[0]),
1297 module_comedi_driver(das16_driver);
1299 MODULE_AUTHOR("Comedi http://www.comedi.org");
1300 MODULE_DESCRIPTION("Comedi low-level driver");
1301 MODULE_LICENSE("GPL");