[go: nahoru, domu]

1/*
2 * fl512.c
3 * Anders Gnistrup <ex18@kalman.iau.dtu.dk>
4 *
5 * COMEDI - Linux Control and Measurement Device Interface
6 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 * GNU General Public License for more details.
17 */
18
19/*
20 * Driver: fl512
21 * Description: unknown
22 * Author: Anders Gnistrup <ex18@kalman.iau.dtu.dk>
23 * Devices: [unknown] FL512 (fl512)
24 * Status: unknown
25 *
26 * Digital I/O is not supported.
27 *
28 * Configuration options:
29 *   [0] - I/O port base address
30 */
31
32#include <linux/module.h>
33#include "../comedidev.h"
34
35#include <linux/delay.h>
36
37/*
38 * Register I/O map
39 */
40#define FL512_AI_LSB_REG		0x02
41#define FL512_AI_MSB_REG		0x03
42#define FL512_AI_MUX_REG		0x02
43#define FL512_AI_START_CONV_REG		0x03
44#define FL512_AO_DATA_REG(x)		(0x04 + ((x) * 2))
45#define FL512_AO_TRIG_REG(x)		(0x04 + ((x) * 2))
46
47static const struct comedi_lrange range_fl512 = {
48	4, {
49		BIP_RANGE(0.5),
50		BIP_RANGE(1),
51		BIP_RANGE(5),
52		BIP_RANGE(10),
53		UNI_RANGE(1),
54		UNI_RANGE(5),
55		UNI_RANGE(10)
56	}
57};
58
59static int fl512_ai_insn_read(struct comedi_device *dev,
60			      struct comedi_subdevice *s,
61			      struct comedi_insn *insn,
62			      unsigned int *data)
63{
64	unsigned int chan = CR_CHAN(insn->chanspec);
65	unsigned int val;
66	int i;
67
68	outb(chan, dev->iobase + FL512_AI_MUX_REG);
69
70	for (i = 0; i < insn->n; i++) {
71		outb(0, dev->iobase + FL512_AI_START_CONV_REG);
72
73		/* XXX should test "done" flag instead of delay */
74		udelay(30);
75
76		val = inb(dev->iobase + FL512_AI_LSB_REG);
77		val |= (inb(dev->iobase + FL512_AI_MSB_REG) << 8);
78		val &= s->maxdata;
79
80		data[i] = val;
81	}
82
83	return insn->n;
84}
85
86static int fl512_ao_insn_write(struct comedi_device *dev,
87			       struct comedi_subdevice *s,
88			       struct comedi_insn *insn,
89			       unsigned int *data)
90{
91	unsigned int chan = CR_CHAN(insn->chanspec);
92	unsigned int val = s->readback[chan];
93	int i;
94
95	for (i = 0; i < insn->n; i++) {
96		val = data[i];
97
98		/* write LSB, MSB then trigger conversion */
99		outb(val & 0x0ff, dev->iobase + FL512_AO_DATA_REG(chan));
100		outb((val >> 8) & 0xf, dev->iobase + FL512_AO_DATA_REG(chan));
101		inb(dev->iobase + FL512_AO_TRIG_REG(chan));
102	}
103	s->readback[chan] = val;
104
105	return insn->n;
106}
107
108static int fl512_attach(struct comedi_device *dev, struct comedi_devconfig *it)
109{
110	struct comedi_subdevice *s;
111	int ret;
112
113	ret = comedi_request_region(dev, it->options[0], 0x10);
114	if (ret)
115		return ret;
116
117	ret = comedi_alloc_subdevices(dev, 2);
118	if (ret)
119		return ret;
120
121	/* Analog Input subdevice */
122	s = &dev->subdevices[0];
123	s->type		= COMEDI_SUBD_AI;
124	s->subdev_flags	= SDF_READABLE | SDF_GROUND;
125	s->n_chan	= 16;
126	s->maxdata	= 0x0fff;
127	s->range_table	= &range_fl512;
128	s->insn_read	= fl512_ai_insn_read;
129
130	/* Analog Output subdevice */
131	s = &dev->subdevices[1];
132	s->type		= COMEDI_SUBD_AO;
133	s->subdev_flags	= SDF_WRITABLE;
134	s->n_chan	= 2;
135	s->maxdata	= 0x0fff;
136	s->range_table	= &range_fl512;
137	s->insn_write	= fl512_ao_insn_write;
138	s->insn_read	= comedi_readback_insn_read;
139
140	ret = comedi_alloc_subdev_readback(s);
141	if (ret)
142		return ret;
143
144	return 0;
145}
146
147static struct comedi_driver fl512_driver = {
148	.driver_name	= "fl512",
149	.module		= THIS_MODULE,
150	.attach		= fl512_attach,
151	.detach		= comedi_legacy_detach,
152};
153module_comedi_driver(fl512_driver);
154
155MODULE_AUTHOR("Comedi http://www.comedi.org");
156MODULE_DESCRIPTION("Comedi low-level driver");
157MODULE_LICENSE("GPL");
158