From 98a6d49b74ee3edc229b2d5f7e8ee757d2c2c8ba Mon Sep 17 00:00:00 2001 From: Frank Mori Hess Date: Sat, 9 Jun 2001 22:24:59 +0000 Subject: [PATCH] added support for cio-das802/16 to das800 driver --- Documentation/comedi/drivers.txt | 5 +- Documentation/comedi/hardware | 1 + comedi/drivers/das800.c | 105 +++++++++++++++++++++++++------ 3 files changed, 90 insertions(+), 21 deletions(-) diff --git a/Documentation/comedi/drivers.txt b/Documentation/comedi/drivers.txt index 66bf4a95..f7439a28 100644 --- a/Documentation/comedi/drivers.txt +++ b/Documentation/comedi/drivers.txt @@ -141,6 +141,7 @@ Options (for ISA cards): Options (for pci-das08): [0] - bus (optional) [1] = slot (optional) +Use the name 'pci-das08' for the pci-das08, NOT 'das08'. The das08 driver doesn't support asynchronous commands, since the el cheapo das08 hardware doesn't really support them. The @@ -269,7 +270,8 @@ Status: unknown Driver: das800.o Description: Keithley Metrabyte DAS800 (& compatibles) Author: Frank Mori Hess -Status: works +Status: works, cio-das802/16 untested - email me if you have tested it + Recognizes the following board names: @@ -279,6 +281,7 @@ das-802 cio-das800 cio-das801 cio-das802 +cio-das802/16 Configuration options: [0] - base io address diff --git a/Documentation/comedi/hardware b/Documentation/comedi/hardware index 13969b1f..2377d45f 100644 --- a/Documentation/comedi/hardware +++ b/Documentation/comedi/hardware @@ -61,6 +61,7 @@ ComputerBoards CIO-DAS16/330 das16 ComputerBoards CIO-DAS800 das800 ComputerBoards CIO-DAS801 das800 ComputerBoards CIO-DAS802 das800 +ComputerBoards CIO-DAS802/16 das800 ComputerBoards PCI-DAS08 das08 ComputerBoards PCI-DAS1200 cb_pcidas Data Translation DT21-EZ dt282x diff --git a/comedi/drivers/das800.c b/comedi/drivers/das800.c index f8b075a9..41ded3d3 100644 --- a/comedi/drivers/das800.c +++ b/comedi/drivers/das800.c @@ -30,6 +30,7 @@ and Measurement Computing (Computer Boards) models: cio-das800 cio-das801 cio-das802 +cio-das802/16 Options: [0] - base io address @@ -52,6 +53,9 @@ NOTES: I've never tested the gain setting stuff since I only have a DAS-800 board with fixed gain. + The cio-das802/16 does not have a fifo-empty status bit! Therefore + only fifo-half-full transfers are possible with this card. + */ #include @@ -93,6 +97,8 @@ NOTES: #define IRQ 0x8 #define BUSY 0x80 #define DAS800_GAIN 3 +#define FFOV 0x8 // fifo overflow for cio-das802/16 +#define ENHF 0x90 // interrupt fifo half full for cio-das802/16 #define CONTROL1 0x80 #define CONV_CONTROL 0xa0 #define SCAN_LIMITS 0xc0 @@ -106,6 +112,7 @@ typedef struct das800_board_struct{ char *name; int ai_speed; comedi_lrange *ai_range; + int resolution; }das800_board; //analog input ranges @@ -161,7 +168,21 @@ static comedi_lrange range_das802_ai = { } }; -enum{das800, ciodas800, das801, ciodas801, das802, ciodas802}; +static comedi_lrange range_das80216_ai = { + 8, + { + RANGE(-10, 10), + RANGE(0, 10), + RANGE(-5, 5), + RANGE(0, 5), + RANGE(-2.5, 2.5), + RANGE(0, 2.5), + RANGE(-1.25, 1.25), + RANGE(0, 1.25), + } +}; + +enum{das800, ciodas800, das801, ciodas801, das802, ciodas802, ciodas80216}; das800_board das800_boards[] = { @@ -169,31 +190,43 @@ das800_board das800_boards[] = name: "das-800", ai_speed: 25000, ai_range: &range_das800_ai, + resolution: 12, }, { name: "cio-das800", ai_speed: 20000, ai_range: &range_das800_ai, + resolution: 12, }, { name: "das-801", ai_speed: 25000, ai_range: &range_das801_ai, + resolution: 12, }, { name: "cio-das801", ai_speed: 20000, ai_range: &range_cio_das801_ai, + resolution: 12, }, { name: "das-802", ai_speed: 25000, ai_range: &range_das802_ai, + resolution: 12, }, { name: "cio-das802", ai_speed: 20000, ai_range: &range_das802_ai, + resolution: 12, + }, + { + name: "cio-das802/16", + ai_speed: 10000, + ai_range: &range_das80216_ai, + resolution: 16, }, }; /* @@ -295,12 +328,17 @@ int das800_probe(comedi_device *dev) printk(" Board model: CIO-DAS802\n"); return board; } + if(board == ciodas80216) + { + printk(" Board model: CIO-DAS802/16\n"); + return board; + } printk(" Board model (probed): DAS-802\n"); return das802; break; default : printk(" Board model: probe returned 0x%x (unknown)\n", id_bits); - return -1; + return board; break; } return -1; @@ -322,12 +360,17 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) comedi_async *async; int status; unsigned long irq_flags; - static const int max_loops = 256; + static const int max_loops = 128; // half-fifo size for cio-das802/16 + // flags + int fifo_empty = 0; + int fifo_overflow = 0; status = inb(dev->iobase + DAS800_STATUS); - /* if interupt was not generated by board or driver not attached, quit */ + /* if interrupt was not generated by board or driver not attached, quit */ if(!(status & IRQ) || !(dev->attached)) + { return; + } /* wait until here to initialize async, since we will get null dereference * if interrupt occurs before driver is fully attached! @@ -345,14 +388,27 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) return; } - /* loop while card's fifo is not empty (and make sure loop terminates by limiting to 256 iterations) */ + if(thisboard->resolution == 16) + { + fifo_empty = 0; // cio-das802/16 has no fifo-empty status bit + fifo_overflow = inb(dev->iobase + DAS800_GAIN) & FFOV; + } + /* loop while card's fifo is not empty (and limit to half fifo for cio-das802/16) */ for(i = 0; i < max_loops; i++) { /* read 16 bits from dev->iobase and dev->iobase + 1 */ dataPoint = inb(dev->iobase + DAS800_LSB); dataPoint += inb(dev->iobase + DAS800_MSB) << 8; - if(dataPoint & FIFO_EMPTY) break; - if( dataPoint & FIFO_OVF ) + if(thisboard->resolution == 12) + { + fifo_empty = dataPoint & FIFO_EMPTY; + fifo_overflow = dataPoint & FIFO_OVF; + } + if(fifo_empty) + { + break; + } + if(fifo_overflow) { comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); comedi_error(dev, "DAS800 FIFO overflow"); @@ -360,7 +416,9 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) comedi_error_done(dev, s); return; } - dataPoint = (dataPoint >> 4) & 0xfff; /* strip off extraneous bits */ + /* strip off extraneous bits for 12 bit cards*/ + if(thisboard->resolution == 12) + dataPoint = (dataPoint >> 4) & 0xfff; /* if there are more data points to collect */ if(devpriv->count > 0 || devpriv->forever == 1) { @@ -382,28 +440,31 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) if(devpriv->count > 0) devpriv->count--; } } - /* we can release spinlock now since we dont case if hardware conversions are enabled anymore */ - comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); if(i == max_loops) comedi_error(dev, "possible problem with loop in interrupt handler"); comedi_bufcheck(dev,s); if(devpriv->count > 0 || devpriv->forever == 1) { - /* Re-enable card's interrupt */ - comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + /* Re-enable card's interrupt. + * We already have spinlock, so indirect addressing is safe */ outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ outb(CONTROL1_INTE | devpriv->do_bits, dev->iobase + DAS800_CONTROL1); - comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); /* otherwise, stop taking data */ } else { - /* read 16 bits from dev->iobase and dev->iobase + 1 */ - dataPoint = inb(dev->iobase + DAS800_LSB); - dataPoint += inb(dev->iobase + DAS800_MSB) << 8; /* check for overflow on last data point */ - if( dataPoint & FIFO_OVF ) + if(thisboard->resolution == 12) + { + fifo_overflow = inb(dev->iobase + DAS800_LSB) & FIFO_OVF; + // else cio-das802/16 + }else { + fifo_overflow = inb(dev->iobase + DAS800_GAIN) & FFOV; + } + if(fifo_overflow) + { + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); comedi_error(dev, "DAS800 FIFO overflow"); das800_cancel(dev, dev->subdevices + 0); comedi_error_done(dev, s); @@ -412,6 +473,7 @@ static void das800_interrupt(int irq, void *d, struct pt_regs *regs) disable_das800(dev); /* diable hardware triggered conversions */ comedi_done(dev, s); } + comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags); return; } @@ -486,7 +548,7 @@ static int das800_attach(comedi_device *dev, comedi_devconfig *it) s->subdev_flags = SDF_READABLE; s->n_chan = 8; s->len_chanlist = 8; - s->maxdata = 0xfff; + s->maxdata = (1 << thisboard->resolution) - 1; s->range_table = thisboard->ai_range; s->do_cmd = das800_ai_do_cmd; s->do_cmdtest = das800_ai_do_cmdtest; @@ -549,6 +611,9 @@ void enable_das800(comedi_device *dev) { unsigned long irq_flags; comedi_spin_lock_irqsave(&dev->spinlock, irq_flags); + // enable fifo-half full interrupts for + if(thisboard->resolution == 16) + outb(ENHF, dev->iobase + DAS800_GAIN); outb(CONV_CONTROL, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be conversion control register */ outb(CONV_HCEN, dev->iobase + DAS800_CONV_CONTROL); /* enable hardware triggering */ outb(CONTROL1, dev->iobase + DAS800_GAIN); /* select dev->iobase + 2 to be control register 1 */ @@ -716,7 +781,7 @@ static int das800_ai_do_cmd(comedi_device *dev, comedi_subdevice *s) /* set gain */ gain = CR_RANGE(async->cmd.chanlist[0]); - if( gain > 0) + if( thisboard->resolution == 12 && gain > 0) gain += 0x7; gain &= 0xf; outb(gain, dev->iobase + DAS800_GAIN); @@ -790,7 +855,7 @@ static int das800_ai_rinsn(comedi_device *dev, comedi_subdevice *s, comedi_insn /* set gain / range */ range = CR_RANGE(insn->chanspec); - if(range) + if(thisboard->resolution == 12 && range) range += 0x7; range &= 0xf; outb(range, dev->iobase + DAS800_GAIN); -- 2.26.2