Merge remote-tracking branch 'staging/staging-next'
[deliverable/linux.git] / drivers / staging / comedi / drivers / ni_atmio.c
CommitLineData
a8b77430 1/*
44a678b9
HS
2 * Comedi driver for NI AT-MIO E series cards
3 *
4 * COMEDI - Linux Control and Measurement Device Interface
5 * Copyright (C) 1997-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 */
a8b77430 17
a8b77430 18/*
44a678b9
HS
19 * Driver: ni_atmio
20 * Description: National Instruments AT-MIO-E series
21 * Author: ds
22 * Devices: [National Instruments] AT-MIO-16E-1 (ni_atmio),
23 * AT-MIO-16E-2, AT-MIO-16E-10, AT-MIO-16DE-10, AT-MIO-64E-3,
24 * AT-MIO-16XE-50, AT-MIO-16XE-10, AT-AI-16XE-10
25 * Status: works
26 * Updated: Thu May 1 20:03:02 CDT 2003
27 *
28 * The driver has 2.6 kernel isapnp support, and will automatically probe for
29 * a supported board if the I/O base is left unspecified with comedi_config.
30 * However, many of the isapnp id numbers are unknown. If your board is not
31 * recognized, please send the output of 'cat /proc/isapnp' (you may need to
32 * modprobe the isa-pnp module for /proc/isapnp to exist) so the id numbers
33 * for your board can be added to the driver.
34 *
35 * Otherwise, you can use the isapnptools package to configure your board.
36 * Use isapnp to configure the I/O base and IRQ for the board, and then pass
37 * the same values as parameters in comedi_config. A sample isapnp.conf file
38 * is included in the etc/ directory of Comedilib.
39 *
40 * Comedilib includes a utility to autocalibrate these boards. The boards
41 * seem to boot into a state where the all calibration DACs are at one
42 * extreme of their range, thus the default calibration is terrible.
43 * Calibration at boot is strongly encouraged.
44 *
45 * To use the extended digital I/O on some of the boards, enable the
46 * 8255 driver when configuring the Comedi source tree.
47 *
48 * External triggering is supported for some events. The channel index
49 * (scan_begin_arg, etc.) maps to PFI0 - PFI9.
50 *
51 * Some of the more esoteric triggering possibilities of these boards are
52 * not supported.
53 */
a8b77430 54
a8b77430 55/*
44a678b9
HS
56 * The real guts of the driver is in ni_mio_common.c, which is included
57 * both here and in ni_pcimio.c
58 *
59 * Interrupt support added by Truxton Fulton <trux@truxton.com>
60 *
61 * References for specifications:
62 * 340747b.pdf Register Level Programmer Manual (obsolete)
63 * 340747c.pdf Register Level Programmer Manual (new)
64 * DAQ-STC reference manual
65 *
66 * Other possibly relevant info:
67 * 320517c.pdf User manual (obsolete)
68 * 320517f.pdf User manual (new)
69 * 320889a.pdf delete
70 * 320906c.pdf maximum signal ratings
71 * 321066a.pdf about 16x
72 * 321791a.pdf discontinuation of at-mio-16e-10 rev. c
73 * 321808a.pdf about at-mio-16e-10 rev P
74 * 321837a.pdf discontinuation of at-mio-16de-10 rev d
75 * 321838a.pdf about at-mio-16de-10 rev N
76 *
77 * ISSUES:
78 * - need to deal with external reference for DAC, and other DAC
79 * properties in board properties
80 * - deal with at-mio-16de-10 revision D to N changes, etc.
81 */
a8b77430 82
ce157f80 83#include <linux/module.h>
25436dc9 84#include <linux/interrupt.h>
a8b77430
DS
85#include "../comedidev.h"
86
a8b77430
DS
87#include <linux/isapnp.h>
88
89#include "ni_stc.h"
90#include "8255.h"
91
da91a80a 92/* AT specific setup */
8ab41df0 93static const struct ni_board_struct ni_boards[] = {
25294851 94 {
b674f9df 95 .name = "at-mio-16e-1",
25294851
HS
96 .device_id = 44,
97 .isapnp_id = 0x0000, /* XXX unknown */
25294851 98 .n_adchan = 16,
db2255f5 99 .ai_maxdata = 0x0fff,
25294851
HS
100 .ai_fifo_depth = 8192,
101 .gainlkup = ai_gain_16,
102 .ai_speed = 800,
103 .n_aochan = 2,
c5f26499 104 .ao_maxdata = 0x0fff,
25294851
HS
105 .ao_fifo_depth = 2048,
106 .ao_range_table = &range_ni_E_ao_ext,
25294851 107 .ao_speed = 1000,
25294851
HS
108 .caldac = { mb88341 },
109 }, {
b674f9df 110 .name = "at-mio-16e-2",
25294851
HS
111 .device_id = 25,
112 .isapnp_id = 0x1900,
25294851 113 .n_adchan = 16,
db2255f5 114 .ai_maxdata = 0x0fff,
25294851
HS
115 .ai_fifo_depth = 2048,
116 .gainlkup = ai_gain_16,
117 .ai_speed = 2000,
118 .n_aochan = 2,
c5f26499 119 .ao_maxdata = 0x0fff,
25294851
HS
120 .ao_fifo_depth = 2048,
121 .ao_range_table = &range_ni_E_ao_ext,
25294851 122 .ao_speed = 1000,
25294851
HS
123 .caldac = { mb88341 },
124 }, {
b674f9df 125 .name = "at-mio-16e-10",
25294851
HS
126 .device_id = 36,
127 .isapnp_id = 0x2400,
25294851 128 .n_adchan = 16,
db2255f5 129 .ai_maxdata = 0x0fff,
25294851
HS
130 .ai_fifo_depth = 512,
131 .gainlkup = ai_gain_16,
132 .ai_speed = 10000,
133 .n_aochan = 2,
c5f26499 134 .ao_maxdata = 0x0fff,
25294851 135 .ao_range_table = &range_ni_E_ao_ext,
25294851 136 .ao_speed = 10000,
25294851
HS
137 .caldac = { ad8804_debug },
138 }, {
b674f9df 139 .name = "at-mio-16de-10",
25294851
HS
140 .device_id = 37,
141 .isapnp_id = 0x2500,
25294851 142 .n_adchan = 16,
db2255f5 143 .ai_maxdata = 0x0fff,
25294851
HS
144 .ai_fifo_depth = 512,
145 .gainlkup = ai_gain_16,
146 .ai_speed = 10000,
147 .n_aochan = 2,
c5f26499 148 .ao_maxdata = 0x0fff,
25294851 149 .ao_range_table = &range_ni_E_ao_ext,
25294851 150 .ao_speed = 10000,
25294851
HS
151 .caldac = { ad8804_debug },
152 .has_8255 = 1,
153 }, {
b674f9df 154 .name = "at-mio-64e-3",
25294851
HS
155 .device_id = 38,
156 .isapnp_id = 0x2600,
25294851 157 .n_adchan = 64,
db2255f5 158 .ai_maxdata = 0x0fff,
25294851
HS
159 .ai_fifo_depth = 2048,
160 .gainlkup = ai_gain_16,
161 .ai_speed = 2000,
162 .n_aochan = 2,
c5f26499 163 .ao_maxdata = 0x0fff,
25294851
HS
164 .ao_fifo_depth = 2048,
165 .ao_range_table = &range_ni_E_ao_ext,
25294851 166 .ao_speed = 1000,
25294851
HS
167 .caldac = { ad8804_debug },
168 }, {
b674f9df 169 .name = "at-mio-16xe-50",
25294851
HS
170 .device_id = 39,
171 .isapnp_id = 0x2700,
25294851 172 .n_adchan = 16,
db2255f5 173 .ai_maxdata = 0xffff,
25294851
HS
174 .ai_fifo_depth = 512,
175 .alwaysdither = 1,
176 .gainlkup = ai_gain_8,
177 .ai_speed = 50000,
178 .n_aochan = 2,
c5f26499 179 .ao_maxdata = 0x0fff,
25294851
HS
180 .ao_range_table = &range_bipolar10,
181 .ao_speed = 50000,
25294851
HS
182 .caldac = { dac8800, dac8043 },
183 }, {
b674f9df 184 .name = "at-mio-16xe-10",
25294851
HS
185 .device_id = 50,
186 .isapnp_id = 0x0000, /* XXX unknown */
25294851 187 .n_adchan = 16,
db2255f5 188 .ai_maxdata = 0xffff,
25294851
HS
189 .ai_fifo_depth = 512,
190 .alwaysdither = 1,
191 .gainlkup = ai_gain_14,
192 .ai_speed = 10000,
193 .n_aochan = 2,
c5f26499 194 .ao_maxdata = 0xffff,
25294851
HS
195 .ao_fifo_depth = 2048,
196 .ao_range_table = &range_ni_E_ao_ext,
25294851 197 .ao_speed = 1000,
25294851
HS
198 .caldac = { dac8800, dac8043, ad8522 },
199 }, {
b674f9df 200 .name = "at-ai-16xe-10",
25294851
HS
201 .device_id = 51,
202 .isapnp_id = 0x0000, /* XXX unknown */
25294851 203 .n_adchan = 16,
db2255f5 204 .ai_maxdata = 0xffff,
25294851 205 .ai_fifo_depth = 512,
da91a80a 206 .alwaysdither = 1, /* unknown */
25294851
HS
207 .gainlkup = ai_gain_14,
208 .ai_speed = 10000,
25294851
HS
209 .caldac = { dac8800, dac8043, ad8522 },
210 },
a8b77430
DS
211};
212
963ff774
JB
213static const int ni_irqpin[] = {
214 -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
215};
a8b77430 216
ac63baf5 217#include "ni_mio_common.c"
a8b77430 218
a8b77430 219static struct pnp_device_id device_ids[] = {
bc2955dd
GH
220 {.id = "NIC1900", .driver_data = 0},
221 {.id = "NIC2400", .driver_data = 0},
222 {.id = "NIC2500", .driver_data = 0},
223 {.id = "NIC2600", .driver_data = 0},
224 {.id = "NIC2700", .driver_data = 0},
a8b77430
DS
225 {.id = ""}
226};
227
228MODULE_DEVICE_TABLE(pnp, device_ids);
229
a8b77430
DS
230static int ni_isapnp_find_board(struct pnp_dev **dev)
231{
232 struct pnp_dev *isapnp_dev = NULL;
233 int i;
234
ca4d4aa6 235 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
a8b77430 236 isapnp_dev = pnp_find_dev(NULL,
0a85b6f0
MT
237 ISAPNP_VENDOR('N', 'I', 'C'),
238 ISAPNP_FUNCTION(ni_boards[i].
239 isapnp_id), NULL);
a8b77430 240
77ba71f6 241 if (!isapnp_dev || !isapnp_dev->card)
a8b77430
DS
242 continue;
243
ee68d168 244 if (pnp_device_attach(isapnp_dev) < 0)
a8b77430 245 continue;
ee68d168 246
a8b77430
DS
247 if (pnp_activate_dev(isapnp_dev) < 0) {
248 pnp_device_detach(isapnp_dev);
249 return -EAGAIN;
250 }
ee68d168
HS
251
252 if (!pnp_port_valid(isapnp_dev, 0) ||
253 !pnp_irq_valid(isapnp_dev, 0)) {
a8b77430 254 pnp_device_detach(isapnp_dev);
a8b77430
DS
255 return -ENOMEM;
256 }
257 break;
258 }
ca4d4aa6 259 if (i == ARRAY_SIZE(ni_boards))
a8b77430
DS
260 return -ENODEV;
261 *dev = isapnp_dev;
262 return 0;
263}
264
1ee02fe1 265static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev)
5aac8294
HS
266{
267 int device_id = ni_read_eeprom(dev, 511);
268 int i;
269
ca4d4aa6 270 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
1ee02fe1
HS
271 const struct ni_board_struct *board = &ni_boards[i];
272
273 if (board->device_id == device_id)
274 return board;
5aac8294
HS
275 }
276 if (device_id == 255)
b252ebfc 277 dev_err(dev->class_dev, "can't find board\n");
da91a80a 278 else if (device_id == 0)
b252ebfc
HS
279 dev_err(dev->class_dev,
280 "EEPROM read error (?) or device not found\n");
da91a80a 281 else
b252ebfc
HS
282 dev_err(dev->class_dev,
283 "unknown device ID %d -- contact author\n", device_id);
5aac8294 284
1ee02fe1 285 return NULL;
5aac8294
HS
286}
287
0a85b6f0
MT
288static int ni_atmio_attach(struct comedi_device *dev,
289 struct comedi_devconfig *it)
a8b77430 290{
1ee02fe1 291 const struct ni_board_struct *board;
a8b77430
DS
292 struct pnp_dev *isapnp_dev;
293 int ret;
294 unsigned long iobase;
a8b77430
DS
295 unsigned int irq;
296
c3744138 297 ret = ni_alloc_private(dev);
0e05c552 298 if (ret)
a8b77430 299 return ret;
c3744138 300
a8b77430
DS
301 iobase = it->options[0];
302 irq = it->options[1];
303 isapnp_dev = NULL;
304 if (iobase == 0) {
305 ret = ni_isapnp_find_board(&isapnp_dev);
306 if (ret < 0)
307 return ret;
308
309 iobase = pnp_port_start(isapnp_dev, 0);
310 irq = pnp_irq(isapnp_dev, 0);
ffd0a782 311 comedi_set_hw_dev(dev, &isapnp_dev->dev);
a8b77430
DS
312 }
313
551d7939 314 ret = comedi_request_region(dev, iobase, 0x20);
b1bc9276
HS
315 if (ret)
316 return ret;
a8b77430 317
1ee02fe1
HS
318 board = ni_atmio_probe(dev);
319 if (!board)
320 return -ENODEV;
321 dev->board_ptr = board;
322 dev->board_name = board->name;
a8b77430
DS
323
324 /* irq stuff */
325
326 if (irq != 0) {
221fa08c 327 if (irq > 15 || ni_irqpin[irq] == -1)
a8b77430 328 return -EINVAL;
32d878a2 329 ret = request_irq(irq, ni_E_interrupt, 0,
71e06874 330 dev->board_name, dev);
221fa08c 331 if (ret < 0)
a8b77430 332 return -EINVAL;
a8b77430
DS
333 dev->irq = irq;
334 }
335
336 /* generic E series stuff in ni_mio_common.c */
337
1fa955ba 338 ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
bc2955dd 339 if (ret < 0)
a8b77430 340 return ret;
bc2955dd 341
a8b77430
DS
342 return 0;
343}
344
484ecc95 345static void ni_atmio_detach(struct comedi_device *dev)
a8b77430 346{
ffd0a782 347 struct pnp_dev *isapnp_dev;
0e05c552 348
5aac8294 349 mio_common_detach(dev);
a32c6d00 350 comedi_legacy_detach(dev);
ffd0a782
HS
351
352 isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
353 if (isapnp_dev)
354 pnp_device_detach(isapnp_dev);
a8b77430 355}
5aac8294
HS
356
357static struct comedi_driver ni_atmio_driver = {
358 .driver_name = "ni_atmio",
359 .module = THIS_MODULE,
360 .attach = ni_atmio_attach,
361 .detach = ni_atmio_detach,
362};
363module_comedi_driver(ni_atmio_driver);
This page took 0.74386 seconds and 5 git commands to generate.