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