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