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