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(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(char *name)
107 for(i=0;i<n_boards;i++){
108 if(!strcmp(boards[i].name,name))
115 static int poc_attach(comedi_device *dev, comedi_devconfig *it)
120 iobase = it->options[0];
121 printk("comedi%d: poc: using %s iobase 0x%x\n", dev->minor,
122 boards[dev->board].name, iobase);
124 dev->board_name = boards[dev->board].name;
128 printk("io base address required\n");
132 iosize = boards[dev->board].iosize;
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)
180 chan = CR_CHAN(insn->chanspec);
181 data[0]=((lsampl_t *)dev->private)[chan];
186 static int dac02_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
192 chan = CR_CHAN(insn->chanspec);
193 ((lsampl_t *)dev->private)[chan] = data[0];
196 // convert to complementary binary if range is bipolar
197 if((CR_RANGE(insn->chanspec) & 0x2) == 0)
200 temp = (output << 4) & 0xf0;
201 outb(temp, dev->iobase + DAC02_LSB(chan));
202 temp = (output >> 4) & 0xff;
203 outb(temp, dev->iobase + DAC02_MSB(chan));
208 COMEDI_INITCLEANUP(driver_poc);