]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/staging/comedi/drivers/das800.c
Merge branch 'for-4.8/core' of git://git.kernel.dk/linux-block
[karo-tx-linux.git] / drivers / staging / comedi / drivers / das800.c
index 39d304a1259f4fe2e9be0dad8675f1e2af4f21b7..fd4cb4911671ce1fa145a57473d3b0ba90bea34d 100644 (file)
@@ -1,56 +1,56 @@
 /*
   comedi/drivers/das800.c
   Driver for Keitley das800 series boards and compatibles
   Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
-
   COMEDI - Linux Control and Measurement Device Interface
   Copyright (C) 2000 David A. Schleef <ds@schleef.org>
-
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
-
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
-*/
* comedi/drivers/das800.c
* Driver for Keitley das800 series boards and compatibles
* Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
+ *
* COMEDI - Linux Control and Measurement Device Interface
* Copyright (C) 2000 David A. Schleef <ds@schleef.org>
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
+ */
 /*
-Driver: das800
-Description: Keithley Metrabyte DAS800 (& compatibles)
-Author: Frank Mori Hess <fmhess@users.sourceforge.net>
-Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
-  DAS-802 (das-802),
-  [Measurement Computing] CIO-DAS800 (cio-das800),
-  CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
-  CIO-DAS802/16 (cio-das802/16)
-Status: works, cio-das802/16 untested - email me if you have tested it
-
-Configuration options:
-  [0] - I/O port base address
-  [1] - IRQ (optional, required for timed or externally triggered conversions)
-
-Notes:
      IRQ can be omitted, although the cmd interface will not work without it.
-
      All entries in the channel/gain list must use the same gain and be
      consecutive channels counting upwards in channel number (these are
      hardware limitations.)
-
      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.
-
-cmd triggers supported:
      start_src:      TRIG_NOW | TRIG_EXT
      scan_begin_src: TRIG_FOLLOW
      scan_end_src:   TRIG_COUNT
      convert_src:    TRIG_TIMER | TRIG_EXT
      stop_src:       TRIG_NONE | TRIG_COUNT
-*/
+ * Driver: das800
+ * Description: Keithley Metrabyte DAS800 (& compatibles)
+ * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
+ * Devices: [Keithley Metrabyte] DAS-800 (das-800), DAS-801 (das-801),
* DAS-802 (das-802),
* [Measurement Computing] CIO-DAS800 (cio-das800),
* CIO-DAS801 (cio-das801), CIO-DAS802 (cio-das802),
* CIO-DAS802/16 (cio-das802/16)
+ * Status: works, cio-das802/16 untested - email me if you have tested it
+ *
+ * Configuration options:
* [0] - I/O port base address
* [1] - IRQ (optional, required for timed or externally triggered conversions)
+ *
+ * Notes:
*     IRQ can be omitted, although the cmd interface will not work without it.
+ *
*     All entries in the channel/gain list must use the same gain and be
*     consecutive channels counting upwards in channel number (these are
*     hardware limitations.)
+ *
*     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.
+ *
+ * cmd triggers supported:
*     start_src:      TRIG_NOW | TRIG_EXT
*     scan_begin_src: TRIG_FOLLOW
*     scan_end_src:   TRIG_COUNT
*     convert_src:    TRIG_TIMER | TRIG_EXT
*     stop_src:       TRIG_NONE | TRIG_COUNT
+ */
 
 #include <linux/module.h>
 #include <linux/interrupt.h>
@@ -218,7 +218,7 @@ struct das800_private {
 };
 
 static void das800_ind_write(struct comedi_device *dev,
-                            unsigned val, unsigned reg)
+                            unsigned int val, unsigned int reg)
 {
        /*
         * Select dev->iobase + 2 to be desired register
@@ -228,7 +228,7 @@ static void das800_ind_write(struct comedi_device *dev,
        outb(val, dev->iobase + 2);
 }
 
-static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg)
+static unsigned int das800_ind_read(struct comedi_device *dev, unsigned int reg)
 {
        /*
         * Select dev->iobase + 7 to be desired register
@@ -240,13 +240,13 @@ static unsigned das800_ind_read(struct comedi_device *dev, unsigned reg)
 
 static void das800_enable(struct comedi_device *dev)
 {
-       const struct das800_board *thisboard = dev->board_ptr;
+       const struct das800_board *board = dev->board_ptr;
        struct das800_private *devpriv = dev->private;
        unsigned long irq_flags;
 
        spin_lock_irqsave(&dev->spinlock, irq_flags);
        /*  enable fifo-half full interrupts for cio-das802/16 */
-       if (thisboard->resolution == 16)
+       if (board->resolution == 16)
                outb(CIO_ENHF, dev->iobase + DAS800_GAIN);
        /* enable hardware triggering */
        das800_ind_write(dev, CONV_HCEN, CONV_CONTROL);
@@ -303,7 +303,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
                                struct comedi_subdevice *s,
                                struct comedi_cmd *cmd)
 {
-       const struct das800_board *thisboard = dev->board_ptr;
+       const struct das800_board *board = dev->board_ptr;
        int err = 0;
 
        /* Step 1 : check if triggers are trivially valid */
@@ -335,7 +335,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 
        if (cmd->convert_src == TRIG_TIMER) {
                err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
-                                                   thisboard->ai_speed);
+                                                   board->ai_speed);
        }
 
        err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
