staging: comedi: remove FSF address from boilerplate text
[deliverable/linux.git] / drivers / staging / comedi / drivers / ni_daq_700.c
1 /*
2 * comedi/drivers/ni_daq_700.c
3 * Driver for DAQCard-700 DIO/AI
4 * copied from 8255
5 *
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 1998 David A. Schleef <ds@schleef.org>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20 /*
21 Driver: ni_daq_700
22 Description: National Instruments PCMCIA DAQCard-700 DIO only
23 Author: Fred Brooks <nsaspook@nsaspook.com>,
24 based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
25 Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
26 Status: works
27 Updated: Wed, 19 Sep 2012 12:07:20 +0000
28
29 The daqcard-700 appears in Comedi as a digital I/O subdevice (0) with
30 16 channels and a analog input subdevice (1) with 16 single-ended channels.
31
32 Digital: The channel 0 corresponds to the daqcard-700's output
33 port, bit 0; channel 8 corresponds to the input port, bit 0.
34
35 Digital direction configuration: channels 0-7 output, 8-15 input (8225 device
36 emu as port A output, port B input, port C N/A).
37
38 Analog: The input range is 0 to 4095 for -10 to +10 volts
39 IRQ is assigned but not used.
40
41 Version 0.1 Original DIO only driver
42 Version 0.2 DIO and basic AI analog input support on 16 se channels
43
44 Manuals: Register level: http://www.ni.com/pdf/manuals/340698.pdf
45 User Manual: http://www.ni.com/pdf/manuals/320676d.pdf
46 */
47
48 #include <linux/ioport.h>
49 #include <linux/interrupt.h>
50 #include <linux/slab.h>
51
52 #include "../comedidev.h"
53
54 #include <pcmcia/cistpl.h>
55 #include <pcmcia/ds.h>
56
57 /* daqcard700 registers */
58 #define DIO_W 0x04 /* WO 8bit */
59 #define DIO_R 0x05 /* RO 8bit */
60 #define CMD_R1 0x00 /* WO 8bit */
61 #define CMD_R2 0x07 /* RW 8bit */
62 #define CMD_R3 0x05 /* W0 8bit */
63 #define STA_R1 0x00 /* RO 8bit */
64 #define STA_R2 0x01 /* RO 8bit */
65 #define ADFIFO_R 0x02 /* RO 16bit */
66 #define ADCLEAR_R 0x01 /* WO 8bit */
67 #define CDA_R0 0x08 /* RW 8bit */
68 #define CDA_R1 0x09 /* RW 8bit */
69 #define CDA_R2 0x0A /* RW 8bit */
70 #define CMO_R 0x0B /* RO 8bit */
71 #define TIC_R 0x06 /* WO 8bit */
72
73 static int daq700_dio_insn_bits(struct comedi_device *dev,
74 struct comedi_subdevice *s,
75 struct comedi_insn *insn, unsigned int *data)
76 {
77 if (data[0]) {
78 s->state &= ~data[0];
79 s->state |= (data[0] & data[1]);
80
81 if (data[0] & 0xff)
82 outb(s->state & 0xff, dev->iobase + DIO_W);
83 }
84
85 data[1] = s->state & 0xff;
86 data[1] |= inb(dev->iobase + DIO_R) << 8;
87
88 return insn->n;
89 }
90
91 static int daq700_dio_insn_config(struct comedi_device *dev,
92 struct comedi_subdevice *s,
93 struct comedi_insn *insn, unsigned int *data)
94 {
95 unsigned int chan = 1 << CR_CHAN(insn->chanspec);
96
97 switch (data[0]) {
98 case INSN_CONFIG_DIO_INPUT:
99 break;
100 case INSN_CONFIG_DIO_OUTPUT:
101 break;
102 case INSN_CONFIG_DIO_QUERY:
103 data[1] = (s->io_bits & chan) ? COMEDI_OUTPUT : COMEDI_INPUT;
104 break;
105 default:
106 return -EINVAL;
107 }
108
109 return insn->n;
110 }
111
112 static int daq700_ai_rinsn(struct comedi_device *dev,
113 struct comedi_subdevice *s,
114 struct comedi_insn *insn, unsigned int *data)
115 {
116 int n, i, chan;
117 int d;
118 unsigned int status;
119 enum { TIMEOUT = 100 };
120
121 chan = CR_CHAN(insn->chanspec);
122 /* write channel to multiplexer */
123 /* set mask scan bit high to disable scanning */
124 outb(chan | 0x80, dev->iobase + CMD_R1);
125
126 /* convert n samples */
127 for (n = 0; n < insn->n; n++) {
128 /* trigger conversion with out0 L to H */
129 outb(0x00, dev->iobase + CMD_R2); /* enable ADC conversions */
130 outb(0x30, dev->iobase + CMO_R); /* mode 0 out0 L, from H */
131 /* mode 1 out0 H, L to H, start conversion */
132 outb(0x32, dev->iobase + CMO_R);
133 /* wait for conversion to end */
134 for (i = 0; i < TIMEOUT; i++) {
135 status = inb(dev->iobase + STA_R2);
136 if ((status & 0x03) != 0) {
137 dev_info(dev->class_dev,
138 "Overflow/run Error\n");
139 return -EOVERFLOW;
140 }
141 status = inb(dev->iobase + STA_R1);
142 if ((status & 0x02) != 0) {
143 dev_info(dev->class_dev, "Data Error\n");
144 return -ENODATA;
145 }
146 if ((status & 0x11) == 0x01) {
147 /* ADC conversion complete */
148 break;
149 }
150 udelay(1);
151 }
152 if (i == TIMEOUT) {
153 dev_info(dev->class_dev,
154 "timeout during ADC conversion\n");
155 return -ETIMEDOUT;
156 }
157 /* read data */
158 d = inw(dev->iobase + ADFIFO_R);
159 /* mangle the data as necessary */
160 /* Bipolar Offset Binary: 0 to 4095 for -10 to +10 */
161 d &= 0x0fff;
162 d ^= 0x0800;
163 data[n] = d;
164 }
165 return n;
166 }
167
168 /*
169 * Data acquisition is enabled.
170 * The counter 0 output is high.
171 * The I/O connector pin CLK1 drives counter 1 source.
172 * Multiple-channel scanning is disabled.
173 * All interrupts are disabled.
174 * The analog input range is set to +-10 V
175 * The analog input mode is single-ended.
176 * The analog input circuitry is initialized to channel 0.
177 * The A/D FIFO is cleared.
178 */
179 static void daq700_ai_config(struct comedi_device *dev,
180 struct comedi_subdevice *s)
181 {
182 unsigned long iobase = dev->iobase;
183
184 outb(0x80, iobase + CMD_R1); /* disable scanning, ADC to chan 0 */
185 outb(0x00, iobase + CMD_R2); /* clear all bits */
186 outb(0x00, iobase + CMD_R3); /* set +-10 range */
187 outb(0x32, iobase + CMO_R); /* config counter mode1, out0 to H */
188 outb(0x00, iobase + TIC_R); /* clear counter interrupt */
189 outb(0x00, iobase + ADCLEAR_R); /* clear the ADC FIFO */
190 inw(iobase + ADFIFO_R); /* read 16bit junk from FIFO to clear */
191 }
192
193 static int daq700_auto_attach(struct comedi_device *dev,
194 unsigned long context)
195 {
196 struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
197 struct comedi_subdevice *s;
198 int ret;
199
200 link->config_flags |= CONF_AUTO_SET_IO;
201 ret = comedi_pcmcia_enable(dev, NULL);
202 if (ret)
203 return ret;
204 dev->iobase = link->resource[0]->start;
205
206 ret = comedi_alloc_subdevices(dev, 2);
207 if (ret)
208 return ret;
209
210 /* DAQCard-700 dio */
211 s = &dev->subdevices[0];
212 s->type = COMEDI_SUBD_DIO;
213 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
214 s->n_chan = 16;
215 s->range_table = &range_digital;
216 s->maxdata = 1;
217 s->insn_bits = daq700_dio_insn_bits;
218 s->insn_config = daq700_dio_insn_config;
219 s->state = 0;
220 s->io_bits = 0x00ff;
221
222 /* DAQCard-700 ai */
223 s = &dev->subdevices[1];
224 s->type = COMEDI_SUBD_AI;
225 /* we support single-ended (ground) */
226 s->subdev_flags = SDF_READABLE | SDF_GROUND;
227 s->n_chan = 16;
228 s->maxdata = (1 << 12) - 1;
229 s->range_table = &range_bipolar10;
230 s->insn_read = daq700_ai_rinsn;
231 daq700_ai_config(dev, s);
232
233 dev_info(dev->class_dev, "%s: %s, io 0x%lx\n",
234 dev->driver->driver_name,
235 dev->board_name,
236 dev->iobase);
237
238 return 0;
239 }
240
241 static struct comedi_driver daq700_driver = {
242 .driver_name = "ni_daq_700",
243 .module = THIS_MODULE,
244 .auto_attach = daq700_auto_attach,
245 .detach = comedi_pcmcia_disable,
246 };
247
248 static int daq700_cs_attach(struct pcmcia_device *link)
249 {
250 return comedi_pcmcia_auto_config(link, &daq700_driver);
251 }
252
253 static const struct pcmcia_device_id daq700_cs_ids[] = {
254 PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),
255 PCMCIA_DEVICE_NULL
256 };
257 MODULE_DEVICE_TABLE(pcmcia, daq700_cs_ids);
258
259 static struct pcmcia_driver daq700_cs_driver = {
260 .name = "ni_daq_700",
261 .owner = THIS_MODULE,
262 .id_table = daq700_cs_ids,
263 .probe = daq700_cs_attach,
264 .remove = comedi_pcmcia_auto_unconfig,
265 };
266 module_comedi_pcmcia_driver(daq700_driver, daq700_cs_driver);
267
268 MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
269 MODULE_DESCRIPTION(
270 "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO/AI");
271 MODULE_VERSION("0.2.00");
272 MODULE_LICENSE("GPL");
This page took 0.049522 seconds and 5 git commands to generate.