/*
- 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>
};
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
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
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);
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 */
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);
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]);
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);
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));
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,
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;