staging: comedi: ni_atmio: remove NI_SIZE define
[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 static const struct ni_board_struct ni_boards[] = {
109         {.device_id = 44,
110          .isapnp_id = 0x0000,   /* XXX unknown */
111          .name = "at-mio-16e-1",
112          .n_adchan = 16,
113          .adbits = 12,
114          .ai_fifo_depth = 8192,
115          .gainlkup = ai_gain_16,
116          .ai_speed = 800,
117          .n_aochan = 2,
118          .aobits = 12,
119          .ao_fifo_depth = 2048,
120          .ao_range_table = &range_ni_E_ao_ext,
121          .ao_unipolar = 1,
122          .ao_speed = 1000,
123          .num_p0_dio_channels = 8,
124          .caldac = {mb88341},
125          },
126         {.device_id = 25,
127          .isapnp_id = 0x1900,
128          .name = "at-mio-16e-2",
129          .n_adchan = 16,
130          .adbits = 12,
131          .ai_fifo_depth = 2048,
132          .gainlkup = ai_gain_16,
133          .ai_speed = 2000,
134          .n_aochan = 2,
135          .aobits = 12,
136          .ao_fifo_depth = 2048,
137          .ao_range_table = &range_ni_E_ao_ext,
138          .ao_unipolar = 1,
139          .ao_speed = 1000,
140          .num_p0_dio_channels = 8,
141          .caldac = {mb88341},
142          },
143         {.device_id = 36,
144          .isapnp_id = 0x2400,
145          .name = "at-mio-16e-10",
146          .n_adchan = 16,
147          .adbits = 12,
148          .ai_fifo_depth = 512,
149          .gainlkup = ai_gain_16,
150          .ai_speed = 10000,
151          .n_aochan = 2,
152          .aobits = 12,
153          .ao_range_table = &range_ni_E_ao_ext,
154          .ao_unipolar = 1,
155          .ao_speed = 10000,
156          .num_p0_dio_channels = 8,
157          .caldac = {ad8804_debug},
158          },
159         {.device_id = 37,
160          .isapnp_id = 0x2500,
161          .name = "at-mio-16de-10",
162          .n_adchan = 16,
163          .adbits = 12,
164          .ai_fifo_depth = 512,
165          .gainlkup = ai_gain_16,
166          .ai_speed = 10000,
167          .n_aochan = 2,
168          .aobits = 12,
169          .ao_range_table = &range_ni_E_ao_ext,
170          .ao_unipolar = 1,
171          .ao_speed = 10000,
172          .num_p0_dio_channels = 8,
173          .caldac = {ad8804_debug},
174          .has_8255 = 1,
175          },
176         {.device_id = 38,
177          .isapnp_id = 0x2600,
178          .name = "at-mio-64e-3",
179          .n_adchan = 64,
180          .adbits = 12,
181          .ai_fifo_depth = 2048,
182          .gainlkup = ai_gain_16,
183          .ai_speed = 2000,
184          .n_aochan = 2,
185          .aobits = 12,
186          .ao_fifo_depth = 2048,
187          .ao_range_table = &range_ni_E_ao_ext,
188          .ao_unipolar = 1,
189          .ao_speed = 1000,
190          .num_p0_dio_channels = 8,
191          .caldac = {ad8804_debug},
192          },
193         {.device_id = 39,
194          .isapnp_id = 0x2700,
195          .name = "at-mio-16xe-50",
196          .n_adchan = 16,
197          .adbits = 16,
198          .ai_fifo_depth = 512,
199          .alwaysdither = 1,
200          .gainlkup = ai_gain_8,
201          .ai_speed = 50000,
202          .n_aochan = 2,
203          .aobits = 12,
204          .ao_range_table = &range_bipolar10,
205          .ao_speed = 50000,
206          .num_p0_dio_channels = 8,
207          .caldac = {dac8800, dac8043},
208          },
209         {.device_id = 50,
210          .isapnp_id = 0x0000,   /* XXX unknown */
211          .name = "at-mio-16xe-10",
212          .n_adchan = 16,
213          .adbits = 16,
214          .ai_fifo_depth = 512,
215          .alwaysdither = 1,
216          .gainlkup = ai_gain_14,
217          .ai_speed = 10000,
218          .n_aochan = 2,
219          .aobits = 16,
220          .ao_fifo_depth = 2048,
221          .ao_range_table = &range_ni_E_ao_ext,
222          .ao_unipolar = 1,
223          .ao_speed = 1000,
224          .num_p0_dio_channels = 8,
225          .caldac = {dac8800, dac8043, ad8522},
226          },
227         {.device_id = 51,
228          .isapnp_id = 0x0000,   /* XXX unknown */
229          .name = "at-ai-16xe-10",
230          .n_adchan = 16,
231          .adbits = 16,
232          .ai_fifo_depth = 512,
233          .alwaysdither = 1,     /* unknown */
234          .gainlkup = ai_gain_14,
235          .ai_speed = 10000,
236          .num_p0_dio_channels = 8,
237          .caldac = {dac8800, dac8043, ad8522},
238          }
239 };
240
241 static const int ni_irqpin[] = {
242         -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
243 };
244
245 #include "ni_mio_common.c"
246
247 static struct pnp_device_id device_ids[] = {
248         {.id = "NIC1900", .driver_data = 0},
249         {.id = "NIC2400", .driver_data = 0},
250         {.id = "NIC2500", .driver_data = 0},
251         {.id = "NIC2600", .driver_data = 0},
252         {.id = "NIC2700", .driver_data = 0},
253         {.id = ""}
254 };
255
256 MODULE_DEVICE_TABLE(pnp, device_ids);
257
258 static int ni_isapnp_find_board(struct pnp_dev **dev)
259 {
260         struct pnp_dev *isapnp_dev = NULL;
261         int i;
262
263         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
264                 isapnp_dev = pnp_find_dev(NULL,
265                                           ISAPNP_VENDOR('N', 'I', 'C'),
266                                           ISAPNP_FUNCTION(ni_boards[i].
267                                                           isapnp_id), NULL);
268
269                 if (isapnp_dev == NULL || isapnp_dev->card == NULL)
270                         continue;
271
272                 if (pnp_device_attach(isapnp_dev) < 0) {
273                         printk
274                          ("ni_atmio: %s found but already active, skipping.\n",
275                           ni_boards[i].name);
276                         continue;
277                 }
278                 if (pnp_activate_dev(isapnp_dev) < 0) {
279                         pnp_device_detach(isapnp_dev);
280                         return -EAGAIN;
281                 }
282                 if (!pnp_port_valid(isapnp_dev, 0)
283                     || !pnp_irq_valid(isapnp_dev, 0)) {
284                         pnp_device_detach(isapnp_dev);
285                         printk("ni_atmio: pnp invalid port or irq, aborting\n");
286                         return -ENOMEM;
287                 }
288                 break;
289         }
290         if (i == ARRAY_SIZE(ni_boards))
291                 return -ENODEV;
292         *dev = isapnp_dev;
293         return 0;
294 }
295
296 static int ni_getboardtype(struct comedi_device *dev)
297 {
298         int device_id = ni_read_eeprom(dev, 511);
299         int i;
300
301         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
302                 if (ni_boards[i].device_id == device_id)
303                         return i;
304
305         }
306         if (device_id == 255)
307                 printk(" can't find board\n");
308          else if (device_id == 0)
309                 printk(" EEPROM read error (?) or device not found\n");
310          else
311                 printk(" unknown device ID %d -- contact author\n", device_id);
312
313         return -1;
314 }
315
316 static int ni_atmio_attach(struct comedi_device *dev,
317                            struct comedi_devconfig *it)
318 {
319         const struct ni_board_struct *boardtype;
320         struct ni_private *devpriv;
321         struct pnp_dev *isapnp_dev;
322         int ret;
323         unsigned long iobase;
324         int board;
325         unsigned int irq;
326
327         ret = ni_alloc_private(dev);
328         if (ret)
329                 return ret;
330         devpriv = dev->private;
331
332         iobase = it->options[0];
333         irq = it->options[1];
334         isapnp_dev = NULL;
335         if (iobase == 0) {
336                 ret = ni_isapnp_find_board(&isapnp_dev);
337                 if (ret < 0)
338                         return ret;
339
340                 iobase = pnp_port_start(isapnp_dev, 0);
341                 irq = pnp_irq(isapnp_dev, 0);
342                 comedi_set_hw_dev(dev, &isapnp_dev->dev);
343         }
344
345         ret = comedi_request_region(dev, iobase, 0x20);
346         if (ret)
347                 return ret;
348
349         /* get board type */
350
351         board = ni_getboardtype(dev);
352         if (board < 0)
353                 return -EIO;
354
355         dev->board_ptr = ni_boards + board;
356         boardtype = comedi_board(dev);
357
358         printk(" %s", boardtype->name);
359         dev->board_name = boardtype->name;
360
361         /* irq stuff */
362
363         if (irq != 0) {
364                 if (irq > 15 || ni_irqpin[irq] == -1) {
365                         printk(" invalid irq %u\n", irq);
366                         return -EINVAL;
367                 }
368                 printk(" ( irq = %u )", irq);
369                 ret = request_irq(irq, ni_E_interrupt, 0,
370                                   "ni_atmio", dev);
371
372                 if (ret < 0) {
373                         printk(" irq not available\n");
374                         return -EINVAL;
375                 }
376                 dev->irq = irq;
377         }
378
379         /* generic E series stuff in ni_mio_common.c */
380
381         ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
382         if (ret < 0)
383                 return ret;
384
385
386         return 0;
387 }
388
389 static void ni_atmio_detach(struct comedi_device *dev)
390 {
391         struct pnp_dev *isapnp_dev;
392
393         mio_common_detach(dev);
394         comedi_legacy_detach(dev);
395
396         isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
397         if (isapnp_dev)
398                 pnp_device_detach(isapnp_dev);
399 }
400
401 static struct comedi_driver ni_atmio_driver = {
402         .driver_name    = "ni_atmio",
403         .module         = THIS_MODULE,
404         .attach         = ni_atmio_attach,
405         .detach         = ni_atmio_detach,
406 };
407 module_comedi_driver(ni_atmio_driver);