Version:  2.0.40 2.2.26 2.4.37 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9

Linux/drivers/staging/comedi/drivers/ni_atmio.c

  1 /*
  2  * Comedi driver for NI AT-MIO E series cards
  3  *
  4  * COMEDI - Linux Control and Measurement Device Interface
  5  * Copyright (C) 1997-2001 David A. Schleef <ds@schleef.org>
  6  *
  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.
 11  *
 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.
 16  */
 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 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.
 34  *
 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.
 39  *
 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.
 44  *
 45  * To use the extended digital I/O on some of the boards, enable the
 46  * 8255 driver when configuring the Comedi source tree.
 47  *
 48  * External triggering is supported for some events. The channel index
 49  * (scan_begin_arg, etc.) maps to PFI0 - PFI9.
 50  *
 51  * Some of the more esoteric triggering possibilities of these boards are
 52  * not supported.
 53  */
 54 
 55 /*
 56  * The real guts of the driver is in ni_mio_common.c, which is included
 57  * both here and in ni_pcimio.c
 58  *
 59  * Interrupt support added by Truxton Fulton <trux@truxton.com>
 60  *
 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
 65  *
 66  * Other possibly relevant info:
 67  *      320517c.pdf  User manual (obsolete)
 68  *      320517f.pdf  User manual (new)
 69  *      320889a.pdf  delete
 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
 76  *
 77  * ISSUES:
 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.
 81  */
 82 
 83 #include <linux/module.h>
 84 #include <linux/interrupt.h>
 85 #include "../comedidev.h"
 86 
 87 #include <linux/isapnp.h>
 88 
 89 #include "ni_stc.h"
 90 #include "8255.h"
 91 
 92 /* AT specific setup */
 93 static const struct ni_board_struct ni_boards[] = {
 94         {
 95                 .name           = "at-mio-16e-1",
 96                 .device_id      = 44,
 97                 .isapnp_id      = 0x0000,       /* XXX unknown */
 98                 .n_adchan       = 16,
 99                 .ai_maxdata     = 0x0fff,
100                 .ai_fifo_depth  = 8192,
101                 .gainlkup       = ai_gain_16,
102                 .ai_speed       = 800,
103                 .n_aochan       = 2,
104                 .ao_maxdata     = 0x0fff,
105                 .ao_fifo_depth  = 2048,
106                 .ao_range_table = &range_ni_E_ao_ext,
107                 .ao_speed       = 1000,
108                 .caldac         = { mb88341 },
109         }, {
110                 .name           = "at-mio-16e-2",
111                 .device_id      = 25,
112                 .isapnp_id      = 0x1900,
113                 .n_adchan       = 16,
114                 .ai_maxdata     = 0x0fff,
115                 .ai_fifo_depth  = 2048,
116                 .gainlkup       = ai_gain_16,
117                 .ai_speed       = 2000,
118                 .n_aochan       = 2,
119                 .ao_maxdata     = 0x0fff,
120                 .ao_fifo_depth  = 2048,
121                 .ao_range_table = &range_ni_E_ao_ext,
122                 .ao_speed       = 1000,
123                 .caldac         = { mb88341 },
124         }, {
125                 .name           = "at-mio-16e-10",
126                 .device_id      = 36,
127                 .isapnp_id      = 0x2400,
128                 .n_adchan       = 16,
129                 .ai_maxdata     = 0x0fff,
130                 .ai_fifo_depth  = 512,
131                 .gainlkup       = ai_gain_16,
132                 .ai_speed       = 10000,
133                 .n_aochan       = 2,
134                 .ao_maxdata     = 0x0fff,
135                 .ao_range_table = &range_ni_E_ao_ext,
136                 .ao_speed       = 10000,
137                 .caldac         = { ad8804_debug },
138         }, {
139                 .name           = "at-mio-16de-10",
140                 .device_id      = 37,
141                 .isapnp_id      = 0x2500,
142                 .n_adchan       = 16,
143                 .ai_maxdata     = 0x0fff,
144                 .ai_fifo_depth  = 512,
145                 .gainlkup       = ai_gain_16,
146                 .ai_speed       = 10000,
147                 .n_aochan       = 2,
148                 .ao_maxdata     = 0x0fff,
149                 .ao_range_table = &range_ni_E_ao_ext,
150                 .ao_speed       = 10000,
151                 .caldac         = { ad8804_debug },
152                 .has_8255       = 1,
153         }, {
154                 .name           = "at-mio-64e-3",
155                 .device_id      = 38,
156                 .isapnp_id      = 0x2600,
157                 .n_adchan       = 64,
158                 .ai_maxdata     = 0x0fff,
159                 .ai_fifo_depth  = 2048,
160                 .gainlkup       = ai_gain_16,
161                 .ai_speed       = 2000,
162                 .n_aochan       = 2,
163                 .ao_maxdata     = 0x0fff,
164                 .ao_fifo_depth  = 2048,
165                 .ao_range_table = &range_ni_E_ao_ext,
166                 .ao_speed       = 1000,
167                 .caldac         = { ad8804_debug },
168         }, {
169                 .name           = "at-mio-16xe-50",
170                 .device_id      = 39,
171                 .isapnp_id      = 0x2700,
172                 .n_adchan       = 16,
173                 .ai_maxdata     = 0xffff,
174                 .ai_fifo_depth  = 512,
175                 .alwaysdither   = 1,
176                 .gainlkup       = ai_gain_8,
177                 .ai_speed       = 50000,
178                 .n_aochan       = 2,
179                 .ao_maxdata     = 0x0fff,
180                 .ao_range_table = &range_bipolar10,
181                 .ao_speed       = 50000,
182                 .caldac         = { dac8800, dac8043 },
183         }, {
184                 .name           = "at-mio-16xe-10",
185                 .device_id      = 50,
186                 .isapnp_id      = 0x0000,       /* XXX unknown */
187                 .n_adchan       = 16,
188                 .ai_maxdata     = 0xffff,
189                 .ai_fifo_depth  = 512,
190                 .alwaysdither   = 1,
191                 .gainlkup       = ai_gain_14,
192                 .ai_speed       = 10000,
193                 .n_aochan       = 2,
194                 .ao_maxdata     = 0xffff,
195                 .ao_fifo_depth  = 2048,
196                 .ao_range_table = &range_ni_E_ao_ext,
197                 .ao_speed       = 1000,
198                 .caldac         = { dac8800, dac8043, ad8522 },
199         }, {
200                 .name           = "at-ai-16xe-10",
201                 .device_id      = 51,
202                 .isapnp_id      = 0x0000,       /* XXX unknown */
203                 .n_adchan       = 16,
204                 .ai_maxdata     = 0xffff,
205                 .ai_fifo_depth  = 512,
206                 .alwaysdither   = 1,            /* unknown */
207                 .gainlkup       = ai_gain_14,
208                 .ai_speed       = 10000,
209                 .caldac         = { dac8800, dac8043, ad8522 },
210         },
211 };
212 
213 static const int ni_irqpin[] = {
214         -1, -1, -1, 0, 1, 2, -1, 3, -1, -1, 4, 5, 6, -1, -1, 7
215 };
216 
217 #include "ni_mio_common.c"
218 
219 static 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},
225         {.id = ""}
226 };
227 
228 MODULE_DEVICE_TABLE(pnp, device_ids);
229 
230 static int ni_isapnp_find_board(struct pnp_dev **dev)
231 {
232         struct pnp_dev *isapnp_dev = NULL;
233         int i;
234 
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].
239                                                           isapnp_id), NULL);
240 
241                 if (!isapnp_dev || !isapnp_dev->card)
242                         continue;
243 
244                 if (pnp_device_attach(isapnp_dev) < 0)
245                         continue;
246 
247                 if (pnp_activate_dev(isapnp_dev) < 0) {
248                         pnp_device_detach(isapnp_dev);
249                         return -EAGAIN;
250                 }
251 
252                 if (!pnp_port_valid(isapnp_dev, 0) ||
253                     !pnp_irq_valid(isapnp_dev, 0)) {
254                         pnp_device_detach(isapnp_dev);
255                         return -ENOMEM;
256                 }
257                 break;
258         }
259         if (i == ARRAY_SIZE(ni_boards))
260                 return -ENODEV;
261         *dev = isapnp_dev;
262         return 0;
263 }
264 
265 static const struct ni_board_struct *ni_atmio_probe(struct comedi_device *dev)
266 {
267         int device_id = ni_read_eeprom(dev, 511);
268         int i;
269 
270         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
271                 const struct ni_board_struct *board = &ni_boards[i];
272 
273                 if (board->device_id == device_id)
274                         return board;
275         }
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");
281         else
282                 dev_err(dev->class_dev,
283                         "unknown device ID %d -- contact author\n", device_id);
284 
285         return NULL;
286 }
287 
288 static int ni_atmio_attach(struct comedi_device *dev,
289                            struct comedi_devconfig *it)
290 {
291         const struct ni_board_struct *board;
292         struct pnp_dev *isapnp_dev;
293         int ret;
294         unsigned long iobase;
295         unsigned int irq;
296 
297         ret = ni_alloc_private(dev);
298         if (ret)
299                 return ret;
300 
301         iobase = it->options[0];
302         irq = it->options[1];
303         isapnp_dev = NULL;
304         if (iobase == 0) {
305                 ret = ni_isapnp_find_board(&isapnp_dev);
306                 if (ret < 0)
307                         return ret;
308 
309                 iobase = pnp_port_start(isapnp_dev, 0);
310                 irq = pnp_irq(isapnp_dev, 0);
311                 comedi_set_hw_dev(dev, &isapnp_dev->dev);
312         }
313 
314         ret = comedi_request_region(dev, iobase, 0x20);
315         if (ret)
316                 return ret;
317 
318         board = ni_atmio_probe(dev);
319         if (!board)
320                 return -ENODEV;
321         dev->board_ptr = board;
322         dev->board_name = board->name;
323 
324         /* irq stuff */
325 
326         if (irq != 0) {
327                 if (irq > 15 || ni_irqpin[irq] == -1)
328                         return -EINVAL;
329                 ret = request_irq(irq, ni_E_interrupt, 0,
330                                   dev->board_name, dev);
331                 if (ret < 0)
332                         return -EINVAL;
333                 dev->irq = irq;
334         }
335 
336         /* generic E series stuff in ni_mio_common.c */
337 
338         ret = ni_E_init(dev, ni_irqpin[dev->irq], 0);
339         if (ret < 0)
340                 return ret;
341 
342         return 0;
343 }
344 
345 static void ni_atmio_detach(struct comedi_device *dev)
346 {
347         struct pnp_dev *isapnp_dev;
348 
349         mio_common_detach(dev);
350         comedi_legacy_detach(dev);
351 
352         isapnp_dev = dev->hw_dev ? to_pnp_dev(dev->hw_dev) : NULL;
353         if (isapnp_dev)
354                 pnp_device_detach(isapnp_dev);
355 }
356 
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,
362 };
363 module_comedi_driver(ni_atmio_driver);
364 

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us