GNU Linux-libre 4.9.297-gnu1
[releases.git] / drivers / staging / comedi / drivers / ni_mio_cs.c
1 /*
2  * Comedi driver for NI PCMCIA MIO E series cards
3  *
4  * COMEDI - Linux Control and Measurement Device Interface
5  * Copyright (C) 1997-2000 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_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 /*
31  * The real guts of the driver is in ni_mio_common.c, which is
32  * included by all the E series drivers.
33  *
34  * References for specifications:
35  *      341080a.pdf  DAQCard E Series Register Level Programmer Manual
36  */
37
38 #include <linux/module.h>
39 #include <linux/delay.h>
40
41 #include "../comedi_pcmcia.h"
42 #include "ni_stc.h"
43 #include "8255.h"
44
45 /*
46  *  AT specific setup
47  */
48
49 static const struct ni_board_struct ni_boards[] = {
50         {
51                 .name           = "DAQCard-ai-16xe-50",
52                 .device_id      = 0x010d,
53                 .n_adchan       = 16,
54                 .ai_maxdata     = 0xffff,
55                 .ai_fifo_depth  = 1024,
56                 .gainlkup       = ai_gain_8,
57                 .ai_speed       = 5000,
58                 .caldac         = { dac8800, dac8043 },
59         }, {
60                 .name           = "DAQCard-ai-16e-4",
61                 .device_id      = 0x010c,
62                 .n_adchan       = 16,
63                 .ai_maxdata     = 0x0fff,
64                 .ai_fifo_depth  = 1024,
65                 .gainlkup       = ai_gain_16,
66                 .ai_speed       = 4000,
67                 .caldac         = { mb88341 },          /* verified */
68         }, {
69                 .name           = "DAQCard-6062E",
70                 .device_id      = 0x02c4,
71                 .n_adchan       = 16,
72                 .ai_maxdata     = 0x0fff,
73                 .ai_fifo_depth  = 8192,
74                 .gainlkup       = ai_gain_16,
75                 .ai_speed       = 2000,
76                 .n_aochan       = 2,
77                 .ao_maxdata     = 0x0fff,
78                 .ao_fifo_depth  = 2048,
79                 .ao_range_table = &range_bipolar10,
80                 .ao_speed       = 1176,
81                 .caldac         = { ad8804_debug },     /* verified */
82          }, {
83                 /* specs incorrect! */
84                 .name           = "DAQCard-6024E",
85                 .device_id      = 0x075e,
86                 .n_adchan       = 16,
87                 .ai_maxdata     = 0x0fff,
88                 .ai_fifo_depth  = 1024,
89                 .gainlkup       = ai_gain_4,
90                 .ai_speed       = 5000,
91                 .n_aochan       = 2,
92                 .ao_maxdata     = 0x0fff,
93                 .ao_range_table = &range_bipolar10,
94                 .ao_speed       = 1000000,
95                 .caldac         = { ad8804_debug },
96         }, {
97                 /* specs incorrect! */
98                 .name           = "DAQCard-6036E",
99                 .device_id      = 0x0245,
100                 .n_adchan       = 16,
101                 .ai_maxdata     = 0xffff,
102                 .ai_fifo_depth  = 1024,
103                 .alwaysdither   = 1,
104                 .gainlkup       = ai_gain_4,
105                 .ai_speed       = 5000,
106                 .n_aochan       = 2,
107                 .ao_maxdata     = 0xffff,
108                 .ao_range_table = &range_bipolar10,
109                 .ao_speed       = 1000000,
110                 .caldac         = { ad8804_debug },
111          },
112 #if 0
113         {
114                 .name           = "DAQCard-6715",
115                 .device_id      = 0x0000,       /* unknown */
116                 .n_aochan       = 8,
117                 .ao_maxdata     = 0x0fff,
118                 .ao_671x        = 8192,
119                 .caldac         = { mb88341, mb88341 },
120         },
121 #endif
122 };
123
124 #include "ni_mio_common.c"
125
126 static const void *ni_getboardtype(struct comedi_device *dev,
127                                    struct pcmcia_device *link)
128 {
129         static const struct ni_board_struct *board;
130         int i;
131
132         for (i = 0; i < ARRAY_SIZE(ni_boards); i++) {
133                 board = &ni_boards[i];
134                 if (board->device_id == link->card_id)
135                         return board;
136         }
137         return NULL;
138 }
139
140 static int mio_pcmcia_config_loop(struct pcmcia_device *p_dev, void *priv_data)
141 {
142         int base, ret;
143
144         p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
145         p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_16;
146
147         for (base = 0x000; base < 0x400; base += 0x20) {
148                 p_dev->resource[0]->start = base;
149                 ret = pcmcia_request_io(p_dev);
150                 if (!ret)
151                         return 0;
152         }
153         return -ENODEV;
154 }
155
156 static int mio_cs_auto_attach(struct comedi_device *dev,
157                               unsigned long context)
158 {
159         struct pcmcia_device *link = comedi_to_pcmcia_dev(dev);
160         static const struct ni_board_struct *board;
161         int ret;
162
163         board = ni_getboardtype(dev, link);
164         if (!board)
165                 return -ENODEV;
166         dev->board_ptr = board;
167         dev->board_name = board->name;
168
169         link->config_flags |= CONF_AUTO_SET_IO | CONF_ENABLE_IRQ;
170         ret = comedi_pcmcia_enable(dev, mio_pcmcia_config_loop);
171         if (ret)
172                 return ret;
173         dev->iobase = link->resource[0]->start;
174
175         link->priv = dev;
176         ret = pcmcia_request_irq(link, ni_E_interrupt);
177         if (ret)
178                 return ret;
179         dev->irq = link->irq;
180
181         ret = ni_alloc_private(dev);
182         if (ret)
183                 return ret;
184
185         return ni_E_init(dev, 0, 1);
186 }
187
188 static void mio_cs_detach(struct comedi_device *dev)
189 {
190         mio_common_detach(dev);
191         comedi_pcmcia_disable(dev);
192 }
193
194 static struct comedi_driver driver_ni_mio_cs = {
195         .driver_name    = "ni_mio_cs",
196         .module         = THIS_MODULE,
197         .auto_attach    = mio_cs_auto_attach,
198         .detach         = mio_cs_detach,
199 };
200
201 static int cs_attach(struct pcmcia_device *link)
202 {
203         return comedi_pcmcia_auto_config(link, &driver_ni_mio_cs);
204 }
205
206 static const struct pcmcia_device_id ni_mio_cs_ids[] = {
207         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010d),        /* DAQCard-ai-16xe-50 */
208         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x010c),        /* DAQCard-ai-16e-4 */
209         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x02c4),        /* DAQCard-6062E */
210         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x075e),        /* DAQCard-6024E */
211         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0245),        /* DAQCard-6036E */
212         PCMCIA_DEVICE_NULL
213 };
214 MODULE_DEVICE_TABLE(pcmcia, ni_mio_cs_ids);
215
216 static struct pcmcia_driver ni_mio_cs_driver = {
217         .name           = "ni_mio_cs",
218         .owner          = THIS_MODULE,
219         .id_table       = ni_mio_cs_ids,
220         .probe          = cs_attach,
221         .remove         = comedi_pcmcia_auto_unconfig,
222 };
223 module_comedi_pcmcia_driver(driver_ni_mio_cs, ni_mio_cs_driver);
224
225 MODULE_DESCRIPTION("Comedi driver for National Instruments DAQCard E series");
226 MODULE_AUTHOR("David A. Schleef <ds@schleef.org>");
227 MODULE_LICENSE("GPL");