rti802.c revision 7114a28011f9d5f3d981731ad341177c21f9d948
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 60static int __init driver_rti802_init_module(void) 61{ 62 return comedi_driver_register(&driver_rti802); 63} 64 65static void __exit driver_rti802_cleanup_module(void) 66{ 67 comedi_driver_unregister(&driver_rti802); 68} 69 70module_init(driver_rti802_init_module); 71module_exit(driver_rti802_cleanup_module); 72 73struct rti802_private { 74 enum { 75 dac_2comp, dac_straight 76 } dac_coding[8]; 77 const struct comedi_lrange *range_type_list[8]; 78 unsigned int ao_readback[8]; 79}; 80 81#define devpriv ((struct rti802_private *)dev->private) 82 83static int rti802_ao_insn_read(struct comedi_device *dev, 84 struct comedi_subdevice *s, 85 struct comedi_insn *insn, unsigned int *data) 86{ 87 int i; 88 89 for (i = 0; i < insn->n; i++) 90 data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; 91 92 return i; 93} 94 95static int rti802_ao_insn_write(struct comedi_device *dev, 96 struct comedi_subdevice *s, 97 struct comedi_insn *insn, unsigned int *data) 98{ 99 int i, d; 100 int chan = CR_CHAN(insn->chanspec); 101 102 for (i = 0; i < insn->n; i++) { 103 d = devpriv->ao_readback[chan] = data[i]; 104 if (devpriv->dac_coding[chan] == dac_2comp) 105 d ^= 0x800; 106 outb(chan, dev->iobase + RTI802_SELECT); 107 outb(d & 0xff, dev->iobase + RTI802_DATALOW); 108 outb(d >> 8, dev->iobase + RTI802_DATAHIGH); 109 } 110 return i; 111} 112 113static int rti802_attach(struct comedi_device *dev, struct comedi_devconfig *it) 114{ 115 struct comedi_subdevice *s; 116 int i; 117 unsigned long iobase; 118 119 iobase = it->options[0]; 120 printk(KERN_INFO "comedi%d: rti802: 0x%04lx ", dev->minor, iobase); 121 if (!request_region(iobase, RTI802_SIZE, "rti802")) { 122 printk(KERN_WARNING "I/O port conflict\n"); 123 return -EIO; 124 } 125 dev->iobase = iobase; 126 127 dev->board_name = "rti802"; 128 129 if (alloc_subdevices(dev, 1) < 0 130 || alloc_private(dev, sizeof(struct rti802_private))) { 131 return -ENOMEM; 132 } 133 134 s = dev->subdevices; 135 /* ao subdevice */ 136 s->type = COMEDI_SUBD_AO; 137 s->subdev_flags = SDF_WRITABLE; 138 s->maxdata = 0xfff; 139 s->n_chan = 8; 140 s->insn_read = rti802_ao_insn_read; 141 s->insn_write = rti802_ao_insn_write; 142 s->range_table_list = devpriv->range_type_list; 143 144 for (i = 0; i < 8; i++) { 145 devpriv->dac_coding[i] = (it->options[3 + 2 * i]) 146 ? (dac_straight) 147 : (dac_2comp); 148 devpriv->range_type_list[i] = (it->options[2 + 2 * i]) 149 ? &range_unipolar10 : &range_bipolar10; 150 } 151 152 return 0; 153} 154 155static int rti802_detach(struct comedi_device *dev) 156{ 157 printk(KERN_INFO "comedi%d: rti802: remove\n", dev->minor); 158 159 if (dev->iobase) 160 release_region(dev->iobase, RTI802_SIZE); 161 162 return 0; 163} 164 165MODULE_AUTHOR("Comedi http://www.comedi.org"); 166MODULE_DESCRIPTION("Comedi low-level driver"); 167MODULE_LICENSE("GPL"); 168