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