staging: comedi: pcmuio: remove subdevice pointer math
[deliverable/linux.git] / drivers / staging / comedi / drivers / poc.c
CommitLineData
ac52af96
DS
1/*
2 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>
6
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.
11
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.
16
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.
20*/
21/*
22Driver: poc
23Description: Generic driver for very simple devices
24Author: ds
25Devices: [Keithley Metrabyte] DAC-02 (dac02), [Advantech] PCL-733 (pcl733),
26 PCL-734 (pcl734)
27Updated: Sat, 16 Mar 2002 17:34:48 -0800
28Status: unknown
29
30This driver is indended to support very simple ISA-based devices,
31including:
32 dac02 - Keithley DAC-02 analog output board
33 pcl733 - Advantech PCL-733
34 pcl734 - Advantech PCL-734
35
36Configuration options:
37 [0] - I/O port base
38*/
39
40#include "../comedidev.h"
41
42#include <linux/ioport.h>
43
ac52af96
DS
44struct boarddef_struct {
45 const char *name;
46 unsigned int iosize;
71b5f4f1 47 int (*setup) (struct comedi_device *);
ac52af96
DS
48 int type;
49 int n_chan;
50 int n_bits;
0a85b6f0
MT
51 int (*winsn) (struct comedi_device *, struct comedi_subdevice *,
52 struct comedi_insn *, unsigned int *);
53 int (*rinsn) (struct comedi_device *, struct comedi_subdevice *,
54 struct comedi_insn *, unsigned int *);
55 int (*insnbits) (struct comedi_device *, struct comedi_subdevice *,
56 struct comedi_insn *, unsigned int *);
9ced1de6 57 const struct comedi_lrange *range;
ac52af96 58};
ac52af96 59
da91b269 60static int readback_insn(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 61 struct comedi_insn *insn, unsigned int *data)
ac52af96
DS
62{
63 int chan;
64
65 chan = CR_CHAN(insn->chanspec);
0a85b6f0 66 data[0] = ((unsigned int *)dev->private)[chan];
ac52af96
DS
67
68 return 1;
69}
70
71/* DAC-02 registers */
72#define DAC02_LSB(a) (2 * a)
73#define DAC02_MSB(a) (2 * a + 1)
74
da91b269 75static int dac02_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
0a85b6f0 76 struct comedi_insn *insn, unsigned int *data)
ac52af96
DS
77{
78 int temp;
79 int chan;
80 int output;
81
82 chan = CR_CHAN(insn->chanspec);
0a85b6f0 83 ((unsigned int *)dev->private)[chan] = data[0];
ac52af96
DS
84 output = data[0];
85#ifdef wrong
2696fb57 86 /* convert to complementary binary if range is bipolar */
ac52af96
DS
87 if ((CR_RANGE(insn->chanspec) & 0x2) == 0)
88 output = ~output;
89#endif
90 temp = (output << 4) & 0xf0;
91 outb(temp, dev->iobase + DAC02_LSB(chan));
92 temp = (output >> 4) & 0xff;
93 outb(temp, dev->iobase + DAC02_MSB(chan));
94
95 return 1;
96}
97
0a85b6f0
MT
98static int pcl733_insn_bits(struct comedi_device *dev,
99 struct comedi_subdevice *s,
100 struct comedi_insn *insn, unsigned int *data)
ac52af96 101{
ac52af96
DS
102 data[1] = inb(dev->iobase + 0);
103 data[1] |= (inb(dev->iobase + 1) << 8);
104 data[1] |= (inb(dev->iobase + 2) << 16);
105 data[1] |= (inb(dev->iobase + 3) << 24);
106
a2714e3e 107 return insn->n;
ac52af96
DS
108}
109
0a85b6f0
MT
110static int pcl734_insn_bits(struct comedi_device *dev,
111 struct comedi_subdevice *s,
112 struct comedi_insn *insn, unsigned int *data)
ac52af96 113{
ac52af96
DS
114 if (data[0]) {
115 s->state &= ~data[0];
116 s->state |= (data[0] & data[1]);
117 if ((data[0] >> 0) & 0xff)
118 outb((s->state >> 0) & 0xff, dev->iobase + 0);
119 if ((data[0] >> 8) & 0xff)
120 outb((s->state >> 8) & 0xff, dev->iobase + 1);
121 if ((data[0] >> 16) & 0xff)
122 outb((s->state >> 16) & 0xff, dev->iobase + 2);
123 if ((data[0] >> 24) & 0xff)
124 outb((s->state >> 24) & 0xff, dev->iobase + 3);
125 }
126 data[1] = s->state;
127
a2714e3e 128 return insn->n;
ac52af96
DS
129}
130
9a644c40
HS
131static int poc_attach(struct comedi_device *dev, struct comedi_devconfig *it)
132{
d5016e24 133 const struct boarddef_struct *board = comedi_board(dev);
9a644c40
HS
134 struct comedi_subdevice *s;
135 unsigned long iobase;
136 unsigned int iosize;
8b6c5694 137 int ret;
9a644c40
HS
138
139 iobase = it->options[0];
140 printk(KERN_INFO "comedi%d: poc: using %s iobase 0x%lx\n", dev->minor,
d5016e24 141 board->name, iobase);
9a644c40 142
d5016e24 143 dev->board_name = board->name;
9a644c40
HS
144
145 if (iobase == 0) {
146 printk(KERN_ERR "io base address required\n");
147 return -EINVAL;
148 }
149
d5016e24 150 iosize = board->iosize;
9a644c40
HS
151 /* check if io addresses are available */
152 if (!request_region(iobase, iosize, "dac02")) {
153 printk(KERN_ERR "I/O port conflict: failed to allocate ports "
154 "0x%lx to 0x%lx\n", iobase, iobase + iosize - 1);
155 return -EIO;
156 }
157 dev->iobase = iobase;
158
8b6c5694
HS
159 ret = comedi_alloc_subdevices(dev, 1);
160 if (ret)
161 return ret;
162
d5016e24 163 if (alloc_private(dev, sizeof(unsigned int) * board->n_chan) < 0)
9a644c40
HS
164 return -ENOMEM;
165
166 /* analog output subdevice */
167 s = dev->subdevices + 0;
d5016e24
HS
168 s->type = board->type;
169 s->n_chan = board->n_chan;
170 s->maxdata = (1 << board->n_bits) - 1;
171 s->range_table = board->range;
172 s->insn_write = board->winsn;
173 s->insn_read = board->rinsn;
174 s->insn_bits = board->insnbits;
9a644c40
HS
175 if (s->type == COMEDI_SUBD_AO || s->type == COMEDI_SUBD_DO)
176 s->subdev_flags = SDF_WRITABLE;
177
178 return 0;
179}
180
484ecc95 181static void poc_detach(struct comedi_device *dev)
9a644c40 182{
d5016e24
HS
183 const struct boarddef_struct *board = comedi_board(dev);
184
9a644c40 185 if (dev->iobase)
d5016e24 186 release_region(dev->iobase, board->iosize);
9a644c40
HS
187}
188
189static const struct boarddef_struct boards[] = {
190 {
191 .name = "dac02",
192 .iosize = 8,
193 /* .setup = dac02_setup, */
194 .type = COMEDI_SUBD_AO,
195 .n_chan = 2,
196 .n_bits = 12,
197 .winsn = dac02_ao_winsn,
198 .rinsn = readback_insn,
199 .range = &range_unknown,
200 }, {
201 .name = "pcl733",
202 .iosize = 4,
203 .type = COMEDI_SUBD_DI,
204 .n_chan = 32,
205 .n_bits = 1,
206 .insnbits = pcl733_insn_bits,
207 .range = &range_digital,
208 }, {
209 .name = "pcl734",
210 .iosize = 4,
211 .type = COMEDI_SUBD_DO,
212 .n_chan = 32,
213 .n_bits = 1,
214 .insnbits = pcl734_insn_bits,
215 .range = &range_digital,
216 },
217};
218
294f930d 219static struct comedi_driver poc_driver = {
9a644c40
HS
220 .driver_name = "poc",
221 .module = THIS_MODULE,
222 .attach = poc_attach,
223 .detach = poc_detach,
224 .board_name = &boards[0].name,
225 .num_names = ARRAY_SIZE(boards),
226 .offset = sizeof(boards[0]),
227};
294f930d 228module_comedi_driver(poc_driver);
90f703d3
AT
229
230MODULE_AUTHOR("Comedi http://www.comedi.org");
231MODULE_DESCRIPTION("Comedi low-level driver");
232MODULE_LICENSE("GPL");
This page took 0.375822 seconds and 5 git commands to generate.