rti802.c revision 0a85b6f0ab0d2edb0d41b32697111ce0e4f43496
1/* 2 comedi/drivers/rti802.c 3 Hardware driver for Analog Devices RTI-802 board 4 5 COMEDI - Linux Control and Measurement Device Interface 6 Copyright (C) 1999 Anders Blomdell <anders.blomdell@control.lth.se> 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22 */ 23/* 24Driver: rti802 25Description: Analog Devices RTI-802 26Author: Anders Blomdell <anders.blomdell@control.lth.se> 27Devices: [Analog Devices] RTI-802 (rti802) 28Status: works 29 30Configuration Options: 31 [0] - i/o base 32 [1] - unused 33 [2] - dac#0 0=two's comp, 1=straight 34 [3] - dac#0 0=bipolar, 1=unipolar 35 [4] - dac#1 ... 36 ... 37 [17] - dac#7 ... 38*/ 39 40#include "../comedidev.h" 41 42#include <linux/ioport.h> 43 44#define RTI802_SIZE 4 45 46#define RTI802_SELECT 0 47#define RTI802_DATALOW 1 48#define RTI802_DATAHIGH 2 49 50static int rti802_attach(struct comedi_device *dev, 51 struct comedi_devconfig *it); 52static int rti802_detach(struct comedi_device *dev); 53static struct comedi_driver driver_rti802 = { 54 .driver_name = "rti802", 55 .module = THIS_MODULE, 56 .attach = rti802_attach, 57 .detach = rti802_detach, 58}; 59 60COMEDI_INITCLEANUP(driver_rti802); 61 62struct rti802_private { 63 enum { 64 dac_2comp, dac_straight 65 } dac_coding[8]; 66 const struct comedi_lrange *range_type_list[8]; 67 unsigned int ao_readback[8]; 68}; 69 70#define devpriv ((struct rti802_private *)dev->private) 71 72static int rti802_ao_insn_read(struct comedi_device *dev, 73 struct comedi_subdevice *s, 74 struct comedi_insn *insn, unsigned int *data) 75{ 76 int i; 77 78 for (i = 0; i < insn->n; i++) 79 data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; 80 81 return i; 82} 83 84static int rti802_ao_insn_write(struct comedi_device *dev, 85 struct comedi_subdevice *s, 86 struct comedi_insn *insn, unsigned int *data) 87{ 88 int i, d; 89 int chan = CR_CHAN(insn->chanspec); 90 91 for (i = 0; i < insn->n; i++) { 92 d = devpriv->ao_readback[chan] = data[i]; 93 if (devpriv->dac_coding[chan] == dac_2comp) 94 d ^= 0x800; 95 outb(chan, dev->iobase + RTI802_SELECT); 96 outb(d & 0xff, dev->iobase + RTI802_DATALOW); 97 outb(d >> 8, dev->iobase + RTI802_DATAHIGH); 98 } 99 return i; 100} 101 102static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) 103{ 104 struct comedi_subdevice *s; 105 int i; 106 unsigned long iobase; 107 108 iobase = it->options[0]; 109 printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase); 110 if (!request_region(iobase, RTI802_SIZE, "rti802")) { 111 printk("I/O port conflict\n"); 112 return -EIO; 113 } 114 dev->iobase = iobase; 115 116 dev->board_name = "rti802"; 117 118 if (alloc_subdevices(dev, 1) < 0 119 || alloc_private(dev, sizeof(struct rti802_private))) { 120 return -ENOMEM; 121 } 122 123 s = dev->subdevices; 124 /* ao subdevice */ 125 s->type = COMEDI_SUBD_AO; 126 s->subdev_flags = SDF_WRITABLE; 127 s->maxdata = 0xfff; 128 s->n_chan = 8; 129 s->insn_read = rti802_ao_insn_read; 130 s->insn_write = rti802_ao_insn_write; 131 s->range_table_list = devpriv->range_type_list; 132 133 for (i = 0; i < 8; i++) { 134 devpriv->dac_coding[i] = (it->options[3 + 2 * i]) 135 ? (dac_straight) 136 : (dac_2comp); 137 devpriv->range_type_list[i] = (it->options[2 + 2 * i]) 138 ? &range_unipolar10 : &range_bipolar10; 139 } 140 141 printk("\n"); 142 143 return 0; 144} 145 146static int rti802_detach(struct comedi_device *dev) 147{ 148 printk("comedi%d: rti802: remove\n", dev->minor); 149 150 if (dev->iobase) 151 release_region(dev->iobase, RTI802_SIZE); 152 153 return 0; 154} 155