Version:  2.0.40 2.2.26 2.4.37 2.6.39 3.0 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15

Linux/drivers/staging/comedi/drivers/ni_mio_cs.c

  1 /*
  2     comedi/drivers/ni_mio_cs.c
  3     Hardware driver for NI PCMCIA MIO E series cards
  4 
  5     COMEDI - Linux Control and Measurement Device Interface
  6     Copyright (C) 1997-2000 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_mio_cs
 20 Description: National Instruments DAQCard E series
 21 Author: ds
 22 Status: works
 23 Devices: [National Instruments] DAQCard-AI-16XE-50 (ni_mio_cs),
 24   DAQCard-AI-16E-4, DAQCard-6062E, DAQCard-6024E, DAQCard-6036E
 25 Updated: Thu Oct 23 19:43:17 CDT 2003
 26 
 27 See the notes in the ni_atmio.o driver.
 28 */
 29 /*
 30         The real guts of the driver is in ni_mio_common.c, which is
 31         included by all the E series drivers.
 32 
 33         References for specifications:
 34 
 35            341080a.pdf  DAQCard E Series Register Level Programmer Manual
 36 
 37 */
 38 
 39 #include <linux/module.h>
 40 #include "../comedidev.h"
 41 
 42 #include <linux/delay.h>
 43 
 44 #include "ni_stc.h"
 45 #include "8255.h"
 46 
 47 #include <pcmcia/cistpl.h>
 48 #include <pcmcia/ds.h>
 49 
 50 #define ATMIO 1
 51 #undef PCIMIO
 52 
 53 /*
 54  *  AT specific setup
 55  */
 56 
 57 #define NI_SIZE 0x20
 58 
 59 #define MAX_N_CALDACS 32
 60 
 61 static const struct ni_board_struct ni_boards[] = {
 62         {
 63                 .device_id      = 0x010d,
 64                 .name           = "DAQCard-ai-16xe-50",
 65                 .n_adchan       = 16,
 66                 .adbits         = 16,
 67                 .ai_fifo_depth  = 1024,
 68                 .gainlkup       = ai_gain_8,
 69                 .ai_speed       = 5000,
 70                 .num_p0_dio_channels = 8,
 71                 .caldac         = { dac8800, dac8043 },
 72         }, {
 73                 .device_id      = 0x010c,
 74                 .name           = "DAQCard-ai-16e-4",
 75                 .n_adchan       = 16,
 76                 .adbits         = 12,
 77                 .ai_fifo_depth  = 1024,
 78                 .gainlkup       = ai_gain_16,
 79                 .ai_speed       = 4000,
 80                 .num_p0_dio_channels = 8,
 81                 .caldac         = { mb88341 },          /* verified */
 82         }, {
 83                 .device_id      = 0x02c4,
 84                 .name           = "DAQCard-6062E",
 85                 .n_adchan       = 16,
 86                 .adbits         = 12,
 87                 .ai_fifo_depth  = 8192,
 88                 .gainlkup       = ai_gain_16,
 89                 .ai_speed       = 2000,
 90                 .n_aochan       = 2,
 91                 .aobits         = 12,
 92                 .ao_fifo_depth  = 2048,
 93                 .ao_range_table = &range_bipolar10,
 94                 .ao_speed       = 1176,
 95                 .num_p0_dio_channels = 8,
 96                 .caldac         = { ad8804_debug },     /* verified */
 97          }, {
 98                 /* specs incorrect! */
 99                 .device_id      = 0x075e,
100                 .name           = "DAQCard-6024E",
101                 .n_adchan       = 16,
102                 .adbits         = 12,
103                 .ai_fifo_depth  = 1024,
104                 .gainlkup       = ai_gain_4,
105                 .ai_speed       = 5000,
106                 .n_aochan       = 2,
107                 .aobits         = 12,
108                 .ao_range_table = &range_bipolar10,
109                 .ao_speed       = 1000000,
110                 .num_p0_dio_channels = 8,
111                 .caldac         = { ad8804_debug },
112         }, {
113                 /* specs incorrect! */
114                 .device_id      = 0x0245,
115                 .name           = "DAQCard-6036E",
116                 .n_adchan       = 16,
117                 .adbits         = 16,
118                 .ai_fifo_depth  = 1024,
119                 .alwaysdither   = 1,
120                 .gainlkup       = ai_gain_4,
121                 .ai_speed       = 5000,
122                 .n_aochan       = 2,
123                 .aobits         = 16,
124                 .ao_range_table = &range_bipolar10,
125                 .ao_speed       = 1000000,
126                 .num_p0_dio_channels = 8,
127                 .caldac         = { ad8804_debug },
128          },
129 #if 0
130         {
131                 .device_id      = 0x0000,       /* unknown */
132                 .name           = "DAQCard-6715",
133                 .n_aochan       = 8,
134                 .aobits         = 12,
135                 .ao_671x        = 8192,
136                 .num_p0_dio_channels = 8,
137                 .caldac         = { mb88341, mb88341 },
138         },
139 #endif
140 };
141 
142 #define interrupt_pin(a)        0
143 
144 #define IRQ_POLARITY 1
145 
146 struct ni_private {
147 
148         struct pcmcia_device *link;
149 
150 NI_PRIVATE_COMMON};
151 
152 /* How we access registers */
153 
154 #define ni_writel(a, b)         (outl((a), (b)+dev->iobase))
155 #define ni_readl(a)             (inl((a)+dev->iobase))
156 #define ni_writew(a, b)         (outw((a), (b)+dev->iobase))
157 #define ni_readw(a)             (inw((a)+dev->iobase))
158 #define ni_writeb(a, b)         (outb((a), (b)+dev->iobase))
159 #define ni_readb(a)             (inb((a)+dev->iobase))
160 
161 /* How we access windowed registers */
162 
163 /* We automatically take advantage of STC registers that can be
164  * read/written directly in the I/O space of the board.  The
165  * DAQCard devices map the low 8 STC registers to iobase+addr*2. */
166 
167 static void mio_cs_win_out(struct comedi_device *dev, uint16_t data, int addr)
168 {
169         struct ni_private *devpriv = dev->private;
170         unsigned long flags;
171 
172         spin_lock_irqsave(&devpriv->window_lock, flags);
173         if (addr < 8) {
174                 ni_writew(data, addr * 2);
175         } else {
176                 ni_writew(addr, Window_Address);
177                 ni_writew(data, Window_Data);
178         }
179         spin_unlock_irqrestore(&devpriv->window_lock, flags);
180 }
181 
182 static uint16_t mio_cs_win_in(struct comedi_device *dev, int addr)
183 {
184         struct ni_private *devpriv = dev->private;
185         unsigned long flags;
186         uint16_t ret;
187 
188         spin_lock_irqsave(&devpriv->window_lock, flags);
189         if (addr < 8) {
190                 ret = ni_readw(addr * 2);
191         } else {
192                 ni_writew(addr, Window_Address);
193                 ret = ni_readw(Window_Data);
194         }
195         spin_unlock_irqrestore(&devpriv->window_lock, flags);
196 
197         return ret;
198 }
199 
200 #include "ni_mio_common.c"
201 
202 static const void *ni_getboardtype(struct comedi_device *dev,
203                                    struct pcmcia_device *link)
204 {
205         static const struct ni_board_struct *board;
206         int i;
207 
208         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
209                 board = &ni_boards[i];
210                 if (board->device_id == link->card_id)
211                         return board;
212         }
213         return NULL;
214 }
215 
216 static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
217 {
218         int base, ret;
219 
220         p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
221         p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
222 
223         for (base = 0x000; base < 0x400; base += 0x20) {
224                 p_dev->resource[0]->start = base;
225                 ret = pcmcia_request_io(p_dev);
226                 if (!ret)
227                         return 0;
228         }
229         return -ENODEV;
230 }
231 
232 static int mio_cs_auto_attach(struct comedi_device *dev,
233                               unsigned long context)
234 {
235         struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
236         static const struct ni_board_struct *board;
237         struct ni_private *devpriv;
238         int ret;
239 
240         board = ni_getboardtype(dev, link);
241         if (!board)
242                 return -ENODEV;
243         dev->board_ptr = board;
244         dev->board_name = board->name;
245 
246         link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
247         ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop);
248         if (ret)
249                 return ret;
250         dev->iobase = link->resource[0]->start;
251 
252         link->priv = dev;
253         ret = pcmcia_request_irq(link, ni_E_interrupt);
254         if (ret)
255                 return ret;
256         dev->irq = link->irq;
257 
258         ret = ni_alloc_private(dev);
259         if (ret)
260                 return ret;
261 
262         devpriv = dev->private;
263         devpriv->stc_writew     = mio_cs_win_out;
264         devpriv->stc_readw      = mio_cs_win_in;
265         devpriv->stc_writel     = win_out2;
266         devpriv->stc_readl      = win_in2;
267 
268         return ni_E_init(dev);
269 }
270 
271 static void mio_cs_detach(struct comedi_device *dev)
272 {
273         mio_common_detach(dev);
274         comedi_pcmcia_disable(dev);
275 }
276 
277 static struct comedi_driver driver_ni_mio_cs = {
278         .driver_name    = "ni_mio_cs",
279         .module         = THIS_MODULE,
280         .auto_attach    = mio_cs_auto_attach,
281         .detach         = mio_cs_detach,
282 };
283 
284 static int cs_attach(struct pcmcia_device *link)
285 {
286         return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
287 }
288 
289 static const struct pcmcia_device_id ni_mio_cs_ids[] = {
290         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d),        /* DAQCard-ai-16xe-50 */
291         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c),        /* DAQCard-ai-16e-4 */
292         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4),        /* DAQCard-6062E */
293         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e),        /* DAQCard-6024E */
294         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245),        /* DAQCard-6036E */
295         PCMCIA_DEVICE_NULL
296 };
297 MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids);
298 
299 static struct pcmcia_driver ni_mio_cs_driver = {
300         .name           = "ni_mio_cs",
301         .owner          = THIS_MODULE,
302         .id_table       = ni_mio_cs_ids,
303         .probe          = cs_attach,
304         .remove         = comedi_pcmcia_auto_unconfig,
305 };
306 module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);
307 
308 MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
309 MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
310 MODULE_LICENSE("GPL");
311 

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