/*
 * aio_iiro_16.c
 * Comedi driver for Access I/O Products 104-IIRO-16 board
 * Copyright (C) 2006 C&C Technologies, Inc.
 *
 * 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: aio_iiro_16
 * Description: Access I/O Products PC/104 Isolated Input/Relay Output Board
 * Author: Zachary Ware <zach.ware@cctechnol.com>
 * Devices: [Access I/O] 104-IIRO-16 (aio_iiro_16)
 * Status: experimental
 *
 * Configuration Options:
 *   [0] - I/O port base address
 *   [1] - IRQ (optional)
 *
 * The board supports interrupts on change of state of the digital inputs.
 * The sample data returned by the async command indicates which inputs
 * changed state and the current state of the inputs:
 *
 *	Bit 23 - IRQ Enable (1) / Disable (0)
 *	Bit 17 - Input 8-15 Changed State (1 = Changed, 0 = No Change)
 *	Bit 16 - Input 0-7 Changed State (1 = Changed, 0 = No Change)
 *	Bit 15 - Digital input 15
 *	...
 *	Bit 0  - Digital input 0
 */

#include <linux/module.h>
#include <linux/interrupt.h>

#include "../comedidev.h"

#define AIO_IIRO_16_RELAY_0_7		0x00
#define AIO_IIRO_16_INPUT_0_7		0x01
#define AIO_IIRO_16_IRQ			0x02
#define AIO_IIRO_16_RELAY_8_15		0x04
#define AIO_IIRO_16_INPUT_8_15		0x05
#define AIO_IIRO_16_STATUS		0x07
#define AIO_IIRO_16_STATUS_IRQE		BIT(7)
#define AIO_IIRO_16_STATUS_INPUT_8_15	BIT(1)
#define AIO_IIRO_16_STATUS_INPUT_0_7	BIT(0)

static unsigned int aio_iiro_16_read_inputs(struct comedi_device *dev)
{
	unsigned int val;

	val = inb(dev->iobase + AIO_IIRO_16_INPUT_0_7);
	val |= inb(dev->iobase + AIO_IIRO_16_INPUT_8_15) << 8;

	return val;
}

static irqreturn_t aio_iiro_16_cos(int irq, void *d)
{
	struct comedi_device *dev = d;
	struct comedi_subdevice *s = dev->read_subdev;
	unsigned int status;
	unsigned int val;

	status = inb(dev->iobase + AIO_IIRO_16_STATUS);
	if (!(status & AIO_IIRO_16_STATUS_IRQE))
		return IRQ_NONE;

	val = aio_iiro_16_read_inputs(dev);
	val |= (status << 16);

	comedi_buf_write_samples(s, &val, 1);
	comedi_handle_events(dev, s);

	return IRQ_HANDLED;
}

static void aio_iiro_enable_irq(struct comedi_device *dev, bool enable)
{
	if (enable)
		inb(dev->iobase + AIO_IIRO_16_IRQ);
	else
		outb(0, dev->iobase + AIO_IIRO_16_IRQ);
}

static int aio_iiro_16_cos_cancel(struct comedi_device *dev,
				  struct comedi_subdevice *s)
{
	aio_iiro_enable_irq(dev, false);

	return 0;
}

static int aio_iiro_16_cos_cmd(struct comedi_device *dev,
			       struct comedi_subdevice *s)
{
	aio_iiro_enable_irq(dev, true);

	return 0;
}

static int aio_iiro_16_cos_cmdtest(struct comedi_device *dev,
				   struct comedi_subdevice *s,
				   struct comedi_cmd *cmd)
{
	int err = 0;

	/* Step 1 : check if triggers are trivially valid */

	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW);
	err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
	err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
	err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_NONE);

	if (err)
		return 1;

	/* Step 2a : make sure trigger sources are unique */
	/* Step 2b : and mutually compatible */

	/* Step 3: check if arguments are trivially valid */

	err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
	err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
	err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
					   cmd->chanlist_len);
	err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);

	if (err)
		return 3;

	/* Step 4: fix up any arguments */

	/* Step 5: check channel list if it exists */

	return 0;
}

static int aio_iiro_16_do_insn_bits(struct comedi_device *dev,
				    struct comedi_subdevice *s,
				    struct comedi_insn *insn,
				    unsigned int *data)
{
	if (comedi_dio_update_state(s, data)) {
		outb(s->state & 0xff, dev->iobase + AIO_IIRO_16_RELAY_0_7);
		outb((s->state >> 8) & 0xff,
		     dev->iobase + AIO_IIRO_16_RELAY_8_15);
	}

	data[1] = s->state;

	return insn->n;
}

static int aio_iiro_16_di_insn_bits(struct comedi_device *dev,
				    struct comedi_subdevice *s,
				    struct comedi_insn *insn,
				    unsigned int *data)
{
	data[1] = aio_iiro_16_read_inputs(dev);

	return insn->n;
}

static int aio_iiro_16_attach(struct comedi_device *dev,
			      struct comedi_devconfig *it)
{
	struct comedi_subdevice *s;
	int ret;

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

	aio_iiro_enable_irq(dev, false);

	/*
	 * Digital input change of state interrupts are optionally supported
	 * using IRQ 2-7, 10-12, 14, or 15.
	 */
	if ((1 << it->options[1]) & 0xdcfc) {
		ret = request_irq(it->options[1], aio_iiro_16_cos, 0,
				  dev->board_name, dev);
		if (ret == 0)
			dev->irq = it->options[1];
	}

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

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

	/* get the initial state of the relays */
	s->state = inb(dev->iobase + AIO_IIRO_16_RELAY_0_7) |
		   (inb(dev->iobase + AIO_IIRO_16_RELAY_8_15) << 8);

	/* Digital Input subdevice */
	s = &dev->subdevices[1];
	s->type		= COMEDI_SUBD_DI;
	s->subdev_flags	= SDF_READABLE;
	s->n_chan	= 16;
	s->maxdata	= 1;
	s->range_table	= &range_digital;
	s->insn_bits	= aio_iiro_16_di_insn_bits;
	if (dev->irq) {
		dev->read_subdev = s;
		s->subdev_flags	|= SDF_CMD_READ | SDF_LSAMPL;
		s->len_chanlist	= 1;
		s->do_cmdtest	= aio_iiro_16_cos_cmdtest;
		s->do_cmd	= aio_iiro_16_cos_cmd;
		s->cancel	= aio_iiro_16_cos_cancel;
	}

	return 0;
}

static struct comedi_driver aio_iiro_16_driver = {
	.driver_name	= "aio_iiro_16",
	.module		= THIS_MODULE,
	.attach		= aio_iiro_16_attach,
	.detach		= comedi_legacy_detach,
};
module_comedi_driver(aio_iiro_16_driver);

MODULE_AUTHOR("Comedi http://www.comedi.org");
MODULE_DESCRIPTION("Comedi driver for Access I/O Products 104-IIRO-16 board");
MODULE_LICENSE("GPL");
