From a58ebc2a65290e0dd240240a75f2ccf05b6ab4bb Mon Sep 17 00:00:00 2001 From: Anders Blomdell Date: Tue, 17 Feb 2009 16:23:41 -0800 Subject: Staging: comedi: add rti802 driver From: Anders Blomdell Driver for Analog Devices RTI-802 board From: Anders Blomdell Cc: David Schleef Cc: Frank Mori Hess Cc: Ian Abbott Signed-off-by: Greg Kroah-Hartman --- drivers/staging/comedi/drivers/rti802.c | 151 ++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 drivers/staging/comedi/drivers/rti802.c --- /dev/null +++ b/drivers/staging/comedi/drivers/rti802.c @@ -0,0 +1,151 @@ +/* + comedi/drivers/rti802.c + Hardware driver for Analog Devices RTI-802 board + + COMEDI - Linux Control and Measurement Device Interface + Copyright (C) 1999 Anders Blomdell + + 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. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + + */ +/* +Driver: rti802 +Description: Analog Devices RTI-802 +Author: Anders Blomdell +Devices: [Analog Devices] RTI-802 (rti802) +Status: works + +Configuration Options: + [0] - i/o base + [1] - unused + [2] - dac#0 0=two's comp, 1=straight + [3] - dac#0 0=bipolar, 1=unipolar + [4] - dac#1 ... + ... + [17] - dac#7 ... +*/ + +#include "../comedidev.h" + +#include + +#define RTI802_SIZE 4 + +#define RTI802_SELECT 0 +#define RTI802_DATALOW 1 +#define RTI802_DATAHIGH 2 + +static int rti802_attach(comedi_device * dev, comedi_devconfig * it); +static int rti802_detach(comedi_device * dev); +static comedi_driver driver_rti802 = { + driver_name:"rti802", + module:THIS_MODULE, + attach:rti802_attach, + detach:rti802_detach, +}; + +COMEDI_INITCLEANUP(driver_rti802); + +typedef struct { + enum { + dac_2comp, dac_straight + } dac_coding[8]; + const comedi_lrange *range_type_list[8]; + lsampl_t ao_readback[8]; +} rti802_private; + +#define devpriv ((rti802_private *)dev->private) + +static int rti802_ao_insn_read(comedi_device * dev, comedi_subdevice * s, + comedi_insn * insn, lsampl_t * data) +{ + int i; + + for (i = 0; i < insn->n; i++) + data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; + + return i; +} + +static int rti802_ao_insn_write(comedi_device * dev, comedi_subdevice * s, + comedi_insn * insn, lsampl_t * data) +{ + int i, d; + int chan = CR_CHAN(insn->chanspec); + + for (i = 0; i < insn->n; i++) { + d = devpriv->ao_readback[chan] = data[i]; + if (devpriv->dac_coding[chan] == dac_2comp) + d ^= 0x800; + outb(chan, dev->iobase + RTI802_SELECT); + outb(d & 0xff, dev->iobase + RTI802_DATALOW); + outb(d >> 8, dev->iobase + RTI802_DATAHIGH); + } + return i; +} + +static int rti802_attach(comedi_device * dev, comedi_devconfig * it) +{ + comedi_subdevice *s; + int i; + unsigned long iobase; + + iobase = it->options[0]; + printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase); + if (!request_region(iobase, RTI802_SIZE, "rti802")) { + printk("I/O port conflict\n"); + return -EIO; + } + dev->iobase = iobase; + + dev->board_name = "rti802"; + + if (alloc_subdevices(dev, 1) < 0 + || alloc_private(dev, sizeof(rti802_private))) { + return -ENOMEM; + } + + s = dev->subdevices; + /* ao subdevice */ + s->type = COMEDI_SUBD_AO; + s->subdev_flags = SDF_WRITABLE; + s->maxdata = 0xfff; + s->n_chan = 8; + s->insn_read = rti802_ao_insn_read; + s->insn_write = rti802_ao_insn_write; + s->range_table_list = devpriv->range_type_list; + + for (i = 0; i < 8; i++) { + devpriv->dac_coding[i] = (it->options[3 + 2 * i]) + ? (dac_straight) + : (dac_2comp); + devpriv->range_type_list[i] = (it->options[2 + 2 * i]) + ? &range_unipolar10 : &range_bipolar10; + } + + printk("\n"); + + return 0; +} + +static int rti802_detach(comedi_device * dev) +{ + printk("comedi%d: rti802: remove\n", dev->minor); + + if (dev->iobase) + release_region(dev->iobase, RTI802_SIZE); + + return 0; +}