[PATCH] pcmcia: remove dev_list from drivers
[linux-2.6] / drivers / isdn / hisax / elsa_cs.c
1 /*======================================================================
2
3     An elsa_cs PCMCIA client driver
4
5     This driver is for the Elsa PCM ISDN Cards, i.e. the MicroLink
6
7
8     The contents of this file are subject to the Mozilla Public
9     License Version 1.1 (the "License"); you may not use this file
10     except in compliance with the License. You may obtain a copy of
11     the License at http://www.mozilla.org/MPL/
12
13     Software distributed under the License is distributed on an "AS
14     IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
15     implied. See the License for the specific language governing
16     rights and limitations under the License.
17
18     The initial developer of the original code is David A. Hinds
19     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
20     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
21
22     Modifications from dummy_cs.c are Copyright (C) 1999-2001 Klaus
23     Lichtenwalder <Lichtenwalder@ACM.org>. All Rights Reserved.
24
25     Alternatively, the contents of this file may be used under the
26     terms of the GNU General Public License version 2 (the "GPL"), in
27     which case the provisions of the GPL are applicable instead of the
28     above.  If you wish to allow the use of your version of this file
29     only under the terms of the GPL and not to allow others to use
30     your version of this file under the MPL, indicate your decision
31     by deleting the provisions above and replace them with the notice
32     and other provisions required by the GPL.  If you do not delete
33     the provisions above, a recipient may use your version of this
34     file under either the MPL or the GPL.
35
36 ======================================================================*/
37
38 #include <linux/module.h>
39 #include <linux/kernel.h>
40 #include <linux/init.h>
41 #include <linux/sched.h>
42 #include <linux/ptrace.h>
43 #include <linux/slab.h>
44 #include <linux/string.h>
45 #include <linux/timer.h>
46 #include <linux/ioport.h>
47 #include <asm/io.h>
48 #include <asm/system.h>
49
50 #include <pcmcia/cs_types.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/cistpl.h>
53 #include <pcmcia/cisreg.h>
54 #include <pcmcia/ds.h>
55 #include "hisax_cfg.h"
56
57 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for Elsa PCM cards");
58 MODULE_AUTHOR("Klaus Lichtenwalder");
59 MODULE_LICENSE("Dual MPL/GPL");
60
61 /*
62    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
63    you do not define PCMCIA_DEBUG at all, all the debug code will be
64    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
65    be present but disabled -- but it can then be enabled for specific
66    modules at load time with a 'pc_debug=#' option to insmod.
67 */
68
69 #ifdef PCMCIA_DEBUG
70 static int pc_debug = PCMCIA_DEBUG;
71 module_param(pc_debug, int, 0);
72 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
73 static char *version =
74 "elsa_cs.c $Revision: 1.2.2.4 $ $Date: 2004/01/25 15:07:06 $ (K.Lichtenwalder)";
75 #else
76 #define DEBUG(n, args...)
77 #endif
78
79 /*====================================================================*/
80
81 /* Parameters that can be set with 'insmod' */
82
83 static int protocol = 2;        /* EURO-ISDN Default */
84 module_param(protocol, int, 0);
85
86 /*====================================================================*/
87
88 /*
89    The event() function is this driver's Card Services event handler.
90    It will be called by Card Services when an appropriate card status
91    event is received.  The config() and release() entry points are
92    used to configure or release a socket, in response to card insertion
93    and ejection events.  They are invoked from the elsa_cs event
94    handler.
95 */
96
97 static void elsa_cs_config(dev_link_t *link);
98 static void elsa_cs_release(dev_link_t *link);
99 static int elsa_cs_event(event_t event, int priority,
100                           event_callback_args_t *args);
101
102 /*
103    The attach() and detach() entry points are used to create and destroy
104    "instances" of the driver, where each instance represents everything
105    needed to manage one actual PCMCIA card.
106 */
107
108 static dev_link_t *elsa_cs_attach(void);
109 static void elsa_cs_detach(struct pcmcia_device *p_dev);
110
111 /*
112    The dev_info variable is the "key" that is used to match up this
113    device driver with appropriate cards, through the card configuration
114    database.
115 */
116
117 static dev_info_t dev_info = "elsa_cs";
118
119 /*
120    A linked list of "instances" of the elsa_cs device.  Each actual
121    PCMCIA card corresponds to one device instance, and is described
122    by one dev_link_t structure (defined in ds.h).
123
124    You may not want to use a linked list for this -- for example, the
125    memory card driver uses an array of dev_link_t pointers, where minor
126    device numbers are used to derive the corresponding array index.
127 */
128
129 /*
130    A driver needs to provide a dev_node_t structure for each device
131    on a card.  In some cases, there is only one device per card (for
132    example, ethernet cards, modems).  In other cases, there may be
133    many actual or logical devices (SCSI adapters, memory cards with
134    multiple partitions).  The dev_node_t structures need to be kept
135    in a linked list starting at the 'dev' field of a dev_link_t
136    structure.  We allocate them in the card's private data structure,
137    because they generally shouldn't be allocated dynamically.
138    In this case, we also provide a flag to indicate if a device is
139    "stopped" due to a power management event, or card ejection.  The
140    device IO routines can use a flag like this to throttle IO to a
141    card that is not ready to accept it.
142 */
143
144 typedef struct local_info_t {
145     dev_link_t          link;
146     dev_node_t          node;
147     int                 busy;
148     int                 cardnr;
149 } local_info_t;
150
151 /*======================================================================
152
153     elsa_cs_attach() creates an "instance" of the driver, allocatingx
154     local data structures for one device.  The device is registered
155     with Card Services.
156
157     The dev_link structure is initialized, but we don't actually
158     configure the card at this point -- we wait until we receive a
159     card insertion event.
160
161 ======================================================================*/
162
163 static dev_link_t *elsa_cs_attach(void)
164 {
165     client_reg_t client_reg;
166     dev_link_t *link;
167     local_info_t *local;
168     int ret;
169
170     DEBUG(0, "elsa_cs_attach()\n");
171
172     /* Allocate space for private device-specific data */
173     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
174     if (!local) return NULL;
175     memset(local, 0, sizeof(local_info_t));
176     local->cardnr = -1;
177     link = &local->link; link->priv = local;
178
179     /* Interrupt setup */
180     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
181     link->irq.IRQInfo1 = IRQ_LEVEL_ID|IRQ_SHARE_ID;
182     link->irq.Handler = NULL;
183
184     /*
185       General socket configuration defaults can go here.  In this
186       client, we assume very little, and rely on the CIS for almost
187       everything.  In most clients, many details (i.e., number, sizes,
188       and attributes of IO windows) are fixed by the nature of the
189       device, and can be hard-wired here.
190     */
191     link->io.NumPorts1 = 8;
192     link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
193     link->io.IOAddrLines = 3;
194
195     link->conf.Attributes = CONF_ENABLE_IRQ;
196     link->conf.Vcc = 50;
197     link->conf.IntType = INT_MEMORY_AND_IO;
198
199     /* Register with Card Services */
200     link->next = NULL;
201     client_reg.dev_info = &dev_info;
202     client_reg.Version = 0x0210;
203     client_reg.event_callback_args.client_data = link;
204     ret = pcmcia_register_client(&link->handle, &client_reg);
205     if (ret != CS_SUCCESS) {
206         cs_error(link->handle, RegisterClient, ret);
207         elsa_cs_detach(link->handle);
208         return NULL;
209     }
210
211     return link;
212 } /* elsa_cs_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 elsa_cs_detach(struct pcmcia_device *p_dev)
224 {
225     dev_link_t *link = dev_to_instance(p_dev);
226     local_info_t *info = link->priv;
227
228     DEBUG(0, "elsa_cs_detach(0x%p)\n", link);
229
230     if (link->state & DEV_CONFIG) {
231             info->busy = 1;
232             elsa_cs_release(link);
233     }
234
235     kfree(info);
236
237 } /* elsa_cs_detach */
238
239 /*======================================================================
240
241     elsa_cs_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 static int get_tuple(client_handle_t handle, tuple_t *tuple,
247                      cisparse_t *parse)
248 {
249     int i = pcmcia_get_tuple_data(handle, tuple);
250     if (i != CS_SUCCESS) return i;
251     return pcmcia_parse_tuple(handle, tuple, parse);
252 }
253
254 static int first_tuple(client_handle_t handle, tuple_t *tuple,
255                      cisparse_t *parse)
256 {
257     int i = pcmcia_get_first_tuple(handle, tuple);
258     if (i != CS_SUCCESS) return i;
259     return get_tuple(handle, tuple, parse);
260 }
261
262 static int next_tuple(client_handle_t handle, tuple_t *tuple,
263                      cisparse_t *parse)
264 {
265     int i = pcmcia_get_next_tuple(handle, tuple);
266     if (i != CS_SUCCESS) return i;
267     return get_tuple(handle, tuple, parse);
268 }
269
270 static void elsa_cs_config(dev_link_t *link)
271 {
272     client_handle_t handle;
273     tuple_t tuple;
274     cisparse_t parse;
275     local_info_t *dev;
276     int i, j, last_fn;
277     u_short buf[128];
278     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
279     IsdnCard_t icard;
280
281     DEBUG(0, "elsa_config(0x%p)\n", link);
282     handle = link->handle;
283     dev = link->priv;
284
285     /*
286        This reads the card's CONFIG tuple to find its configuration
287        registers.
288     */
289     tuple.DesiredTuple = CISTPL_CONFIG;
290     tuple.TupleData = (cisdata_t *)buf;
291     tuple.TupleDataMax = 255;
292     tuple.TupleOffset = 0;
293     tuple.Attributes = 0;
294     i = first_tuple(handle, &tuple, &parse);
295     if (i != CS_SUCCESS) {
296         last_fn = ParseTuple;
297         goto cs_failed;
298     }
299     link->conf.ConfigBase = parse.config.base;
300     link->conf.Present = parse.config.rmask[0];
301
302     /* Configure card */
303     link->state |= DEV_CONFIG;
304
305     tuple.TupleData = (cisdata_t *)buf;
306     tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
307     tuple.Attributes = 0;
308     tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
309     i = first_tuple(handle, &tuple, &parse);
310     while (i == CS_SUCCESS) {
311         if ( (cf->io.nwin > 0) && cf->io.win[0].base) {
312             printk(KERN_INFO "(elsa_cs: looks like the 96 model)\n");
313             link->conf.ConfigIndex = cf->index;
314             link->io.BasePort1 = cf->io.win[0].base;
315             i = pcmcia_request_io(link->handle, &link->io);
316             if (i == CS_SUCCESS) break;
317         } else {
318           printk(KERN_INFO "(elsa_cs: looks like the 97 model)\n");
319           link->conf.ConfigIndex = cf->index;
320           for (i = 0, j = 0x2f0; j > 0x100; j -= 0x10) {
321             link->io.BasePort1 = j;
322             i = pcmcia_request_io(link->handle, &link->io);
323             if (i == CS_SUCCESS) break;
324           }
325           break;
326         }
327         i = next_tuple(handle, &tuple, &parse);
328     }
329
330     if (i != CS_SUCCESS) {
331         last_fn = RequestIO;
332         goto cs_failed;
333     }
334
335     i = pcmcia_request_irq(link->handle, &link->irq);
336     if (i != CS_SUCCESS) {
337         link->irq.AssignedIRQ = 0;
338         last_fn = RequestIRQ;
339         goto cs_failed;
340     }
341
342     i = pcmcia_request_configuration(link->handle, &link->conf);
343     if (i != CS_SUCCESS) {
344       last_fn = RequestConfiguration;
345       goto cs_failed;
346     }
347
348     /* At this point, the dev_node_t structure(s) should be
349        initialized and arranged in a linked list at link->dev. *//*  */
350     sprintf(dev->node.dev_name, "elsa");
351     dev->node.major = dev->node.minor = 0x0;
352
353     link->dev = &dev->node;
354
355     /* Finally, report what we've done */
356     printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
357            dev->node.dev_name, link->conf.ConfigIndex,
358            link->conf.Vcc/10, link->conf.Vcc%10);
359     if (link->conf.Vpp1)
360         printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
361     if (link->conf.Attributes & CONF_ENABLE_IRQ)
362         printk(", irq %d", link->irq.AssignedIRQ);
363     if (link->io.NumPorts1)
364         printk(", io 0x%04x-0x%04x", link->io.BasePort1,
365                link->io.BasePort1+link->io.NumPorts1-1);
366     if (link->io.NumPorts2)
367         printk(" & 0x%04x-0x%04x", link->io.BasePort2,
368                link->io.BasePort2+link->io.NumPorts2-1);
369     printk("\n");
370
371     link->state &= ~DEV_CONFIG_PENDING;
372
373     icard.para[0] = link->irq.AssignedIRQ;
374     icard.para[1] = link->io.BasePort1;
375     icard.protocol = protocol;
376     icard.typ = ISDN_CTYPE_ELSA_PCMCIA;
377     
378     i = hisax_init_pcmcia(link, &(((local_info_t*)link->priv)->busy), &icard);
379     if (i < 0) {
380         printk(KERN_ERR "elsa_cs: failed to initialize Elsa PCMCIA %d at i/o %#x\n",
381                 i, link->io.BasePort1);
382         elsa_cs_release(link);
383     } else
384         ((local_info_t*)link->priv)->cardnr = i;
385
386     return;
387 cs_failed:
388     cs_error(link->handle, last_fn, i);
389     elsa_cs_release(link);
390 } /* elsa_cs_config */
391
392 /*======================================================================
393
394     After a card is removed, elsa_cs_release() will unregister the net
395     device, and release the PCMCIA configuration.  If the device is
396     still open, this will be postponed until it is closed.
397
398 ======================================================================*/
399
400 static void elsa_cs_release(dev_link_t *link)
401 {
402     local_info_t *local = link->priv;
403
404     DEBUG(0, "elsa_cs_release(0x%p)\n", link);
405
406     if (local) {
407         if (local->cardnr >= 0) {
408             /* no unregister function with hisax */
409             HiSax_closecard(local->cardnr);
410         }
411     }
412     /* Unlink the device chain */
413     link->dev = NULL;
414
415     /* Don't bother checking to see if these succeed or not */
416     if (link->win)
417         pcmcia_release_window(link->win);
418     pcmcia_release_configuration(link->handle);
419     pcmcia_release_io(link->handle, &link->io);
420     pcmcia_release_irq(link->handle, &link->irq);
421     link->state &= ~DEV_CONFIG;
422 } /* elsa_cs_release */
423
424 static int elsa_suspend(struct pcmcia_device *p_dev)
425 {
426         dev_link_t *link = dev_to_instance(p_dev);
427         local_info_t *dev = link->priv;
428
429         link->state |= DEV_SUSPEND;
430         dev->busy = 1;
431         if (link->state & DEV_CONFIG)
432                 pcmcia_release_configuration(link->handle);
433
434         return 0;
435 }
436
437 static int elsa_resume(struct pcmcia_device *p_dev)
438 {
439         dev_link_t *link = dev_to_instance(p_dev);
440         local_info_t *dev = link->priv;
441
442         link->state &= ~DEV_SUSPEND;
443         if (link->state & DEV_CONFIG)
444                 pcmcia_request_configuration(link->handle, &link->conf);
445         dev->busy = 0;
446
447         return 0;
448 }
449
450 /*======================================================================
451
452     The card status event handler.  Mostly, this schedules other
453     stuff to run after an event is received.  A CARD_REMOVAL event
454     also sets some flags to discourage the net drivers from trying
455     to talk to the card any more.
456
457     When a CARD_REMOVAL event is received, we immediately set a flag
458     to block future accesses to this device.  All the functions that
459     actually access the device should check this flag to make sure
460     the card is still present.
461
462 ======================================================================*/
463
464 static int elsa_cs_event(event_t event, int priority,
465                           event_callback_args_t *args)
466 {
467     dev_link_t *link = args->client_data;
468
469     DEBUG(1, "elsa_cs_event(%d)\n", event);
470
471     switch (event) {
472     case CS_EVENT_CARD_INSERTION:
473         link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
474         elsa_cs_config(link);
475         break;
476     }
477     return 0;
478 } /* elsa_cs_event */
479
480 static struct pcmcia_device_id elsa_ids[] = {
481         PCMCIA_DEVICE_PROD_ID12("ELSA AG (Aachen, Germany)", "MicroLink ISDN/MC ", 0x983de2c4, 0x333ba257),
482         PCMCIA_DEVICE_PROD_ID12("ELSA GmbH, Aachen", "MicroLink ISDN/MC ", 0x639e5718, 0x333ba257),
483         PCMCIA_DEVICE_NULL
484 };
485 MODULE_DEVICE_TABLE(pcmcia, elsa_ids);
486
487 static struct pcmcia_driver elsa_cs_driver = {
488         .owner          = THIS_MODULE,
489         .drv            = {
490                 .name   = "elsa_cs",
491         },
492         .attach         = elsa_cs_attach,
493         .event          = elsa_cs_event,
494         .remove         = elsa_cs_detach,
495         .id_table       = elsa_ids,
496         .suspend        = elsa_suspend,
497         .resume         = elsa_resume,
498 };
499
500 static int __init init_elsa_cs(void)
501 {
502         return pcmcia_register_driver(&elsa_cs_driver);
503 }
504
505 static void __exit exit_elsa_cs(void)
506 {
507         pcmcia_unregister_driver(&elsa_cs_driver);
508 }
509
510 module_init(init_elsa_cs);
511 module_exit(exit_elsa_cs);