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);
57 static int poc_recognize(const char *name);
59 struct boarddef_struct{
62 int (*setup)(comedi_device *);
66 int (*winsn)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *);
67 int (*rinsn)(comedi_device *,comedi_subdevice *,comedi_insn *,lsampl_t *);
69 static struct boarddef_struct boards[]={
77 winsn: dac02_ao_winsn,
81 #define n_boards ((sizeof(boards)/sizeof(boards[0]))
83 comedi_driver driver_poc=
89 recognize: poc_recognize,
92 // analog output ranges
93 static comedi_lrange range_dac02 = {
103 static int poc_recognize(const char *name)
107 for(i=0;i<n_boards;i++){
108 if(!strcmp(boards[i].name,name))
115 static int dac02_attach(comedi_device *dev, comedi_devconfig *it)
120 printk("comedi%d: poc: using %s iobase 0x%x\n", dev->minor,
121 boards[dev->board].name, iobase);
123 dev->board_name = boards[dev->board].name;
127 printk("io base address required\n");
131 iobase = it->options[0];
132 iosize = boards[dev->board].name;
133 /* check if io addresses are available */
134 if(check_region(iobase, iosize) < 0)
136 printk("I/O port conflict: failed to allocate ports 0x%x to 0x%x\n",
137 iobase, iobase + iosize - 1);
140 request_region(iobase, iosize, "dac02");
141 dev->iobase = iobase;
142 dev->iosize = iosize;
144 dev->n_subdevices = 1;
145 if(alloc_subdevices(dev) < 0)
147 if(alloc_private(dev,sizeof(lsampl_t)*boards[dev->board].n_chan) < 0)
150 /* analog output subdevice */
151 s=dev->subdevices + 0;
152 s->type = boards[dev->board].type;
153 s->n_chan = boards[dev->board].n_chan;
154 s->maxdata = (1<<boards[dev->board].n_bits)-1;
155 s->range_table = &range_dac02; // XXX
156 s->insn_write = boards[dev->board].winsn;
157 s->insn_write = boards[dev->board].rinsn;
158 if(s->type==COMEDI_SUBD_AO || s->type==COMEDI_SUBD_DO){
159 s->subdev_flags = SDF_WRITEABLE;
165 static int poc_detach(comedi_device *dev)
167 /* only free stuff if it has been allocated by _attach */
169 release_region(dev->iobase, dev->iosize);
171 printk("comedi%d: dac02: remove\n", dev->minor);
176 static int readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
182 chan = CR_CHAN(insn->chanspec);
183 data[0]=((lsampl_t *)dev->private)[chan];
188 static int dac02_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
194 chan = CR_CHAN(insn->chanspec);
195 ((lsampl_t *)dev->private)[chan] = data[0];
198 // convert to complementary binary if range is bipolar
199 if((CR_RANGE(insn->chanspec) & 0x2) == 0)
202 temp = (output << 4) & 0xf0;
203 outb(temp, dev->iobase + DAC02_LSB(chan));
204 temp = (output >> 4) & 0xff;
205 outb(temp, dev->iobase + DAC02_MSB(chan));
210 COMEDI_INITCLEANUP(driver_poc);