2 * Comedi driver for NI AT-MIO E series cards
4 * COMEDI - Linux Control and Measurement Device Interface
5 * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
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.
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.
20 * Description: National Instruments AT-MIO-E series
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
26 * Updated: Thu May 1 20:03:02 CDT 2003
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.
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.
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.
45 * To use the extended digital I/O on some of the boards, enable the
46 * 8255 driver when configuring the Comedi source tree.
48 * External triggering is supported for some events. The channel index
49 * (scan_begin_arg, etc.) maps to PFI0 - PFI9.
51 * Some of the more esoteric triggering possibilities of these boards are
56 * The real guts of the driver is in ni_mio_common.c, which is included
57 * both here and in ni_pcimio.c
59 * Interrupt support added by Truxton Fulton <trux@truxton.com>
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
66 * Other possibly relevant info:
67 * 320517c.pdf User manual (obsolete)
68 * 320517f.pdf User manual (new)
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
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.
83 #include <linux/module.h>
84 #include <linux/interrupt.h>
85 #include "../comedidev.h"
87 #include <linux/isapnp.h>
92 /* AT specific setup */
93 static const struct ni_board_struct ni_boards[] = {
95 .name = "at-mio-16e-1",
97 .isapnp_id = 0x0000, /* XXX unknown */
100 .ai_fifo_depth = 8192,
101 .gainlkup = ai_gain_16,
104 .ao_maxdata = 0x0fff,
105 .ao_fifo_depth = 2048,
106 .ao_range_table = &range_ni_E_ao_ext,
108 .caldac = { mb88341 },
110 .name = "at-mio-16e-2",
114 .ai_maxdata = 0x0fff,
115 .ai_fifo_depth = 2048,
116 .gainlkup = ai_gain_16,
119 .ao_maxdata = 0x0fff,
120 .ao_fifo_depth = 2048,
121 .ao_range_table = &range_ni_E_ao_ext,
123 .caldac = { mb88341 },
125 .name = "at-mio-16e-10",
129 .ai_maxdata = 0x0fff,
130 .ai_fifo_depth = 512,
131 .gainlkup = ai_gain_16,
134 .ao_maxdata = 0x0fff,
135 .ao_range_table = &range_ni_E_ao_ext,
137 .caldac = { ad8804_debug },
139 .name = "at-mio-16de-10",
143 .ai_maxdata = 0x0fff,
144 .ai_fifo_depth = 512,
145 .gainlkup = ai_gain_16,
148 .ao_maxdata = 0x0fff,
149 .ao_range_table = &range_ni_E_ao_ext,
151 .caldac = { ad8804_debug },
154 .name = "at-mio-64e-3",
158 .ai_maxdata = 0x0fff,
159 .ai_fifo_depth = 2048,
160 .gainlkup = ai_gain_16,
163 .ao_maxdata = 0x0fff,
164 .ao_fifo_depth = 2048,
165 .ao_range_table = &range_ni_E_ao_ext,
167 .caldac = { ad8804_debug },
169 .name = "at-mio-16xe-50",
173 .ai_maxdata = 0xffff,
174 .ai_fifo_depth = 512,
176 .gainlkup = ai_gain_8,
179 .ao_maxdata = 0x0fff,
180 .ao_range_table = &range_bipolar10,
182 .caldac = { dac8800, dac8043 },
184 .name = "at-mio-16xe-10",
186 .isapnp_id = 0x0000, /* XXX unknown */
188 .ai_maxdata = 0xffff,
189 .ai_fifo_depth = 512,
191 .gainlkup = ai_gain_14,
194 .ao_maxdata = 0xffff,
195 .ao_fifo_depth = 2048,
196 .ao_range_table = &range_ni_E_ao_ext,
198 .caldac = { dac8800, dac8043, ad8522 },
200 .name = "at-ai-16xe-10",
202 .isapnp_id = 0x0000, /* XXX unknown */
204 .ai_maxdata = 0xffff,
205 .ai_fifo_depth = 512,
206 .alwaysdither = 1, /* unknown */
207 .gainlkup = ai_gain_14,
209 .caldac = { dac8800, dac8043, ad8522 },
213 static const int ni_irqpin[] = {
214 -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
217 #include "ni_mio_common.c"
219 static const struct pnp_device_id device_ids[] = {
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},
228 MODULE_DEVICE_TABLE(pnp, device_ids);
230 static int ni_isapnp_find_board(struct pnp_dev **dev)
232 struct pnp_dev *isapnp_dev = NULL;
235 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
236 isapnp_dev = pnp_find_dev(NULL,
237 ISAPNP_VENDOR('N', 'I', 'C'),
238 ISAPNP_FUNCTION(ni_boards[i].
241 if (!isapnp_dev || !isapnp_dev->card)
244 if (pnp_device_attach(isapnp_dev) < 0)
247 if (pnp_activate_dev(isapnp_dev) < 0) {
248 pnp_device_detach(isapnp_dev);
252 if (!pnp_port_valid(isapnp_dev, 0) ||
253 !pnp_irq_valid(isapnp_dev, 0)) {
254 pnp_device_detach(isapnp_dev);
259 if (i == ARRAY_SIZE(ni_boards))
265 static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev)
267 int device_id = ni_read_eeprom(dev, 511);
270 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
271 const struct ni_board_struct *board = &ni_boards[i];
273 if (board->device_id == device_id)
276 if (device_id == 255)
277 dev_err(dev->class_dev, "can't find board\n");
278 else if (device_id == 0)
279 dev_err(dev->class_dev,
280 "EEPROM read error (?) or device not found\n");
282 dev_err(dev->class_dev,
283 "unknown device ID %d -- contact author\n", device_id);
288 static int ni_atmio_attach(struct comedi_device *dev,
289 struct comedi_devconfig *it)
291 const struct ni_board_struct *board;
292 struct pnp_dev *isapnp_dev;
294 unsigned long iobase;
297 ret = ni_alloc_private(dev);
301 iobase = it->options[0];
302 irq = it->options[1];
305 ret = ni_isapnp_find_board(&isapnp_dev);
309 iobase = pnp_port_start(isapnp_dev, 0);
310 irq = pnp_irq(isapnp_dev, 0);
311 comedi_set_hw_dev(dev, &isapnp_dev->dev);
314 ret = comedi_request_region(dev, iobase, 0x20);
318 board = ni_atmio_probe(dev);
321 dev->board_ptr = board;
322 dev->board_name = board->name;
327 if (irq > 15 || ni_irqpin[irq] == -1)
329 ret = request_irq(irq, ni_E_interrupt, 0,
330 dev->board_name, dev);
336 /* generic E series stuff in ni_mio_common.c */
338 ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
345 static void ni_atmio_detach(struct comedi_device *dev)
347 struct pnp_dev *isapnp_dev;
349 mio_common_detach(dev);
350 comedi_legacy_detach(dev);
352 isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
354 pnp_device_detach(isapnp_dev);
357 static 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,
363 module_comedi_driver(ni_atmio_driver);