3 Mini-drivers for POC (Piece of Crap) boards
4 Copyright (C) 2000 Frank Mori Hess <fmhess@uiuc.edu>
5 Copyright (C) 2001 David A. Schleef <ds@schleef.org>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 * This driver is a kind of miscellaneous driver for very
26 dac02 - Keithley DAC-02 analog output board driver
28 The card's ranges are set by the wiring you use. The driver only
29 uses the range specified to decide whether or not to take the
30 complement of the data before sending it to the card (since the
31 bipolar outputs of the card are inverted.)
35 #include <linux/kernel.h>
36 #include <linux/module.h>
37 #include <linux/sched.h>
39 #include <linux/malloc.h>
40 #include <linux/errno.h>
41 #include <linux/ioport.h>
42 #include <linux/delay.h>
43 #include <linux/interrupt.h>
44 #include <linux/timex.h>
45 #include <linux/timer.h>
47 #include <linux/comedidev.h>
49 /* DAC-02 registers */
50 #define DAC02_LSB(a) (2 * a)
51 #define DAC02_MSB(a) (2 * a + 1)
53 static int poc_attach(comedi_device *dev,comedi_devconfig *it);
54 static int poc_detach(comedi_device *dev);
55 static int dac02_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
56 static int readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data);
58 struct boarddef_struct{
61 int (*setup)(comedi_device *);
65 int (*winsn)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *);
66 int (*rinsn)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *);
68 static struct boarddef_struct boards[]={
76 winsn: dac02_ao_winsn,
80 #define n_boards (sizeof(boards)/sizeof(boards[0]))
81 #define this_board ((struct boarddef_struct *)dev->board_ptr)
83 comedi_driver driver_poc=
91 offset: sizeof(boards[0]),
94 // analog output ranges
95 static comedi_lrange range_dac02 = {
105 static int poc_attach(comedi_device *dev, comedi_devconfig *it)
110 iobase = it->options[0];
111 printk("comedi%d: poc: using %s iobase 0x%x\n", dev->minor,
112 this_board->name, iobase);
114 dev->board_name = this_board->name;
118 printk("io base address required\n");
122 iosize = this_board->iosize;
123 /* check if io addresses are available */
124 if(check_region(iobase, iosize) < 0)
126 printk("I/O port conflict: failed to allocate ports 0x%x to 0x%x\n",
127 iobase, iobase + iosize - 1);
130 request_region(iobase, iosize, "dac02");
131 dev->iobase = iobase;
132 dev->iosize = iosize;
134 dev->n_subdevices = 1;
135 if(alloc_subdevices(dev) < 0)
137 if(alloc_private(dev,sizeof(lsampl_t)*this_board->n_chan) < 0)
140 /* analog output subdevice */
141 s=dev->subdevices + 0;
142 s->type = this_board->type;
143 s->n_chan = this_board->n_chan;
144 s->maxdata = (1<<this_board->n_bits)-1;
145 s->range_table = &range_dac02; // XXX
146 s->insn_write = this_board->winsn;
147 s->insn_write = this_board->rinsn;
148 if(s->type==COMEDI_SUBD_AO || s->type==COMEDI_SUBD_DO){
149 s->subdev_flags = SDF_WRITEABLE;
155 static int poc_detach(comedi_device *dev)
157 /* only free stuff if it has been allocated by _attach */
159 release_region(dev->iobase, dev->iosize);
161 printk("comedi%d: dac02: remove\n", dev->minor);
166 static int readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
170 chan = CR_CHAN(insn->chanspec);
171 data[0]=((lsampl_t *)dev->private)[chan];
176 static int dac02_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
182 chan = CR_CHAN(insn->chanspec);
183 ((lsampl_t *)dev->private)[chan] = data[0];
186 // convert to complementary binary if range is bipolar
187 if((CR_RANGE(insn->chanspec) & 0x2) == 0)
190 temp = (output << 4) & 0xf0;
191 outb(temp, dev->iobase + DAC02_LSB(chan));
192 temp = (output >> 4) & 0xff;
193 outb(temp, dev->iobase + DAC02_MSB(chan));
198 COMEDI_INITCLEANUP(driver_poc);