staging: comedi: ni_mio_common drivers: remove NI_E_IRQ_FLAGS defines
[cascardo/linux.git] / drivers / staging / comedi / drivers / ni_atmio.c
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.
17 */
18 /*
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
29 will automatically probe for a supported board if the
30 I/O base is left unspecified with comedi_config.
31 However, many of
32 the isapnp id numbers are unknown.  If your board is not
33 recognized, 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
36 id numbers for your board can be added to the driver.
37
38 Otherwise, you can use the isapnptools package to configure
39 your board.  Use isapnp to
40 configure the I/O base and IRQ for the board, and then pass
41 the same values as
42 parameters in comedi_config.  A sample isapnp.conf file is included
43 in the etc/ directory of Comedilib.
44
45 Comedilib includes a utility to autocalibrate these boards.  The
46 boards seem to boot into a state where the all calibration DACs
47 are at one extreme of their range, thus the default calibration
48 is terrible.  Calibration at boot is strongly encouraged.
49
50 To use the extended digital I/O on some of the boards, enable the
51 8255 driver when configuring the Comedi source tree.
52
53 External triggering is supported for some events.  The channel index
54 (scan_begin_arg, etc.) maps to PFI0 - PFI9.
55
56 Some of the more esoteric triggering possibilities of these boards
57 are 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
92 #include <linux/module.h>
93 #include <linux/interrupt.h>
94 #include "../comedidev.h"
95
96 #include <linux/isapnp.h>
97
98 #include "ni_stc.h"
99 #include "8255.h"
100
101 #define ATMIO 1
102 #undef PCIMIO
103
104 /*
105  *  AT specific setup
106  */
107
108 #define NI_SIZE 0x20
109
110 static const struct ni_board_struct ni_boards[] = {
111         {.device_id = 44,
112          .isapnp_id = 0x0000,   /* XXX unknown */
113          .name = "at-mio-16e-1",
114          .n_adchan = 16,
115          .adbits = 12,
116          .ai_fifo_depth = 8192,
117          .alwaysdither = 0,
118          .gainlkup = ai_gain_16,
119          .ai_speed = 800,
120          .n_aochan = 2,
121          .aobits = 12,
122          .ao_fifo_depth = 2048,
123          .ao_range_table = &range_ni_E_ao_ext,
124          .ao_unipolar = 1,
125          .ao_speed = 1000,
126          .has_8255 = 0,
127          .num_p0_dio_channels = 8,
128          .caldac = {mb88341},
129          },
130         {.device_id = 25,
131          .isapnp_id = 0x1900,
132          .name = "at-mio-16e-2",
133          .n_adchan = 16,
134          .adbits = 12,
135          .ai_fifo_depth = 2048,
136          .alwaysdither = 0,
137          .gainlkup = ai_gain_16,
138          .ai_speed = 2000,
139          .n_aochan = 2,
140          .aobits = 12,
141          .ao_fifo_depth = 2048,
142          .ao_range_table = &range_ni_E_ao_ext,
143          .ao_unipolar = 1,
144          .ao_speed = 1000,
145          .has_8255 = 0,
146          .num_p0_dio_channels = 8,
147          .caldac = {mb88341},
148          },
149         {.device_id = 36,
150          .isapnp_id = 0x2400,
151          .name = "at-mio-16e-10",
152          .n_adchan = 16,
153          .adbits = 12,
154          .ai_fifo_depth = 512,
155          .alwaysdither = 0,
156          .gainlkup = ai_gain_16,
157          .ai_speed = 10000,
158          .n_aochan = 2,
159          .aobits = 12,
160          .ao_fifo_depth = 0,
161          .ao_range_table = &range_ni_E_ao_ext,
162          .ao_unipolar = 1,
163          .ao_speed = 10000,
164          .num_p0_dio_channels = 8,
165          .caldac = {ad8804_debug},
166          .has_8255 = 0,
167          },
168         {.device_id = 37,
169          .isapnp_id = 0x2500,
170          .name = "at-mio-16de-10",
171          .n_adchan = 16,
172          .adbits = 12,
173          .ai_fifo_depth = 512,
174          .alwaysdither = 0,
175          .gainlkup = ai_gain_16,
176          .ai_speed = 10000,
177          .n_aochan = 2,
178          .aobits = 12,
179          .ao_fifo_depth = 0,
180          .ao_range_table = &range_ni_E_ao_ext,
181          .ao_unipolar = 1,
182          .ao_speed = 10000,
183          .num_p0_dio_channels = 8,
184          .caldac = {ad8804_debug},
185          .has_8255 = 1,
186          },
187         {.device_id = 38,
188          .isapnp_id = 0x2600,
189          .name = "at-mio-64e-3",
190          .n_adchan = 64,
191          .adbits = 12,
192          .ai_fifo_depth = 2048,
193          .alwaysdither = 0,
194          .gainlkup = ai_gain_16,
195          .ai_speed = 2000,
196          .n_aochan = 2,
197          .aobits = 12,
198          .ao_fifo_depth = 2048,
199          .ao_range_table = &range_ni_E_ao_ext,
200          .ao_unipolar = 1,
201          .ao_speed = 1000,
202          .has_8255 = 0,
203          .num_p0_dio_channels = 8,
204          .caldac = {ad8804_debug},
205          },
206         {.device_id = 39,
207          .isapnp_id = 0x2700,
208          .name = "at-mio-16xe-50",
209          .n_adchan = 16,
210          .adbits = 16,
211          .ai_fifo_depth = 512,
212          .alwaysdither = 1,
213          .gainlkup = ai_gain_8,
214          .ai_speed = 50000,
215          .n_aochan = 2,
216          .aobits = 12,
217          .ao_fifo_depth = 0,
218          .ao_range_table = &range_bipolar10,
219          .ao_unipolar = 0,
220          .ao_speed = 50000,
221          .num_p0_dio_channels = 8,
222          .caldac = {dac8800, dac8043},
223          .has_8255 = 0,
224          },
225         {.device_id = 50,
226          .isapnp_id = 0x0000,   /* XXX unknown */
227          .name = "at-mio-16xe-10",
228          .n_adchan = 16,
229          .adbits = 16,
230          .ai_fifo_depth = 512,
231          .alwaysdither = 1,
232          .gainlkup = ai_gain_14,
233          .ai_speed = 10000,
234          .n_aochan = 2,
235          .aobits = 16,
236          .ao_fifo_depth = 2048,
237          .ao_range_table = &range_ni_E_ao_ext,
238          .ao_unipolar = 1,
239          .ao_speed = 1000,
240          .num_p0_dio_channels = 8,
241          .caldac = {dac8800, dac8043, ad8522},
242          .has_8255 = 0,
243          },
244         {.device_id = 51,
245          .isapnp_id = 0x0000,   /* XXX unknown */
246          .name = "at-ai-16xe-10",
247          .n_adchan = 16,
248          .adbits = 16,
249          .ai_fifo_depth = 512,
250          .alwaysdither = 1,     /* unknown */
251          .gainlkup = ai_gain_14,
252          .ai_speed = 10000,
253          .n_aochan = 0,
254          .aobits = 0,
255          .ao_fifo_depth = 0,
256          .ao_unipolar = 0,
257          .num_p0_dio_channels = 8,
258          .caldac = {dac8800, dac8043, ad8522},
259          .has_8255 = 0,
260          }
261 };
262
263 static const int ni_irqpin[] = {
264         -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
265 };
266
267 #define IRQ_POLARITY 0
268
269 #include "ni_mio_common.c"
270
271 static struct pnp_device_id device_ids[] = {
272         {.id = "NIC1900", .driver_data = 0},
273         {.id = "NIC2400", .driver_data = 0},
274         {.id = "NIC2500", .driver_data = 0},
275         {.id = "NIC2600", .driver_data = 0},
276         {.id = "NIC2700", .driver_data = 0},
277         {.id = ""}
278 };
279
280 MODULE_DEVICE_TABLE(pnp, device_ids);
281
282 static int ni_isapnp_find_board(struct pnp_dev **dev)
283 {
284         struct pnp_dev *isapnp_dev = NULL;
285         int i;
286
287         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
288                 isapnp_dev = pnp_find_dev(NULL,
289                                           ISAPNP_VENDOR('N', 'I', 'C'),
290                                           ISAPNP_FUNCTION(ni_boards[i].
291                                                           isapnp_id), NULL);
292
293                 if (isapnp_dev == NULL || isapnp_dev->card == NULL)
294                         continue;
295
296                 if (pnp_device_attach(isapnp_dev) < 0) {
297                         printk
298                          ("ni_atmio: %s found but already active, skipping.\n",
299                           ni_boards[i].name);
300                         continue;
301                 }
302                 if (pnp_activate_dev(isapnp_dev) < 0) {
303                         pnp_device_detach(isapnp_dev);
304                         return -EAGAIN;
305                 }
306                 if (!pnp_port_valid(isapnp_dev, 0)
307                     || !pnp_irq_valid(isapnp_dev, 0)) {
308                         pnp_device_detach(isapnp_dev);
309                         printk("ni_atmio: pnp invalid port or irq, aborting\n");
310                         return -ENOMEM;
311                 }
312                 break;
313         }
314         if (i == ARRAY_SIZE(ni_boards))
315                 return -ENODEV;
316         *dev = isapnp_dev;
317         return 0;
318 }
319
320 static int ni_getboardtype(struct comedi_device *dev)
321 {
322         int device_id = ni_read_eeprom(dev, 511);
323         int i;
324
325         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
326                 if (ni_boards[i].device_id == device_id)
327                         return i;
328
329         }
330         if (device_id == 255)
331                 printk(" can't find board\n");
332          else if (device_id == 0)
333                 printk(" EEPROM read error (?) or device not found\n");
334          else
335                 printk(" unknown device ID %d -- contact author\n", device_id);
336
337         return -1;
338 }
339
340 static int ni_atmio_attach(struct comedi_device *dev,
341                            struct comedi_devconfig *it)
342 {
343         const struct ni_board_struct *boardtype;
344         struct ni_private *devpriv;
345         struct pnp_dev *isapnp_dev;
346         int ret;
347         unsigned long iobase;
348         int board;
349         unsigned int irq;
350
351         ret = ni_alloc_private(dev);
352         if (ret)
353                 return ret;
354         devpriv = dev->private;
355
356         iobase = it->options[0];
357         irq = it->options[1];
358         isapnp_dev = NULL;
359         if (iobase == 0) {
360                 ret = ni_isapnp_find_board(&isapnp_dev);
361                 if (ret < 0)
362                         return ret;
363
364                 iobase = pnp_port_start(isapnp_dev, 0);
365                 irq = pnp_irq(isapnp_dev, 0);
366                 comedi_set_hw_dev(dev, &isapnp_dev->dev);
367         }
368
369         ret = comedi_request_region(dev, iobase, NI_SIZE);
370         if (ret)
371                 return ret;
372
373         /* get board type */
374
375         board = ni_getboardtype(dev);
376         if (board < 0)
377                 return -EIO;
378
379         dev->board_ptr = ni_boards + board;
380         boardtype = comedi_board(dev);
381
382         printk(" %s", boardtype->name);
383         dev->board_name = boardtype->name;
384
385         /* irq stuff */
386
387         if (irq != 0) {
388                 if (irq > 15 || ni_irqpin[irq] == -1) {
389                         printk(" invalid irq %u\n", irq);
390                         return -EINVAL;
391                 }
392                 printk(" ( irq = %u )", irq);
393                 ret = request_irq(irq, ni_E_interrupt, 0,
394                                   "ni_atmio", dev);
395
396                 if (ret < 0) {
397                         printk(" irq not available\n");
398                         return -EINVAL;
399                 }
400                 dev->irq = irq;
401         }
402
403         /* generic E series stuff in ni_mio_common.c */
404
405         ret = ni_E_init(dev, ni_irqpin[dev->irq]);
406         if (ret < 0)
407                 return ret;
408
409
410         return 0;
411 }
412
413 static void ni_atmio_detach(struct comedi_device *dev)
414 {
415         struct pnp_dev *isapnp_dev;
416
417         mio_common_detach(dev);
418         comedi_legacy_detach(dev);
419
420         isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
421         if (isapnp_dev)
422                 pnp_device_detach(isapnp_dev);
423 }
424
425 static struct comedi_driver ni_atmio_driver = {
426         .driver_name    = "ni_atmio",
427         .module         = THIS_MODULE,
428         .attach         = ni_atmio_attach,
429         .detach         = ni_atmio_detach,
430 };
431 module_comedi_driver(ni_atmio_driver);