linux/drivers/comedi/drivers/das800.c

// SPDX-License-Identifier: GPL-2.0+
/*
 * comedi/drivers/das800.c
 * Driver for Keitley das800 series boards and compatibles
 * Copyright (C) 2000 Frank Mori Hess <[email protected]>
 *
 * COMEDI - Linux Control and Measurement Device Interface
 * Copyright (C) 2000 David A. Schleef <[email protected]>
 */
/*
 * Driver: das800
 * Description: Keithley Metrabyte DAS800 (& compatibles)
 * Author: Frank Mori Hess <[email protected]>
 * 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>
#include <linux/delay.h>
#include <linux/comedi/comedidev.h>
#include <linux/comedi/comedi_8254.h>

#define N_CHAN_AI

/* Registers for the das800 */

#define DAS800_LSB
#define FIFO_EMPTY
#define FIFO_OVF
#define DAS800_MSB
#define DAS800_CONTROL1
#define CONTROL1_INTE
#define DAS800_CONV_CONTROL
#define ITE
#define CASC
#define DTEN
#define IEOC
#define EACS
#define CONV_HCEN
#define DAS800_SCAN_LIMITS
#define DAS800_STATUS
#define IRQ
#define BUSY
#define DAS800_GAIN
#define CIO_FFOV
#define CIO_ENHF
#define CONTROL1
#define CONV_CONTROL
#define SCAN_LIMITS
#define ID
#define DAS800_8254
#define DAS800_STATUS2
#define STATUS2_HCEN
#define STATUS2_INTE
#define DAS800_ID

#define DAS802_16_HALF_FIFO_SZ

struct das800_board {};

static const struct comedi_lrange range_das801_ai =;

static const struct comedi_lrange range_cio_das801_ai =;

static const struct comedi_lrange range_das802_ai =;

static const struct comedi_lrange range_das80216_ai =;

enum das800_boardinfo {};

static const struct das800_board das800_boards[] =;

struct das800_private {};

static void das800_ind_write(struct comedi_device *dev,
			     unsigned int val, unsigned int reg)
{}

static unsigned int das800_ind_read(struct comedi_device *dev, unsigned int reg)
{}

static void das800_enable(struct comedi_device *dev)
{}

static void das800_disable(struct comedi_device *dev)
{}

static int das800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
{}

static int das800_ai_check_chanlist(struct comedi_device *dev,
				    struct comedi_subdevice *s,
				    struct comedi_cmd *cmd)
{}

static int das800_ai_do_cmdtest(struct comedi_device *dev,
				struct comedi_subdevice *s,
				struct comedi_cmd *cmd)
{}

static int das800_ai_do_cmd(struct comedi_device *dev,
			    struct comedi_subdevice *s)
{}

static unsigned int das800_ai_get_sample(struct comedi_device *dev)
{}

static irqreturn_t das800_interrupt(int irq, void *d)
{}

static int das800_ai_eoc(struct comedi_device *dev,
			 struct comedi_subdevice *s,
			 struct comedi_insn *insn,
			 unsigned long context)
{}

static int das800_ai_insn_read(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{}

static int das800_di_insn_bits(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{}

static int das800_do_insn_bits(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn,
			       unsigned int *data)
{}

static const struct das800_board *das800_probe(struct comedi_device *dev)
{}

static int das800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
	const struct das800_board *board;
	struct das800_private *devpriv;
	struct comedi_subdevice *s;
	unsigned int irq = it->options[1];
	unsigned long irq_flags;
	int ret;

	devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
	if (!devpriv)
		return -ENOMEM;

	ret = comedi_request_region(dev, it->options[0], 0x8);
	if (ret)
		return ret;

	board = das800_probe(dev);
	if (!board)
		return -ENODEV;
	dev->board_ptr = board;
	dev->board_name = board->name;

	if (irq > 1 && irq <= 7) {
		ret = request_irq(irq, das800_interrupt, 0, "das800",
				  dev);
		if (ret == 0)
			dev->irq = irq;
	}

	dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS800_8254,
					  I8254_OSC_BASE_1MHZ, I8254_IO8, 0);
	if (IS_ERR(dev->pacer))
		return PTR_ERR(dev->pacer);

	ret = comedi_alloc_subdevices(dev, 3);
	if (ret)
		return ret;

	/* Analog Input subdevice */
	s = &dev->subdevices[0];
	dev->read_subdev = s;
	s->type		= COMEDI_SUBD_AI;
	s->subdev_flags	= SDF_READABLE | SDF_GROUND;
	s->n_chan	= 8;
	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;
		s->len_chanlist	= 8;
		s->do_cmdtest	= das800_ai_do_cmdtest;
		s->do_cmd	= das800_ai_do_cmd;
		s->cancel	= das800_cancel;
	}

	/* Digital Input subdevice */
	s = &dev->subdevices[1];
	s->type		= COMEDI_SUBD_DI;
	s->subdev_flags	= SDF_READABLE;
	s->n_chan	= 3;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= das800_di_insn_bits;

	/* Digital Output subdevice */
	s = &dev->subdevices[2];
	s->type		= COMEDI_SUBD_DO;
	s->subdev_flags	= SDF_WRITABLE;
	s->n_chan	= 4;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= das800_do_insn_bits;

	das800_disable(dev);

	/* initialize digital out channels */
	spin_lock_irqsave(&dev->spinlock, irq_flags);
	das800_ind_write(dev, CONTROL1_INTE | devpriv->do_bits, CONTROL1);
	spin_unlock_irqrestore(&dev->spinlock, irq_flags);

	return 0;
};

static struct comedi_driver driver_das800 =;
module_comedi_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();