/*
   comedi/drivers/dt2815.c
   Hardware driver for Data Translation DT2815

   COMEDI - Linux Control and Measurement Device Interface
   Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se>

   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: dt2815
Description: Data Translation DT2815
Author: ds
Status: mostly complete, untested
Devices: [Data Translation] DT2815 (dt2815)

I'm not sure anyone has ever tested this board.  If you have information
contrary, please update.

Configuration options:
  [0] - I/O port base base address
  [1] - IRQ (unused)
  [2] - Voltage unipolar/bipolar configuration
	0 == unipolar 5V  (0V -- +5V)
	1 == bipolar 5V  (-5V -- +5V)
  [3] - Current offset configuration
	0 == disabled  (0mA -- +32mAV)
	1 == enabled  (+4mA -- +20mAV)
  [4] - Firmware program configuration
	0 == program 1 (see manual table 5-4)
	1 == program 2 (see manual table 5-4)
	2 == program 3 (see manual table 5-4)
	3 == program 4 (see manual table 5-4)
  [5] - Analog output 0 range configuration
	0 == voltage
	1 == current
  [6] - Analog output 1 range configuration (same options)
  [7] - Analog output 2 range configuration (same options)
  [8] - Analog output 3 range configuration (same options)
  [9] - Analog output 4 range configuration (same options)
  [10] - Analog output 5 range configuration (same options)
  [11] - Analog output 6 range configuration (same options)
  [12] - Analog output 7 range configuration (same options)
*/

#include <linux/module.h>
#include "../comedidev.h"

#include <linux/delay.h>

#define DT2815_SIZE 2

#define DT2815_DATA 0
#define DT2815_STATUS 1

struct dt2815_private {

	const struct comedi_lrange *range_type_list[8];
	unsigned int ao_readback[8];
};

static int dt2815_wait_for_status(struct comedi_device *dev, int status)
{
	int i;

	for (i = 0; i < 100; i++) {
		if (inb(dev->iobase + DT2815_STATUS) == status)
			break;
	}
	return status;
}

static int dt2815_ao_insn_read(struct comedi_device *dev,
			       struct comedi_subdevice *s,
			       struct comedi_insn *insn, unsigned int *data)
{
	struct dt2815_private *devpriv = dev->private;
	int i;
	int chan = CR_CHAN(insn->chanspec);

	for (i = 0; i < insn->n; i++)
		data[i] = devpriv->ao_readback[chan];

	return i;
}

static int dt2815_ao_insn(struct comedi_device *dev, struct comedi_subdevice *s,
			  struct comedi_insn *insn, unsigned int *data)
{
	struct dt2815_private *devpriv = dev->private;
	int i;
	int chan = CR_CHAN(insn->chanspec);
	unsigned int status;
	unsigned int lo, hi;

	for (i = 0; i < insn->n; i++) {
		lo = ((data[i] & 0x0f) << 4) | (chan << 1) | 0x01;
		hi = (data[i] & 0xff0) >> 4;

		status = dt2815_wait_for_status(dev, 0x00);
		if (status != 0) {
			dev_dbg(dev->class_dev,
				"failed to write low byte on %d reason %x\n",
				chan, status);
			return -EBUSY;
		}

		outb(lo, dev->iobase + DT2815_DATA);

		status = dt2815_wait_for_status(dev, 0x10);
		if (status != 0x10) {
			dev_dbg(dev->class_dev,
				"failed to write high byte on %d reason %x\n",
				chan, status);
			return -EBUSY;
		}
		devpriv->ao_readback[chan] = data[i];
	}
	return i;
}

/*
  options[0]   Board base address
  options[1]   IRQ (not applicable)
  options[2]   Voltage unipolar/bipolar configuration
		0 == unipolar 5V  (0V -- +5V)
		1 == bipolar 5V  (-5V -- +5V)
  options[3]   Current offset configuration
		0 == disabled  (0mA -- +32mAV)
		1 == enabled  (+4mA -- +20mAV)
  options[4]   Firmware program configuration
		0 == program 1 (see manual table 5-4)
		1 == program 2 (see manual table 5-4)
		2 == program 3 (see manual table 5-4)
		3 == program 4 (see manual table 5-4)
  options[5]   Analog output 0 range configuration
		0 == voltage
		1 == current
  options[6]   Analog output 1 range configuration
  ...
  options[12]   Analog output 7 range configuration
		0 == voltage
		1 == current
 */

static int dt2815_attach(struct comedi_device *dev, struct comedi_devconfig *it)
{
	struct dt2815_private *devpriv;
	struct comedi_subdevice *s;
	int i;
	const struct comedi_lrange *current_range_type, *voltage_range_type;
	int ret;

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

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

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

	s = &dev->subdevices[0];
	/* ao subdevice */
	s->type = COMEDI_SUBD_AO;
	s->subdev_flags = SDF_WRITABLE;
	s->maxdata = 0xfff;
	s->n_chan = 8;
	s->insn_write = dt2815_ao_insn;
	s->insn_read = dt2815_ao_insn_read;
	s->range_table_list = devpriv->range_type_list;

	current_range_type = (it->options[3])
	    ? &range_4_20mA : &range_0_32mA;
	voltage_range_type = (it->options[2])
	    ? &range_bipolar5 : &range_unipolar5;
	for (i = 0; i < 8; i++) {
		devpriv->range_type_list[i] = (it->options[5 + i])
		    ? current_range_type : voltage_range_type;
	}

	/* Init the 2815 */
	outb(0x00, dev->iobase + DT2815_STATUS);
	for (i = 0; i < 100; i++) {
		/* This is incredibly slow (approx 20 ms) */
		unsigned int status;

		udelay(1000);
		status = inb(dev->iobase + DT2815_STATUS);
		if (status == 4) {
			unsigned int program;
			program = (it->options[4] & 0x3) << 3 | 0x7;
			outb(program, dev->iobase + DT2815_DATA);
			dev_dbg(dev->class_dev, "program: 0x%x (@t=%d)\n",
				program, i);
			break;
		} else if (status != 0x00) {
			dev_dbg(dev->class_dev,
				"unexpected status 0x%x (@t=%d)\n",
				status, i);
			if (status & 0x60)
				outb(0x00, dev->iobase + DT2815_STATUS);
		}
	}

	return 0;
}

static struct comedi_driver dt2815_driver = {
	.driver_name	= "dt2815",
	.module		= THIS_MODULE,
	.attach		= dt2815_attach,
	.detach		= comedi_legacy_detach,
};
module_comedi_driver(dt2815_driver);

MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi low-level driver");
MODULE_LICENSE("GPL");
