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