rti802.c revision 71b5f4f11971dea972832ad63a994c7e5b45db6b
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, comedi_devconfig * it); 51static int rti802_detach(struct comedi_device * dev); 52static comedi_driver driver_rti802 = { 53 driver_name:"rti802", 54 module:THIS_MODULE, 55 attach:rti802_attach, 56 detach:rti802_detach, 57}; 58 59COMEDI_INITCLEANUP(driver_rti802); 60 61typedef struct { 62 enum { 63 dac_2comp, dac_straight 64 } dac_coding[8]; 65 const comedi_lrange *range_type_list[8]; 66 unsigned int ao_readback[8]; 67} rti802_private; 68 69#define devpriv ((rti802_private *)dev->private) 70 71static int rti802_ao_insn_read(struct comedi_device * dev, comedi_subdevice * s, 72 comedi_insn * insn, unsigned int * data) 73{ 74 int i; 75 76 for (i = 0; i < insn->n; i++) 77 data[i] = devpriv->ao_readback[CR_CHAN(insn->chanspec)]; 78 79 return i; 80} 81 82static int rti802_ao_insn_write(struct comedi_device * dev, comedi_subdevice * s, 83 comedi_insn * insn, unsigned int * data) 84{ 85 int i, d; 86 int chan = CR_CHAN(insn->chanspec); 87 88 for (i = 0; i < insn->n; i++) { 89 d = devpriv->ao_readback[chan] = data[i]; 90 if (devpriv->dac_coding[chan] == dac_2comp) 91 d ^= 0x800; 92 outb(chan, dev->iobase + RTI802_SELECT); 93 outb(d & 0xff, dev->iobase + RTI802_DATALOW); 94 outb(d >> 8, dev->iobase + RTI802_DATAHIGH); 95 } 96 return i; 97} 98 99static int rti802_attach(struct comedi_device * dev, comedi_devconfig * it) 100{ 101 comedi_subdevice *s; 102 int i; 103 unsigned long iobase; 104 105 iobase = it->options[0]; 106 printk("comedi%d: rti802: 0x%04lx ", dev->minor, iobase); 107 if (!request_region(iobase, RTI802_SIZE, "rti802")) { 108 printk("I/O port conflict\n"); 109 return -EIO; 110 } 111 dev->iobase = iobase; 112 113 dev->board_name = "rti802"; 114 115 if (alloc_subdevices(dev, 1) < 0 116 || alloc_private(dev, sizeof(rti802_private))) { 117 return -ENOMEM; 118 } 119 120 s = dev->subdevices; 121 /* ao subdevice */ 122 s->type = COMEDI_SUBD_AO; 123 s->subdev_flags = SDF_WRITABLE; 124 s->maxdata = 0xfff; 125 s->n_chan = 8; 126 s->insn_read = rti802_ao_insn_read; 127 s->insn_write = rti802_ao_insn_write; 128 s->range_table_list = devpriv->range_type_list; 129 130 for (i = 0; i < 8; i++) { 131 devpriv->dac_coding[i] = (it->options[3 + 2 * i]) 132 ? (dac_straight) 133 : (dac_2comp); 134 devpriv->range_type_list[i] = (it->options[2 + 2 * i]) 135 ? &range_unipolar10 : &range_bipolar10; 136 } 137 138 printk("\n"); 139 140 return 0; 141} 142 143static int rti802_detach(struct comedi_device * dev) 144{ 145 printk("comedi%d: rti802: remove\n", dev->minor); 146 147 if (dev->iobase) 148 release_region(dev->iobase, RTI802_SIZE); 149 150 return 0; 151} 152