xref: /linux/drivers/comedi/drivers/ni_mio_cs.c (revision 2da68a77)
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, 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(link, 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, 0, 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_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