pcmcia: introduce autoconfiguration feature
[linux-2.6.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 /* PCMCIA crap -- watch your words! */
190
191 static void dio24_config(struct pcmcia_device *link);
192 static void dio24_release(struct pcmcia_device *link);
193 static int dio24_cs_suspend(struct pcmcia_device *p_dev);
194 static int dio24_cs_resume(struct pcmcia_device *p_dev);
195
196 /*
197    The attach() and detach() entry points are used to create and destroy
198    "instances" of the driver, where each instance represents everything
199    needed to manage one actual PCMCIA card.
200 */
201
202 static int dio24_cs_attach(struct pcmcia_device *);
203 static void dio24_cs_detach(struct pcmcia_device *);
204
205 /*
206    You'll also need to prototype all the functions that will actually
207    be used to talk to your device.  See 'memory_cs' for a good example
208    of a fully self-sufficient driver; the other drivers rely more or
209    less on other parts of the kernel.
210 */
211
212 struct local_info_t {
213         struct pcmcia_device *link;
214         int stop;
215         struct bus_operations *bus;
216 };
217
218 /*======================================================================
219
220     dio24_cs_attach() creates an "instance" of the driver, allocating
221     local data structures for one device.  The device is registered
222     with Card Services.
223
224     The dev_link structure is initialized, but we don't actually
225     configure the card at this point -- we wait until we receive a
226     card insertion event.
227
228 ======================================================================*/
229
230 static int dio24_cs_attach(struct pcmcia_device *link)
231 {
232         struct local_info_t *local;
233
234         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - CS-attach!\n");
235
236         dev_dbg(&link->dev, "dio24_cs_attach()\n");
237
238         /* Allocate space for private device-specific data */
239         local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
240         if (!local)
241                 return -ENOMEM;
242         local->link = link;
243         link->priv = local;
244
245         pcmcia_cur_dev = link;
246
247         dio24_config(link);
248
249         return 0;
250 }                               /* dio24_cs_attach */
251
252 /*======================================================================
253
254     This deletes a driver "instance".  The device is de-registered
255     with Card Services.  If it has been released, all local data
256     structures are freed.  Otherwise, the structures will be freed
257     when the device is released.
258
259 ======================================================================*/
260
261 static void dio24_cs_detach(struct pcmcia_device *link)
262 {
263
264         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO - cs-detach!\n");
265
266         dev_dbg(&link->dev, "dio24_cs_detach\n");
267
268         ((struct local_info_t *)link->priv)->stop = 1;
269         dio24_release(link);
270
271         /* This points to the parent local_info_t struct */
272         kfree(link->priv);
273
274 }                               /* dio24_cs_detach */
275
276 /*======================================================================
277
278     dio24_config() is scheduled to run after a CARD_INSERTION event
279     is received, to configure the PCMCIA socket, and to make the
280     device available to the system.
281
282 ======================================================================*/
283
284 static int dio24_pcmcia_config_loop(struct pcmcia_device *p_dev,
285                                 cistpl_cftable_entry_t *cfg,
286                                 cistpl_cftable_entry_t *dflt,
287                                 void *priv_data)
288 {
289         if (cfg->index == 0)
290                 return -ENODEV;
291
292         /* IO window settings */
293         p_dev->resource[0]->end = p_dev->resource[1]->end = 0;
294         if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) {
295                 cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io;
296                 p_dev->io_lines = io->flags & CISTPL_IO_LINES_MASK;
297                 p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
298                 p_dev->resource[0]->flags |=
299                         pcmcia_io_cfg_data_width(io->flags);
300                 p_dev->resource[0]->start = io->win[0].base;
301                 p_dev->resource[0]->end = io->win[0].len;
302                 if (io->nwin > 1) {
303                         p_dev->resource[1]->flags = p_dev->resource[0]->flags;
304                         p_dev->resource[1]->start = io->win[1].base;
305                         p_dev->resource[1]->end = io->win[1].len;
306                 }
307                 /* This reserves IO space but doesn't actually enable it */
308                 if (pcmcia_request_io(p_dev) != 0)
309                         return -ENODEV;
310         }
311
312         /* If we got this far, we're cool! */
313         return 0;
314 }
315
316 static void dio24_config(struct pcmcia_device *link)
317 {
318         int ret;
319
320         printk(KERN_INFO "ni_daq_dio24: HOLA SOY YO! - config\n");
321
322         dev_dbg(&link->dev, "dio24_config\n");
323
324         link->config_flags |= CONF_ENABLE_IRQ | CONF_AUTO_AUDIO;
325
326         ret = pcmcia_loop_config(link, dio24_pcmcia_config_loop, NULL);
327         if (ret) {
328                 dev_warn(&link->dev, "no configuration found\n");
329                 goto failed;
330         }
331
332         if (!link->irq)
333                 goto failed;
334
335         /*
336            This actually configures the PCMCIA socket -- setting up
337            the I/O windows and the interrupt mapping, and putting the
338            card and host interface into "Memory and IO" mode.
339          */
340         ret = pcmcia_enable_device(link);
341         if (ret)
342                 goto failed;
343
344         /* Finally, report what we've done */
345         dev_info(&link->dev, "index 0x%02x", link->config_index);
346         printk(", irq %d", link->irq);
347         if (link->resource[0])
348                 printk(" & %pR", link->resource[0]);
349         if (link->resource[1])
350                 printk(" & %pR", link->resource[1]);
351         printk("\n");
352
353         return;
354
355 failed:
356         printk(KERN_INFO "Fallo");
357         dio24_release(link);
358
359 }                               /* dio24_config */
360
361 static void dio24_release(struct pcmcia_device *link)
362 {
363         dev_dbg(&link->dev, "dio24_release\n");
364
365         pcmcia_disable_device(link);
366 }                               /* dio24_release */
367
368 /*======================================================================
369
370     The card status event handler.  Mostly, this schedules other
371     stuff to run after an event is received.
372
373     When a CARD_REMOVAL event is received, we immediately set a
374     private flag to block future accesses to this device.  All the
375     functions that actually access the device should check this flag
376     to make sure the card is still present.
377
378 ======================================================================*/
379
380 static int dio24_cs_suspend(struct pcmcia_device *link)
381 {
382         struct local_info_t *local = link->priv;
383
384         /* Mark the device as stopped, to block IO until later */
385         local->stop = 1;
386         return 0;
387 }                               /* dio24_cs_suspend */
388
389 static int dio24_cs_resume(struct pcmcia_device *link)
390 {
391         struct local_info_t *local = link->priv;
392
393         local->stop = 0;
394         return 0;
395 }                               /* dio24_cs_resume */
396
397 /*====================================================================*/
398
399 static struct pcmcia_device_id dio24_cs_ids[] = {
400         /* N.B. These IDs should match those in dio24_boards */
401         PCMCIA_DEVICE_MANF_CARD(0x010b, 0x475c),        /* daqcard-dio24 */
402         PCMCIA_DEVICE_NULL
403 };
404
405 MODULE_DEVICE_TABLE(pcmcia, dio24_cs_ids);
406 MODULE_AUTHOR("Daniel Vecino Castel <dvecino@able.es>");
407 MODULE_DESCRIPTION("Comedi driver for National Instruments "
408                    "PCMCIA DAQ-Card DIO-24");
409 MODULE_LICENSE("GPL");
410
411 struct pcmcia_driver dio24_cs_driver = {
412         .probe = dio24_cs_attach,
413         .remove = dio24_cs_detach,
414         .suspend = dio24_cs_suspend,
415         .resume = dio24_cs_resume,
416         .id_table = dio24_cs_ids,
417         .owner = THIS_MODULE,
418         .drv = {
419                 .name = "ni_daq_dio24",
420                 },
421 };
422
423 static int __init init_dio24_cs(void)
424 {
425         printk("ni_daq_dio24: HOLA SOY YO!\n");
426         pcmcia_register_driver(&dio24_cs_driver);
427         return 0;
428 }
429
430 static void __exit exit_dio24_cs(void)
431 {
432         pcmcia_unregister_driver(&dio24_cs_driver);
433 }
434
435 int __init init_module(void)
436 {
437         int ret;
438
439         ret = init_dio24_cs();
440         if (ret < 0)
441                 return ret;
442
443         return comedi_driver_register(&driver_dio24);
444 }
445
446 void __exit cleanup_module(void)
447 {
448         exit_dio24_cs();
449         comedi_driver_unregister(&driver_dio24);
450 }