]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/staging/comedi/drivers/ni_daq_700.c
Merge branch 'vfs-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/vfs
[karo-tx-linux.git] / drivers / staging / comedi / drivers / ni_daq_700.c
1 /*
2  *     comedi/drivers/ni_daq_700.c
3  *     Driver for DAQCard-700 DIO only
4  *     copied from 8255
5  *
6  *     COMEDI - Linux Control and Measurement Device Interface
7  *     Copyright (C) 1998 David A. Schleef <ds@schleef.org>
8  *
9  *     This program is free software; you can redistribute it and/or modify
10  *     it under the terms of the GNU General Public License as published by
11  *     the Free Software Foundation; either version 2 of the License, or
12  *     (at your option) any later version.
13  *
14  *     This program is distributed in the hope that it will be useful,
15  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *     GNU General Public License for more details.
18  *
19  *     You should have received a copy of the GNU General Public License
20  *     along with this program; if not, write to the Free Software
21  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25 /*
26 Driver: ni_daq_700
27 Description: National Instruments PCMCIA DAQCard-700 DIO only
28 Author: Fred Brooks <nsaspook@nsaspook.com>,
29   based on ni_daq_dio24 by Daniel Vecino Castel <dvecino@able.es>
30 Devices: [National Instruments] PCMCIA DAQ-Card-700 (ni_daq_700)
31 Status: works
32 Updated: Thu, 21 Feb 2008 12:07:20 +0000
33
34 The daqcard-700 appears in Comedi as a single digital I/O subdevice with
35 16 channels.  The channel 0 corresponds to the daqcard-700's output
36 port, bit 0; channel 8 corresponds to the input port, bit 0.
37
38 Direction configuration: channels 0-7 output, 8-15 input (8225 device
39 emu as port A output, port B input, port C N/A).
40 */
41
42 #include <linux/interrupt.h>
43 #include <linux/slab.h>
44 #include "../comedidev.h"
45
46 #include <linux/ioport.h>
47
48 #include <pcmcia/cistpl.h>
49 #include <pcmcia/cisreg.h>
50 #include <pcmcia/ds.h>
51
52 static struct pcmcia_device *pcmcia_cur_dev;
53
54 struct dio700_board {
55         const char *name;
56 };
57
58 #define DIO_W           0x04
59 #define DIO_R           0x05
60
61 static int subdev_700_insn(struct comedi_device *dev,
62                            struct comedi_subdevice *s, struct comedi_insn *insn,
63                            unsigned int *data)
64 {
65         if (data[0]) {
66                 s->state &= ~data[0];
67                 s->state |= (data[0] & data[1]);
68
69                 if (data[0] & 0xff)
70                         outb(s->state & 0xff, dev->iobase + DIO_W);
71         }
72
73         data[1] = s->state & 0xff;
74         data[1] |= inb(dev->iobase + DIO_R);
75
76         return insn->n;
77 }
78
79 static int subdev_700_insn_config(struct comedi_device *dev,
80                                   struct comedi_subdevice *s,
81                                   struct comedi_insn *insn, unsigned int *data)
82 {
83         unsigned int chan = 1 << CR_CHAN(insn->chanspec);
84
85         switch (data[0]) {
86         case INSN_CONFIG_DIO_INPUT:
87                 break;
88         case INSN_CONFIG_DIO_OUTPUT:
89                 break;
90         case INSN_CONFIG_DIO_QUERY:
91                 data[1] = (s->io_bits & chan) ? COMEDI_OUTPUT : COMEDI_INPUT;
92                 break;
93         default:
94                 return -EINVAL;
95         }
96
97         return insn->n;
98 }
99
100 static int dio700_attach(struct comedi_device *dev, struct comedi_devconfig *it)
101 {
102         const struct dio700_board *thisboard = comedi_board(dev);
103         struct comedi_subdevice *s;
104         struct pcmcia_device *link;
105         int ret;
106
107         link = pcmcia_cur_dev;  /* XXX hack */
108         if (!link)
109                 return -EIO;
110
111         dev->iobase = link->resource[0]->start;
112         if (!dev->iobase) {
113                 dev_err(dev->class_dev, "io base address is zero!\n");
114                 return -EINVAL;
115         }
116
117         dev->board_name = thisboard->name;
118
119         ret = comedi_alloc_subdevices(dev, 1);
120         if (ret)
121                 return ret;
122
123         /* DAQCard-700 dio */
124         s = dev->subdevices + 0;
125         s->type         = COMEDI_SUBD_DIO;
126         s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
127         s->n_chan       = 16;
128         s->range_table  = &range_digital;
129         s->maxdata      = 1;
130         s->insn_bits    = subdev_700_insn;
131         s->insn_config  = subdev_700_insn_config;
132
133         s->state        = 0;
134         s->io_bits      = 0x00ff;
135
136         dev_info(dev->class_dev, "%s: %s, io 0x%lx\n",
137                 dev->driver->driver_name,
138                 dev->board_name,
139                 dev->iobase);
140
141         return 0;
142 }
143
144 static void dio700_detach(struct comedi_device *dev)
145 {
146         /* nothing to cleanup */
147 }
148
149 static const struct dio700_board dio700_boards[] = {
150         {
151                 .name           = "daqcard-700",
152         }, {
153                 .name           = "ni_daq_700",
154         },
155 };
156
157 static struct comedi_driver driver_dio700 = {
158         .driver_name    = "ni_daq_700",
159         .module         = THIS_MODULE,
160         .attach         = dio700_attach,
161         .detach         = dio700_detach,
162         .board_name     = &dio700_boards[0].name,
163         .num_names      = ARRAY_SIZE(dio700_boards),
164         .offset         = sizeof(struct dio700_board),
165 };
166
167 static int dio700_pcmcia_config_loop(struct pcmcia_device *p_dev,
168                                 void *priv_data)
169 {
170         if (p_dev->config_index == 0)
171                 return -EINVAL;
172
173         return pcmcia_request_io(p_dev);
174 }
175
176 static int dio700_cs_attach(struct pcmcia_device *link)
177 {
178         int ret;
179
180         link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
181                 CONF_AUTO_SET_IO;
182
183         ret = pcmcia_loop_config(link, dio700_pcmcia_config_loop, NULL);
184         if (ret)
185                 goto failed;
186
187         if (!link->irq)
188                 goto failed;
189
190         ret = pcmcia_enable_device(link);
191         if (ret)
192                 goto failed;
193
194         pcmcia_cur_dev = link;
195         return 0;
196
197 failed:
198         pcmcia_disable_device(link);
199         return ret;
200 }
201
202 static void dio700_cs_detach(struct pcmcia_device *link)
203 {
204         pcmcia_disable_device(link);
205         pcmcia_cur_dev = NULL;
206 }
207
208 static const struct pcmcia_device_id dio700_cs_ids[] = {
209         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4743),
210         PCMCIA_DEVICE_NULL
211 };
212 MODULE_DEVICE_TABLE(pcmcia, dio700_cs_ids);
213
214 static struct pcmcia_driver dio700_cs_driver = {
215         .name           = "ni_daq_700",
216         .owner          = THIS_MODULE,
217         .probe          = dio700_cs_attach,
218         .remove         = dio700_cs_detach,
219         .id_table       = dio700_cs_ids,
220 };
221
222 static int __init dio700_cs_init(void)
223 {
224         int ret;
225
226         ret = comedi_driver_register(&driver_dio700);
227         if (ret < 0)
228                 return ret;
229
230         ret = pcmcia_register_driver(&dio700_cs_driver);
231         if (ret < 0) {
232                 comedi_driver_unregister(&driver_dio700);
233                 return ret;
234         }
235
236         return 0;
237 }
238 module_init(dio700_cs_init);
239
240 static void __exit dio700_cs_exit(void)
241 {
242         pcmcia_unregister_driver(&dio700_cs_driver);
243         comedi_driver_unregister(&driver_dio700);
244 }
245 module_exit(dio700_cs_exit);
246
247 MODULE_AUTHOR("Fred Brooks <nsaspook@nsaspook.com>");
248 MODULE_DESCRIPTION(
249         "Comedi driver for National Instruments PCMCIA DAQCard-700 DIO");
250 MODULE_LICENSE("GPL");