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