@@ -375,7 +375,7 @@ static int das800_ai_do_cmdtest(struct comedi_device *dev,
 static int das800_ai_do_cmd(struct comedi_device *dev,
                            struct comedi_subdevice *s)
 {
-       const struct das800_board *thisboard = dev->board_ptr;
+       const struct das800_board *board = dev->board_ptr;
        struct comedi_async *async = s->async;
        struct comedi_cmd *cmd = &async->cmd;
        unsigned int gain = CR_RANGE(cmd->chanlist[0]);
@@ -393,7 +393,7 @@ static int das800_ai_do_cmd(struct comedi_device *dev,
        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 
        /* set gain */
-       if (thisboard->resolution == 12 && gain > 0)
+       if (board->resolution == 12 && gain > 0)
                gain += 0x7;
        gain &= 0xf;
        outb(gain, dev->iobase + DAS800_GAIN);
@@ -604,54 +604,62 @@ static int das800_do_insn_bits(struct comedi_device *dev,
        return insn->n;
 }
 
-static int das800_probe(struct comedi_device *dev)
+static const struct das800_board *das800_probe(struct comedi_device *dev)
 {
-       const struct das800_board *thisboard = dev->board_ptr;
-       int board = thisboard ? thisboard - das800_boards : -EINVAL;
+       const struct das800_board *board = dev->board_ptr;
+       int index = board ? board - das800_boards : -EINVAL;
        int id_bits;
        unsigned long irq_flags;
 
+       /*
+        * The dev->board_ptr will be set by comedi_device_attach() if the
+        * board name provided by the user matches a board->name in this
+        * driver. If so, this function sanity checks the id_bits to verify
+        * that the board is correct.
+        *
+        * If the dev->board_ptr is not set, the user is trying to attach
+        * an unspecified board to this driver. In this case the id_bits
+        * are used to 'probe' for the correct dev->board_ptr.
+        */
        spin_lock_irqsave(&dev->spinlock, irq_flags);
        id_bits = das800_ind_read(dev, ID) & 0x3;
        spin_unlock_irqrestore(&dev->spinlock, irq_flags);
 
        switch (id_bits) {
        case 0x0:
-               if (board == BOARD_DAS800 || board == BOARD_CIODAS800)
-                       break;
-               dev_dbg(dev->class_dev, "Board model (probed): DAS-800\n");
-               board = BOARD_DAS800;
+               if (index == BOARD_DAS800 || index == BOARD_CIODAS800)
+                       return board;
+               index = BOARD_DAS800;
                break;
        case 0x2:
-               if (board == BOARD_DAS801 || board == BOARD_CIODAS801)
-                       break;
-               dev_dbg(dev->class_dev, "Board model (probed): DAS-801\n");
-               board = BOARD_DAS801;
+               if (index == BOARD_DAS801 || index == BOARD_CIODAS801)
+                       return board;
+               index = BOARD_DAS801;
                break;
        case 0x3:
-               if (board == BOARD_DAS802 || board == BOARD_CIODAS802 ||
-                   board == BOARD_CIODAS80216)
-                       break;
-               dev_dbg(dev->class_dev, "Board model (probed): DAS-802\n");
-               board = BOARD_DAS802;
+               if (index == BOARD_DAS802 || index == BOARD_CIODAS802 ||
+                   index == BOARD_CIODAS80216)
+                       return board;
+               index = BOARD_DAS802;
                break;
        default:
                dev_dbg(dev->class_dev, "Board model: 0x%x (unknown)\n",
                        id_bits);
-               board = -EINVAL;
-               break;
+               return NULL;
        }
-       return board;
+       dev_dbg(dev->class_dev, "Board model (probed): %s series\n",
+               das800_boards[index].name);
+
+       return &das800_boards[index];
 }
 
 static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
 {
-       const struct das800_board *thisboard;
+       const struct das800_board *board;
        struct das800_private *devpriv;
        struct comedi_subdevice *s;
        unsigned int irq = it->options[1];
        unsigned long irq_flags;
-       int board;
        int ret;
 
        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
@@ -663,13 +671,10 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
                return ret;
 
        board = das800_probe(dev);
-       if (board < 0) {
-               dev_dbg(dev->class_dev, "unable to determine board type\n");
+       if (!board)
                return -ENODEV;
-       }
-       dev->board_ptr = das800_boards + board;
-       thisboard = dev->board_ptr;
-       dev->board_name = thisboard->name;
+       dev->board_ptr = board;
+       dev->board_name = board->name;
 
        if (irq > 1 && irq <= 7) {
                ret = request_irq(irq, das800_interrupt, 0, dev->board_name,
@@ -693,8 +698,8 @@ static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
        s->type         = COMEDI_SUBD_AI;
        s->subdev_flags = SDF_READABLE | SDF_GROUND;
        s->n_chan       = 8;
-       s->maxdata      = (1 << thisboard->resolution) - 1;
-       s->range_table  = thisboard->ai_range;
+       s->maxdata      = (1 << board->resolution) - 1;
+       s->range_table  = board->ai_range;
        s->insn_read    = das800_ai_insn_read;
        if (dev->irq) {
                s->subdev_flags |= SDF_CMD_READ;