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;
133 dev->n_subdevices = 1;
134 if(alloc_subdevices(dev) < 0)
136 if(alloc_private(dev,sizeof(lsampl_t)*this_board->n_chan) < 0)
139 /* analog output subdevice */
140 s=dev->subdevices + 0;
141 s->type = this_board->type;
142 s->n_chan = this_board->n_chan;
143 s->maxdata = (1<<this_board->n_bits)-1;
144 s->range_table = &range_dac02; // XXX
145 s->insn_write = this_board->winsn;
146 s->insn_write = this_board->rinsn;
147 if(s->type==COMEDI_SUBD_AO || s->type==COMEDI_SUBD_DO){
148 s->subdev_flags = SDF_WRITEABLE;
154 static int poc_detach(comedi_device *dev)
156 /* only free stuff if it has been allocated by _attach */
158 release_region(dev->iobase, this_board->iosize);
160 printk("comedi%d: dac02: remove\n", dev->minor);
165 static int readback_insn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
169 chan = CR_CHAN(insn->chanspec);
170 data[0]=((lsampl_t *)dev->private)[chan];
175 static int dac02_ao_winsn(comedi_device *dev,comedi_subdevice *s,comedi_insn *insn,lsampl_t *data)
181 chan = CR_CHAN(insn->chanspec);
182 ((lsampl_t *)dev->private)[chan] = data[0];
185 // convert to complementary binary if range is bipolar
186 if((CR_RANGE(insn->chanspec) & 0x2) == 0)
189 temp = (output << 4) & 0xf0;
190 outb(temp, dev->iobase + DAC02_LSB(chan));
191 temp = (output >> 4) & 0xff;
192 outb(temp, dev->iobase + DAC02_MSB(chan));
197 COMEDI_INITCLEANUP(driver_poc);