Merge branch 'fix/misc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
[pandora-kernel.git] / drivers / staging / comedi / drivers / das08_cs.c
1 /*
2     comedi/drivers/das08_cs.c
3     DAS08 driver
4
5     COMEDI - Linux Control and Measurement Device Interface
6     Copyright (C) 2000 David A. Schleef <ds@schleef.org>
7     Copyright (C) 2001,2002,2003 Frank Mori Hess <fmhess@users.sourceforge.net>
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 /*
27 Driver: das08_cs
28 Description: DAS-08 PCMCIA boards
29 Author: Warren Jasper, ds, Frank Hess
30 Devices: [ComputerBoards] PCM-DAS08 (pcm-das08)
31 Status: works
32
33 This is the PCMCIA-specific support split off from the
34 das08 driver.
35
36 Options (for pcm-das08):
37         NONE
38
39 Command support does not exist, but could be added for this board.
40 */
41
42 #include "../comedidev.h"
43
44 #include <linux/delay.h>
45 #include <linux/pci.h>
46
47 #include "das08.h"
48
49 /* pcmcia includes */
50 #include <pcmcia/cs_types.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/cistpl.h>
53 #include <pcmcia/ds.h>
54
55 static struct pcmcia_device *cur_dev = NULL;
56
57 #define thisboard ((const struct das08_board_struct *)dev->board_ptr)
58
59 static int das08_cs_attach(struct comedi_device *dev,
60                            struct comedi_devconfig *it);
61
62 static struct comedi_driver driver_das08_cs = {
63         .driver_name = "das08_cs",
64         .module = THIS_MODULE,
65         .attach = das08_cs_attach,
66         .detach = das08_common_detach,
67         .board_name = &das08_cs_boards[0].name,
68         .num_names = ARRAY_SIZE(das08_cs_boards),
69         .offset = sizeof(struct das08_board_struct),
70 };
71
72 static int das08_cs_attach(struct comedi_device *dev,
73                            struct comedi_devconfig *it)
74 {
75         int ret;
76         unsigned long iobase;
77         struct pcmcia_device *link = cur_dev;   /*  XXX hack */
78
79         ret = alloc_private(dev, sizeof(struct das08_private_struct));
80         if (ret < 0)
81                 return ret;
82
83         printk("comedi%d: das08_cs: ", dev->minor);
84         /*  deal with a pci board */
85
86         if (thisboard->bustype == pcmcia) {
87                 if (link == NULL) {
88                         printk(" no pcmcia cards found\n");
89                         return -EIO;
90                 }
91                 iobase = link->io.BasePort1;
92         } else {
93                 printk(" bug! board does not have PCMCIA bustype\n");
94                 return -EINVAL;
95         }
96
97         printk("\n");
98
99         return das08_common_attach(dev, iobase);
100 }
101
102 /*======================================================================
103
104     The following pcmcia code for the pcm-das08 is adapted from the
105     dummy_cs.c driver of the Linux PCMCIA Card Services package.
106
107     The initial developer of the original code is David A. Hinds
108     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
109     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
110
111 ======================================================================*/
112
113 /*
114    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
115    you do not define PCMCIA_DEBUG at all, all the debug code will be
116    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
117    be present but disabled -- but it can then be enabled for specific
118    modules at load time with a 'pc_debug=#' option to insmod.
119 */
120
121 #ifdef PCMCIA_DEBUG
122 static int pc_debug = PCMCIA_DEBUG;
123 module_param(pc_debug, int, 0644);
124 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args)
125 static const char *version =
126     "das08.c pcmcia code (Frank Hess), modified from dummy_cs.c 1.31 2001/08/24 12:13:13 (David Hinds)";
127 #else
128 #define DEBUG(n, args...)
129 #endif
130
131 /*====================================================================*/
132 static void das08_pcmcia_config(struct pcmcia_device *link);
133 static void das08_pcmcia_release(struct pcmcia_device *link);
134 static int das08_pcmcia_suspend(struct pcmcia_device *p_dev);
135 static int das08_pcmcia_resume(struct pcmcia_device *p_dev);
136
137 /*
138    The attach() and detach() entry points are used to create and destroy
139    "instances" of the driver, where each instance represents everything
140    needed to manage one actual PCMCIA card.
141 */
142
143 static int das08_pcmcia_attach(struct pcmcia_device *);
144 static void das08_pcmcia_detach(struct pcmcia_device *);
145
146 /*
147    You'll also need to prototype all the functions that will actually
148    be used to talk to your device.  See 'memory_cs' for a good example
149    of a fully self-sufficient driver; the other drivers rely more or
150    less on other parts of the kernel.
151 */
152
153 /*
154    The dev_info variable is the "key" that is used to match up this
155    device driver with appropriate cards, through the card configuration
156    database.
157 */
158
159 static const dev_info_t dev_info = "pcm-das08";
160
161 struct local_info_t {
162         struct pcmcia_device *link;
163         dev_node_t node;
164         int stop;
165         struct bus_operations *bus;
166 };
167
168 /*======================================================================
169
170     das08_pcmcia_attach() creates an "instance" of the driver, allocating
171     local data structures for one device.  The device is registered
172     with Card Services.
173
174     The dev_link structure is initialized, but we don't actually
175     configure the card at this point -- we wait until we receive a
176     card insertion event.
177
178 ======================================================================*/
179
180 static int das08_pcmcia_attach(struct pcmcia_device *link)
181 {
182         struct local_info_t *local;
183
184         DEBUG(0, "das08_pcmcia_attach()\n");
185
186         /* Allocate space for private device-specific data */
187         local = kzalloc(sizeof(struct local_info_t), GFP_KERNEL);
188         if (!local)
189                 return -ENOMEM;
190         local->link = link;
191         link->priv = local;
192
193         /* Interrupt setup */
194         link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
195         link->irq.IRQInfo1 = IRQ_LEVEL_ID;
196         link->irq.Handler = NULL;
197
198         /*
199            General socket configuration defaults can go here.  In this
200            client, we assume very little, and rely on the CIS for almost
201            everything.  In most clients, many details (i.e., number, sizes,
202            and attributes of IO windows) are fixed by the nature of the
203            device, and can be hard-wired here.
204          */
205         link->conf.Attributes = 0;
206         link->conf.IntType = INT_MEMORY_AND_IO;
207
208         cur_dev = link;
209
210         das08_pcmcia_config(link);
211
212         return 0;
213 }                               /* das08_pcmcia_attach */
214
215 /*======================================================================
216
217     This deletes a driver "instance".  The device is de-registered
218     with Card Services.  If it has been released, all local data
219     structures are freed.  Otherwise, the structures will be freed
220     when the device is released.
221
222 ======================================================================*/
223
224 static void das08_pcmcia_detach(struct pcmcia_device *link)
225 {
226
227         DEBUG(0, "das08_pcmcia_detach(0x%p)\n", link);
228
229         if (link->dev_node) {
230                 ((struct local_info_t *)link->priv)->stop = 1;
231                 das08_pcmcia_release(link);
232         }
233
234         /* This points to the parent struct local_info_t struct */
235         if (link->priv)
236                 kfree(link->priv);
237
238 }                               /* das08_pcmcia_detach */
239
240 /*======================================================================
241
242     das08_pcmcia_config() is scheduled to run after a CARD_INSERTION event
243     is received, to configure the PCMCIA socket, and to make the
244     device available to the system.
245
246 ======================================================================*/
247
248 static void das08_pcmcia_config(struct pcmcia_device *link)
249 {
250         struct local_info_t *dev = link->priv;
251         tuple_t tuple;
252         cisparse_t parse;
253         int last_fn, last_ret;
254         u_char buf[64];
255         cistpl_cftable_entry_t dflt = { 0 };
256
257         DEBUG(0, "das08_pcmcia_config(0x%p)\n", link);
258
259         /*
260            This reads the card's CONFIG tuple to find its configuration
261            registers.
262          */
263         tuple.DesiredTuple = CISTPL_CONFIG;
264         tuple.Attributes = 0;
265         tuple.TupleData = buf;
266         tuple.TupleDataMax = sizeof(buf);
267         tuple.TupleOffset = 0;
268         last_fn = GetFirstTuple;
269
270         last_ret = pcmcia_get_first_tuple(link, &tuple);
271         if (last_ret)
272                 goto cs_failed;
273
274         last_fn = GetTupleData;
275
276         last_ret = pcmcia_get_tuple_data(link, &tuple);
277         if (last_ret)
278                 goto cs_failed;
279
280         last_fn = ParseTuple;
281
282         last_ret = pcmcia_parse_tuple(&tuple, &parse);
283         if (last_ret)
284                 goto cs_failed;
285
286         link->conf.ConfigBase = parse.config.base;
287         link->conf.Present = parse.config.rmask[0];
288
289         /*
290            In this loop, we scan the CIS for configuration table entries,
291            each of which describes a valid card configuration, including
292            voltage, IO window, memory window, and interrupt settings.
293
294            We make no assumptions about the card to be configured: we use
295            just the information available in the CIS.  In an ideal world,
296            this would work for any PCMCIA card, but it requires a complete
297            and accurate CIS.  In practice, a driver usually "knows" most of
298            these things without consulting the CIS, and most client drivers
299            will only use the CIS to fill in implementation-defined details.
300          */
301         tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
302         last_fn = GetFirstTuple;
303
304         last_ret = pcmcia_get_first_tuple(link, &tuple);
305         if (last_ret)
306                 goto cs_failed;
307
308         while (1) {
309                 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
310
311                 last_ret = pcmcia_get_tuple_data(link, &tuple);
312                 if (last_ret)
313                         goto next_entry;
314
315                 last_ret = pcmcia_parse_tuple(&tuple, &parse);
316                 if (last_ret)
317                         goto next_entry;
318
319                 if (cfg->flags & CISTPL_CFTABLE_DEFAULT)
320                         dflt = *cfg;
321                 if (cfg->index == 0)
322                         goto next_entry;
323                 link->conf.ConfigIndex = cfg->index;
324
325                 /* Does this card need audio output? */
326 /*      if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
327                 link->conf.Attributes |= CONF_ENABLE_SPKR;
328                 link->conf.Status = CCSR_AUDIO_ENA;
329         }
330 */
331                 /* Do we need to allocate an interrupt? */
332                 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
333                         link->conf.Attributes |= CONF_ENABLE_IRQ;
334
335                 /* IO window settings */
336                 link->io.NumPorts1 = link->io.NumPorts2 = 0;
337                 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
338                         cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
339                         link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
340                         if (!(io->flags & CISTPL_IO_8BIT))
341                                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
342                         if (!(io->flags & CISTPL_IO_16BIT))
343                                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
344                         link->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK;
345                         link->io.BasePort1 = io->win[0].base;
346                         link->io.NumPorts1 = io->win[0].len;
347                         if (io->nwin > 1) {
348                                 link->io.Attributes2 = link->io.Attributes1;
349                                 link->io.BasePort2 = io->win[1].base;
350                                 link->io.NumPorts2 = io->win[1].len;
351                         }
352                         /* This reserves IO space but doesn't actually enable it */
353                         if (pcmcia_request_io(link, &link->io) != 0)
354                                 goto next_entry;
355                 }
356
357                 /* If we got this far, we're cool! */
358                 break;
359
360 next_entry:
361                 last_fn = GetNextTuple;
362
363                 last_ret = pcmcia_get_next_tuple(link, &tuple);
364                 if (last_ret)
365                         goto cs_failed;
366         }
367
368         if (link->conf.Attributes & CONF_ENABLE_IRQ) {
369                 last_fn = RequestIRQ;
370                 last_ret = pcmcia_request_irq(link, &link->irq);
371                 if (last_ret)
372                         goto cs_failed;
373         }
374
375         /*
376            This actually configures the PCMCIA socket -- setting up
377            the I/O windows and the interrupt mapping, and putting the
378            card and host interface into "Memory and IO" mode.
379          */
380         last_fn = RequestConfiguration;
381         last_ret = pcmcia_request_configuration(link, &link->conf);
382         if (last_ret)
383                 goto cs_failed;
384
385         /*
386            At this point, the dev_node_t structure(s) need to be
387            initialized and arranged in a linked list at link->dev.
388          */
389         sprintf(dev->node.dev_name, "pcm-das08");
390         dev->node.major = dev->node.minor = 0;
391         link->dev_node = &dev->node;
392
393         /* Finally, report what we've done */
394         printk(KERN_INFO "%s: index 0x%02x",
395                dev->node.dev_name, link->conf.ConfigIndex);
396         if (link->conf.Attributes & CONF_ENABLE_IRQ)
397                 printk(", irq %u", link->irq.AssignedIRQ);
398         if (link->io.NumPorts1)
399                 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
400                        link->io.BasePort1 + link->io.NumPorts1 - 1);
401         if (link->io.NumPorts2)
402                 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
403                        link->io.BasePort2 + link->io.NumPorts2 - 1);
404         printk("\n");
405
406         return;
407
408 cs_failed:
409         cs_error(link, last_fn, last_ret);
410         das08_pcmcia_release(link);
411
412 }                               /* das08_pcmcia_config */
413
414 /*======================================================================
415
416     After a card is removed, das08_pcmcia_release() will unregister the
417     device, and release the PCMCIA configuration.  If the device is
418     still open, this will be postponed until it is closed.
419
420 ======================================================================*/
421
422 static void das08_pcmcia_release(struct pcmcia_device *link)
423 {
424         DEBUG(0, "das08_pcmcia_release(0x%p)\n", link);
425         pcmcia_disable_device(link);
426 }                               /* das08_pcmcia_release */
427
428 /*======================================================================
429
430     The card status event handler.  Mostly, this schedules other
431     stuff to run after an event is received.
432
433     When a CARD_REMOVAL event is received, we immediately set a
434     private flag to block future accesses to this device.  All the
435     functions that actually access the device should check this flag
436     to make sure the card is still present.
437
438 ======================================================================*/
439
440 static int das08_pcmcia_suspend(struct pcmcia_device *link)
441 {
442         struct local_info_t *local = link->priv;
443         /* Mark the device as stopped, to block IO until later */
444         local->stop = 1;
445
446         return 0;
447 }                               /* das08_pcmcia_suspend */
448
449 static int das08_pcmcia_resume(struct pcmcia_device *link)
450 {
451         struct local_info_t *local = link->priv;
452
453         local->stop = 0;
454         return 0;
455 }                               /* das08_pcmcia_resume */
456
457 /*====================================================================*/
458
459 static struct pcmcia_device_id das08_cs_id_table[] = {
460         PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x4001),
461         PCMCIA_DEVICE_NULL
462 };
463
464 MODULE_DEVICE_TABLE(pcmcia, das08_cs_id_table);
465
466 struct pcmcia_driver das08_cs_driver = {
467         .probe = das08_pcmcia_attach,
468         .remove = das08_pcmcia_detach,
469         .suspend = das08_pcmcia_suspend,
470         .resume = das08_pcmcia_resume,
471         .id_table = das08_cs_id_table,
472         .owner = THIS_MODULE,
473         .drv = {
474                 .name = dev_info,
475                 },
476 };
477
478 static int __init init_das08_pcmcia_cs(void)
479 {
480         DEBUG(0, "%s\n", version);
481         pcmcia_register_driver(&das08_cs_driver);
482         return 0;
483 }
484
485 static void __exit exit_das08_pcmcia_cs(void)
486 {
487         DEBUG(0, "das08_pcmcia_cs: unloading\n");
488         pcmcia_unregister_driver(&das08_cs_driver);
489 }
490
491 static int __init das08_cs_init_module(void)
492 {
493         int ret;
494
495         ret = init_das08_pcmcia_cs();
496         if (ret < 0)
497                 return ret;
498
499         return comedi_driver_register(&driver_das08_cs);
500 }
501
502 static void __exit das08_cs_exit_module(void)
503 {
504         exit_das08_pcmcia_cs();
505         comedi_driver_unregister(&driver_das08_cs);
506 }
507
508 MODULE_LICENSE("GPL");
509 module_init(das08_cs_init_module);
510 module_exit(das08_cs_exit_module);