added support for cio-das802/16 to das800 driver
authorFrank Mori Hess <fmhess@speakeasy.net>
Sat, 9 Jun 2001 22:24:59 +0000 (22:24 +0000)
committerFrank Mori Hess <fmhess@speakeasy.net>
Sat, 9 Jun 2001 22:24:59 +0000 (22:24 +0000)
Documentation/comedi/drivers.txt
Documentation/comedi/hardware
comedi/drivers/das800.c

index 66bf4a95826b7bcabe7c1c52bdef37cfaa80c3d9..f7439a286af1d8067fc7a8286e8ac9eab9f4e509 100644 (file)
@@ -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 <fmhess@uiuc.edu>
-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
index 13969b1ff9d21b80ab036b2f39115fcad98db7d0..2377d45f2238db9d83b3b107f1298b8336d448e3 100644 (file)
@@ -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
index f8b075a9447fbb79f4b19e82cae05f9be65ff4cb..41ded3d350e6d2aaa328608614fc646a6a09d812 100644 (file)
@@ -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 <linux/kernel.h>
@@ -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);