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