pandora: defconfig: update
[pandora-kernel.git] / drivers / staging / comedi / drivers / ni_daq_dio24.c
1 /*
2     comedi/drivers/ni_daq_dio24.c
3     Driver for National Instruments PCMCIA DAQ-Card DIO-24
4     Copyright (C) 2002 Daniel Vecino Castel <dvecino@able.es>
5
6     PCMCIA crap at end of file is adapted from dummy_cs.c 1.31 2001/08/24 12:13:13
7     from the pcmcia package.
8     The initial developer of the pcmcia dummy_cs.c code is David A. Hinds
9     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
10     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
11
12     This program is free software; you can redistribute it and/or modify
13     it under the terms of the GNU General Public License as published by
14     the Free Software Foundation; either version 2 of the License, or
15     (at your option) any later version.
16
17     This program is distributed in the hope that it will be useful,
18     but WITHOUT ANY WARRANTY; without even the implied warranty of
19     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20     GNU General Public License for more details.
21
22     You should have received a copy of the GNU General Public License
23     along with this program; if not, write to the Free Software
24     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
26 ************************************************************************
27 */
28 /*
29 Driver: ni_daq_dio24
30 Description: National Instruments PCMCIA DAQ-Card DIO-24
31 Author: Daniel Vecino Castel <dvecino@able.es>
32 Devices: [National Instruments] PCMCIA DAQ-Card DIO-24 (ni_daq_dio24)
33 Status: ?
34 Updated: Thu, 07 Nov 2002 21:53:06 -0800
35
36 This is just a wrapper around the 8255.o driver to properly handle
37 the PCMCIA interface.
38 */
39
40                             /* #define LABPC_DEBUG *//*  enable debugging messages */
41 #undef LABPC_DEBUG
42
43 #include <linux/interrupt.h>
44 #include <linux/slab.h>
45 #include "../comedidev.h"
46
47 #include <linux/ioport.h>
48
49 #include "8255.h"
50
51 #include <pcmcia/cistpl.h>
52 #include <pcmcia/cisreg.h>
53 #include <pcmcia/ds.h>
54
55 static struct pcmcia_device *pcmcia_cur_dev = NULL;
56
57 #define DIO24_SIZE 4            /*  size of io region used by board */
58
59 static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it);
60 static int dio24_detach(struct comedi_device *dev);
61
62 enum dio24_bustype { pcmcia_bustype };
63
64 struct dio24_board_struct {
65         const char *name;
66         int device_id;          /*  device id for pcmcia board */
67         enum dio24_bustype bustype;     /*  PCMCIA */
68         int have_dio;           /*  have 8255 chip */
69         /*  function pointers so we can use inb/outb or readb/writeb as appropriate */
70         unsigned int (*read_byte) (unsigned int address);
71         void (*write_byte) (unsigned int byte, unsigned int address);
72 };
73
74 static const struct dio24_board_struct dio24_boards[] = {
75         {
76          .name = "daqcard-dio24",
77          .device_id = 0x475c,   /*  0x10b is manufacturer id, 0x475c is device id */
78          .bustype = pcmcia_bustype,
79          .have_dio = 1,
80          },
81         {
82          .name = "ni_daq_dio24",
83          .device_id = 0x475c,   /*  0x10b is manufacturer id, 0x475c is device id */
84          .bustype = pcmcia_bustype,
85          .have_dio = 1,
86          },
87 };
88
89 /*
90  * Useful for shorthand access to the particular board structure
91  */
92 #define thisboard ((const struct dio24_board_struct *)dev->board_ptr)
93
94 struct dio24_private {
95
96         int data;               /* number of data points left to be taken */
97 };
98
99 #define devpriv ((struct dio24_private *)dev->private)
100
101 static struct comedi_driver driver_dio24 = {
102         .driver_name = "ni_daq_dio24",
103         .module = THIS_MODULE,
104         .attach = dio24_attach,
105         .detach = dio24_detach,
106         .num_names = ARRAY_SIZE(dio24_boards),
107         .board_name = &dio24_boards[0].name,
108         .offset = sizeof(struct dio24_board_struct),
109 };
110
111 static int dio24_attach(struct comedi_device *dev, struct comedi_devconfig *it)
112 {
113         struct comedi_subdevice *s;
114         unsigned long iobase = 0;
115 #ifdef incomplete
116         unsigned int irq = 0;
117 #endif
118         struct pcmcia_device *link;
119
120         /* allocate and initialize dev->private */
121         if (alloc_private(dev, sizeof(struct dio24_private)) < 0)
122                 return -ENOMEM;
123
124         /*  get base address, irq etc. based on bustype */
125         switch (thisboard->bustype) {
126         case pcmcia_bustype:
127                 link = pcmcia_cur_dev;  /* XXX hack */
128                 if (!link)
129                         return -EIO;
130                 iobase = link->resource[0]->start;
131 #ifdef incomplete
132                 irq = link->irq;
133 #endif
134                 break;
135         default:
136                 printk("bug! couldn't determine board type\n");
137                 return -EINVAL;
138                 break;
139         }
140         printk("comedi%d: ni_daq_dio24: %s, io 0x%lx", dev->minor,
141                thisboard->name, iobase);
142 #ifdef incomplete
143         if (irq) {
144                 printk(", irq %u", irq);
145         }
146 #endif
147
148         printk("\n");
149
150         if (iobase == 0) {
151                 printk("io base address is zero!\n");
152                 return -EINVAL;
153         }
154
155         dev->iobase = iobase;
156
157 #ifdef incomplete
158         /* grab our IRQ */
159         dev->irq = irq;
160 #endif
161
162         dev->board_name = thisboard->name;
163
164         if (alloc_subdevices(dev, 1) < 0)
165                 return -ENOMEM;
166
167         /* 8255 dio */
168         s = dev->subdevices + 0;
169         subdev_8255_init(dev, s, NULL, dev->iobase);
170
171         return 0;
172 };
173
174 static int dio24_detach(struct comedi_device *dev)
175 {
176         printk("comedi%d: ni_daq_dio24: remove\n", dev->minor);
177
178         if (dev->subdevices)
179                 subdev_8255_cleanup(dev, dev->subdevices + 0);
180
181         if (thisboard->bustype != pcmcia_bustype && dev->iobase)
182                 release_region(dev->iobase, DIO24_SIZE);
183         if (dev->irq)
184                 free_irq(dev->irq, dev);
185
186         return 0;
187 };
188
189 static void dio24_config(struct pcmcia_device *link);
190 static void dio24_release(struct pcmcia_device *link);
191 static int dio24_cs_suspend(struct pcmcia_device *p_dev);
192 static int dio24_cs_resume(struct pcmcia_device *p_dev);
193
194 static int dio24_cs_attach(struct pcmcia_device *);
195 static void dio24_cs_detach(struct pcmcia_device *);
196
197 struct local_info_t {
198         struct pcmcia_device *link;
199         int stop;
200         struct bus_operations *bus;
201 };
202
203 static int dio24_cs_attach(struct pcmcia_device *link)
204 {
205         struct local_info_t *local;
206
207         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
208
209         dev_dbg(&link->dev, "dio24_cs_attach()\n");
210
211         /* Allocate space for private device-specific data */
212         local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
213         if (!local)
214                 return -ENOMEM;
215         local->link = link;
216         link->priv = local;
217
218         pcmcia_cur_dev = link;
219
220         dio24_config(link);
221
222         return 0;
223 }                               /* dio24_cs_attach */
224
225 static void dio24_cs_detach(struct pcmcia_device *link)
226 {
227
228         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
229
230         dev_dbg(&link->dev, "dio24_cs_detach\n");
231
232         ((struct local_info_t *)link->priv)->stop = 1;
233         dio24_release(link);
234
235         /* This points to the parent local_info_t struct */
236         kfree(link->priv);
237
238 }                               /* dio24_cs_detach */
239
240 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
241                                 void *priv_data)
242 {
243         if (p_dev->config_index == 0)
244                 return -EINVAL;
245
246         return pcmcia_request_io(p_dev);
247 }
248
249 static void dio24_config(struct pcmcia_device *link)
250 {
251         int ret;
252
253         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
254
255         dev_dbg(&link->dev, "dio24_config\n");
256
257         link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO |
258                 CONF_AUTO_SET_IO;
259
260         ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
261         if (ret) {
262                 dev_warn(&link->dev, "no configuration found\n");
263                 goto failed;
264         }
265
266         if (!link->irq)
267                 goto failed;
268
269         ret = pcmcia_enable_device(link);
270         if (ret)
271                 goto failed;
272
273         return;
274
275 failed:
276         printk(KERN_INFO "Fallo");
277         dio24_release(link);
278
279 }                               /* dio24_config */
280
281 static void dio24_release(struct pcmcia_device *link)
282 {
283         dev_dbg(&link->dev, "dio24_release\n");
284
285         pcmcia_disable_device(link);
286 }                               /* dio24_release */
287
288 static int dio24_cs_suspend(struct pcmcia_device *link)
289 {
290         struct local_info_t *local = link->priv;
291
292         /* Mark the device as stopped, to block IO until later */
293         local->stop = 1;
294         return 0;
295 }                               /* dio24_cs_suspend */
296
297 static int dio24_cs_resume(struct pcmcia_device *link)
298 {
299         struct local_info_t *local = link->priv;
300
301         local->stop = 0;
302         return 0;
303 }                               /* dio24_cs_resume */
304
305 /*====================================================================*/
306
307 static const struct pcmcia_device_id dio24_cs_ids[] = {
308         /* N.B. These IDs should match those in dio24_boards */
309         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),        /* daqcard-dio24 */
310         PCMCIA_DEVICE_NULL
311 };
312
313 MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
314 MODULE_AUTHOR("Daniel Vecino Castel <dvecino@able.es>");
315 MODULE_DESCRIPTION("Comedi driver for National Instruments "
316                    "PCMCIA DAQ-Card DIO-24");
317 MODULE_LICENSE("GPL");
318
319 struct pcmcia_driver dio24_cs_driver = {
320         .probe = dio24_cs_attach,
321         .remove = dio24_cs_detach,
322         .suspend = dio24_cs_suspend,
323         .resume = dio24_cs_resume,
324         .id_table = dio24_cs_ids,
325         .owner = THIS_MODULE,
326         .name = "ni_daq_dio24",
327 };
328
329 static int __init init_dio24_cs(void)
330 {
331         printk("ni_daq_dio24: HOLA SOY YO!\n");
332         pcmcia_register_driver(&dio24_cs_driver);
333         return 0;
334 }
335
336 static void __exit exit_dio24_cs(void)
337 {
338         pcmcia_unregister_driver(&dio24_cs_driver);
339 }
340
341 int __init init_module(void)
342 {
343         int ret;
344
345         ret = init_dio24_cs();
346         if (ret < 0)
347                 return ret;
348
349         return comedi_driver_register(&driver_dio24);
350 }
351
352 void __exit cleanup_module(void)
353 {
354         exit_dio24_cs();
355         comedi_driver_unregister(&driver_dio24);
356 }