This source file includes following definitions.
- ni_isapnp_find_board
- ni_atmio_probe
- ni_atmio_attach
- ni_atmio_detach
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 #include <linux/module.h>
75 #include <linux/interrupt.h>
76 #include "../comedidev.h"
77
78 #include <linux/isapnp.h>
79
80 #include "ni_stc.h"
81 #include "8255.h"
82
83
84 static const struct ni_board_struct ni_boards[] = {
85 {
86 .name = "at-mio-16e-1",
87 .device_id = 44,
88 .isapnp_id = 0x0000,
89 .n_adchan = 16,
90 .ai_maxdata = 0x0fff,
91 .ai_fifo_depth = 8192,
92 .gainlkup = ai_gain_16,
93 .ai_speed = 800,
94 .n_aochan = 2,
95 .ao_maxdata = 0x0fff,
96 .ao_fifo_depth = 2048,
97 .ao_range_table = &range_ni_E_ao_ext,
98 .ao_speed = 1000,
99 .caldac = { mb88341 },
100 }, {
101 .name = "at-mio-16e-2",
102 .device_id = 25,
103 .isapnp_id = 0x1900,
104 .n_adchan = 16,
105 .ai_maxdata = 0x0fff,
106 .ai_fifo_depth = 2048,
107 .gainlkup = ai_gain_16,
108 .ai_speed = 2000,
109 .n_aochan = 2,
110 .ao_maxdata = 0x0fff,
111 .ao_fifo_depth = 2048,
112 .ao_range_table = &range_ni_E_ao_ext,
113 .ao_speed = 1000,
114 .caldac = { mb88341 },
115 }, {
116 .name = "at-mio-16e-10",
117 .device_id = 36,
118 .isapnp_id = 0x2400,
119 .n_adchan = 16,
120 .ai_maxdata = 0x0fff,
121 .ai_fifo_depth = 512,
122 .gainlkup = ai_gain_16,
123 .ai_speed = 10000,
124 .n_aochan = 2,
125 .ao_maxdata = 0x0fff,
126 .ao_range_table = &range_ni_E_ao_ext,
127 .ao_speed = 10000,
128 .caldac = { ad8804_debug },
129 }, {
130 .name = "at-mio-16de-10",
131 .device_id = 37,
132 .isapnp_id = 0x2500,
133 .n_adchan = 16,
134 .ai_maxdata = 0x0fff,
135 .ai_fifo_depth = 512,
136 .gainlkup = ai_gain_16,
137 .ai_speed = 10000,
138 .n_aochan = 2,
139 .ao_maxdata = 0x0fff,
140 .ao_range_table = &range_ni_E_ao_ext,
141 .ao_speed = 10000,
142 .caldac = { ad8804_debug },
143 .has_8255 = 1,
144 }, {
145 .name = "at-mio-64e-3",
146 .device_id = 38,
147 .isapnp_id = 0x2600,
148 .n_adchan = 64,
149 .ai_maxdata = 0x0fff,
150 .ai_fifo_depth = 2048,
151 .gainlkup = ai_gain_16,
152 .ai_speed = 2000,
153 .n_aochan = 2,
154 .ao_maxdata = 0x0fff,
155 .ao_fifo_depth = 2048,
156 .ao_range_table = &range_ni_E_ao_ext,
157 .ao_speed = 1000,
158 .caldac = { ad8804_debug },
159 }, {
160 .name = "at-mio-16xe-50",
161 .device_id = 39,
162 .isapnp_id = 0x2700,
163 .n_adchan = 16,
164 .ai_maxdata = 0xffff,
165 .ai_fifo_depth = 512,
166 .alwaysdither = 1,
167 .gainlkup = ai_gain_8,
168 .ai_speed = 50000,
169 .n_aochan = 2,
170 .ao_maxdata = 0x0fff,
171 .ao_range_table = &range_bipolar10,
172 .ao_speed = 50000,
173 .caldac = { dac8800, dac8043 },
174 }, {
175 .name = "at-mio-16xe-10",
176 .device_id = 50,
177 .isapnp_id = 0x0000,
178 .n_adchan = 16,
179 .ai_maxdata = 0xffff,
180 .ai_fifo_depth = 512,
181 .alwaysdither = 1,
182 .gainlkup = ai_gain_14,
183 .ai_speed = 10000,
184 .n_aochan = 2,
185 .ao_maxdata = 0xffff,
186 .ao_fifo_depth = 2048,
187 .ao_range_table = &range_ni_E_ao_ext,
188 .ao_speed = 1000,
189 .caldac = { dac8800, dac8043, ad8522 },
190 }, {
191 .name = "at-ai-16xe-10",
192 .device_id = 51,
193 .isapnp_id = 0x0000,
194 .n_adchan = 16,
195 .ai_maxdata = 0xffff,
196 .ai_fifo_depth = 512,
197 .alwaysdither = 1,
198 .gainlkup = ai_gain_14,
199 .ai_speed = 10000,
200 .caldac = { dac8800, dac8043, ad8522 },
201 },
202 };
203
204 static const int ni_irqpin[] = {
205 -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
206 };
207
208 #include "ni_mio_common.c"
209
210 static const struct pnp_device_id device_ids[] = {
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},
216 {.id = ""}
217 };
218
219 MODULE_DEVICE_TABLE(pnp, device_ids);
220
221 static int ni_isapnp_find_board(struct pnp_dev **dev)
222 {
223 struct pnp_dev *isapnp_dev = NULL;
224 int i;
225
226 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
227 isapnp_dev =
228 pnp_find_dev(NULL,
229 ISAPNP_VENDOR('N', 'I', 'C'),
230 ISAPNP_FUNCTION(ni_boards[i].isapnp_id),
231 NULL);
232
233 if (!isapnp_dev || !isapnp_dev->card)
234 continue;
235
236 if (pnp_device_attach(isapnp_dev) < 0)
237 continue;
238
239 if (pnp_activate_dev(isapnp_dev) < 0) {
240 pnp_device_detach(isapnp_dev);
241 return -EAGAIN;
242 }
243
244 if (!pnp_port_valid(isapnp_dev, 0) ||
245 !pnp_irq_valid(isapnp_dev, 0)) {
246 pnp_device_detach(isapnp_dev);
247 return -ENOMEM;
248 }
249 break;
250 }
251 if (i == ARRAY_SIZE(ni_boards))
252 return -ENODEV;
253 *dev = isapnp_dev;
254 return 0;
255 }
256
257 static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev)
258 {
259 int device_id = ni_read_eeprom(dev, 511);
260 int i;
261
262 for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
263 const struct ni_board_struct *board = &ni_boards[i];
264
265 if (board->device_id == device_id)
266 return board;
267 }
268 if (device_id == 255)
269 dev_err(dev->class_dev, "can't find board\n");
270 else if (device_id == 0)
271 dev_err(dev->class_dev,
272 "EEPROM read error (?) or device not found\n");
273 else
274 dev_err(dev->class_dev,
275 "unknown device ID %d -- contact author\n", device_id);
276
277 return NULL;
278 }
279
280 static int ni_atmio_attach(struct comedi_device *dev,
281 struct comedi_devconfig *it)
282 {
283 const struct ni_board_struct *board;
284 struct pnp_dev *isapnp_dev;
285 int ret;
286 unsigned long iobase;
287 unsigned int irq;
288
289 ret = ni_alloc_private(dev);
290 if (ret)
291 return ret;
292
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);
303 comedi_set_hw_dev(dev, &isapnp_dev->dev);
304 }
305
306 ret = comedi_request_region(dev, iobase, 0x20);
307 if (ret)
308 return ret;
309
310 board = ni_atmio_probe(dev);
311 if (!board)
312 return -ENODEV;
313 dev->board_ptr = board;
314 dev->board_name = board->name;
315
316
317
318 if (irq != 0) {
319 if (irq > 15 || ni_irqpin[irq] == -1)
320 return -EINVAL;
321 ret = request_irq(irq, ni_E_interrupt, 0,
322 dev->board_name, dev);
323 if (ret < 0)
324 return -EINVAL;
325 dev->irq = irq;
326 }
327
328
329
330 ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
331 if (ret < 0)
332 return ret;
333
334 return 0;
335 }
336
337 static void ni_atmio_detach(struct comedi_device *dev)
338 {
339 struct pnp_dev *isapnp_dev;
340
341 mio_common_detach(dev);
342 comedi_legacy_detach(dev);
343
344 isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
345 if (isapnp_dev)
346 pnp_device_detach(isapnp_dev);
347 }
348
349 static 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 };
355 module_comedi_driver(ni_atmio_driver);
356
357 MODULE_AUTHOR("Comedi http://www.comedi.org");
358 MODULE_DESCRIPTION("Comedi low-level driver");
359 MODULE_LICENSE("GPL");
360