]>
git.proxmox.com Git - mirror_ubuntu-kernels.git/blob - drivers/staging/comedi/drivers/poc.c
3 Mini-drivers for POC (Piece of Crap) boards
4 Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
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.
23 Description: Generic driver for very simple devices
25 Devices: [Keithley Metrabyte] DAC-02 (dac02), [Advantech] PCL-733 (pcl733),
27 Updated: Sat, 16 Mar 2002 17:34:48 -0800
30 This driver is indended to support very simple ISA-based devices,
32 dac02 - Keithley DAC-02 analog output board
33 pcl733 - Advantech PCL-733
34 pcl734 - Advantech PCL-734
36 Configuration options:
40 #include "../comedidev.h"
42 #include <linux/ioport.h>
44 static int poc_attach(comedi_device
* dev
, comedi_devconfig
* it
);
45 static int poc_detach(comedi_device
* dev
);
46 static int readback_insn(comedi_device
* dev
, comedi_subdevice
* s
,
47 comedi_insn
* insn
, unsigned int * data
);
49 static int dac02_ao_winsn(comedi_device
* dev
, comedi_subdevice
* s
,
50 comedi_insn
* insn
, unsigned int * data
);
51 static int pcl733_insn_bits(comedi_device
* dev
, comedi_subdevice
* s
,
52 comedi_insn
* insn
, unsigned int * data
);
53 static int pcl734_insn_bits(comedi_device
* dev
, comedi_subdevice
* s
,
54 comedi_insn
* insn
, unsigned int * data
);
56 struct boarddef_struct
{
59 int (*setup
) (comedi_device
*);
63 int (*winsn
) (comedi_device
*, comedi_subdevice
*, comedi_insn
*,
65 int (*rinsn
) (comedi_device
*, comedi_subdevice
*, comedi_insn
*,
67 int (*insnbits
) (comedi_device
*, comedi_subdevice
*, comedi_insn
*,
69 const comedi_lrange
*range
;
71 static const struct boarddef_struct boards
[] = {
79 winsn
: dac02_ao_winsn
,
81 range
: &range_unknown
,
89 insnbits
:pcl733_insn_bits
,
90 range
: &range_digital
,
98 insnbits
:pcl734_insn_bits
,
99 range
: &range_digital
,
103 #define n_boards (sizeof(boards)/sizeof(boards[0]))
104 #define this_board ((const struct boarddef_struct *)dev->board_ptr)
106 static comedi_driver driver_poc
= {
111 board_name
:&boards
[0].name
,
113 offset
:sizeof(boards
[0]),
116 static int poc_attach(comedi_device
* dev
, comedi_devconfig
* it
)
119 unsigned long iobase
;
122 iobase
= it
->options
[0];
123 printk("comedi%d: poc: using %s iobase 0x%lx\n", dev
->minor
,
124 this_board
->name
, iobase
);
126 dev
->board_name
= this_board
->name
;
129 printk("io base address required\n");
133 iosize
= this_board
->iosize
;
134 /* check if io addresses are available */
135 if (!request_region(iobase
, iosize
, "dac02")) {
136 printk("I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase
, iobase
+ iosize
- 1);
139 dev
->iobase
= iobase
;
141 if (alloc_subdevices(dev
, 1) < 0)
143 if (alloc_private(dev
, sizeof(unsigned int) * this_board
->n_chan
) < 0)
146 /* analog output subdevice */
147 s
= dev
->subdevices
+ 0;
148 s
->type
= this_board
->type
;
149 s
->n_chan
= this_board
->n_chan
;
150 s
->maxdata
= (1 << this_board
->n_bits
) - 1;
151 s
->range_table
= this_board
->range
;
152 s
->insn_write
= this_board
->winsn
;
153 s
->insn_read
= this_board
->rinsn
;
154 s
->insn_bits
= this_board
->insnbits
;
155 if (s
->type
== COMEDI_SUBD_AO
|| s
->type
== COMEDI_SUBD_DO
) {
156 s
->subdev_flags
= SDF_WRITABLE
;
162 static int poc_detach(comedi_device
* dev
)
164 /* only free stuff if it has been allocated by _attach */
166 release_region(dev
->iobase
, this_board
->iosize
);
168 printk("comedi%d: dac02: remove\n", dev
->minor
);
173 static int readback_insn(comedi_device
* dev
, comedi_subdevice
* s
,
174 comedi_insn
* insn
, unsigned int * data
)
178 chan
= CR_CHAN(insn
->chanspec
);
179 data
[0] = ((unsigned int *) dev
->private)[chan
];
184 /* DAC-02 registers */
185 #define DAC02_LSB(a) (2 * a)
186 #define DAC02_MSB(a) (2 * a + 1)
188 static int dac02_ao_winsn(comedi_device
* dev
, comedi_subdevice
* s
,
189 comedi_insn
* insn
, unsigned int * data
)
195 chan
= CR_CHAN(insn
->chanspec
);
196 ((unsigned int *) dev
->private)[chan
] = data
[0];
199 // convert to complementary binary if range is bipolar
200 if ((CR_RANGE(insn
->chanspec
) & 0x2) == 0)
203 temp
= (output
<< 4) & 0xf0;
204 outb(temp
, dev
->iobase
+ DAC02_LSB(chan
));
205 temp
= (output
>> 4) & 0xff;
206 outb(temp
, dev
->iobase
+ DAC02_MSB(chan
));
211 static int pcl733_insn_bits(comedi_device
* dev
, comedi_subdevice
* s
,
212 comedi_insn
* insn
, unsigned int * data
)
217 data
[1] = inb(dev
->iobase
+ 0);
218 data
[1] |= (inb(dev
->iobase
+ 1) << 8);
219 data
[1] |= (inb(dev
->iobase
+ 2) << 16);
220 data
[1] |= (inb(dev
->iobase
+ 3) << 24);
225 static int pcl734_insn_bits(comedi_device
* dev
, comedi_subdevice
* s
,
226 comedi_insn
* insn
, unsigned int * data
)
231 s
->state
&= ~data
[0];
232 s
->state
|= (data
[0] & data
[1]);
233 if ((data
[0] >> 0) & 0xff)
234 outb((s
->state
>> 0) & 0xff, dev
->iobase
+ 0);
235 if ((data
[0] >> 8) & 0xff)
236 outb((s
->state
>> 8) & 0xff, dev
->iobase
+ 1);
237 if ((data
[0] >> 16) & 0xff)
238 outb((s
->state
>> 16) & 0xff, dev
->iobase
+ 2);
239 if ((data
[0] >> 24) & 0xff)
240 outb((s
->state
>> 24) & 0xff, dev
->iobase
+ 3);
247 COMEDI_INITCLEANUP(driver_poc
);