[PATCH] pcmcia: unify detach, REMOVAL_EVENT handlers into one remove callback
[linux-2.6] / drivers / isdn / hisax / avma1_cs.c
1 /*
2  * PCMCIA client driver for AVM A1 / Fritz!PCMCIA
3  *
4  * Author       Carsten Paeth
5  * Copyright    1998-2001 by Carsten Paeth <calle@calle.in-berlin.de>
6  * 
7  * This software may be used and distributed according to the terms
8  * of the GNU General Public License, incorporated herein by reference.
9  *
10  */
11
12 #include <linux/module.h>
13
14
15 #include <linux/kernel.h>
16 #include <linux/init.h>
17 #include <linux/sched.h>
18 #include <linux/ptrace.h>
19 #include <linux/slab.h>
20 #include <linux/string.h>
21 #include <asm/io.h>
22 #include <asm/system.h>
23
24 #include <pcmcia/cs_types.h>
25 #include <pcmcia/cs.h>
26 #include <pcmcia/cistpl.h>
27 #include <pcmcia/ds.h>
28 #include "hisax_cfg.h"
29
30 MODULE_DESCRIPTION("ISDN4Linux: PCMCIA client driver for AVM A1/Fritz!PCMCIA cards");
31 MODULE_AUTHOR("Carsten Paeth");
32 MODULE_LICENSE("GPL");
33
34 /*
35    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
36    you do not define PCMCIA_DEBUG at all, all the debug code will be
37    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
38    be present but disabled -- but it can then be enabled for specific
39    modules at load time with a 'pc_debug=#' option to insmod.
40 */
41 #ifdef PCMCIA_DEBUG
42 static int pc_debug = PCMCIA_DEBUG;
43 module_param(pc_debug, int, 0);
44 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
45 static char *version =
46 "avma1_cs.c 1.00 1998/01/23 10:00:00 (Carsten Paeth)";
47 #else
48 #define DEBUG(n, args...)
49 #endif
50
51 /*====================================================================*/
52
53 /* Parameters that can be set with 'insmod' */
54
55 static int isdnprot = 2;
56
57 module_param(isdnprot, int, 0);
58
59 /*====================================================================*/
60
61 /*
62    The event() function is this driver's Card Services event handler.
63    It will be called by Card Services when an appropriate card status
64    event is received.  The config() and release() entry points are
65    used to configure or release a socket, in response to card insertion
66    and ejection events.  They are invoked from the skeleton event
67    handler.
68 */
69
70 static void avma1cs_config(dev_link_t *link);
71 static void avma1cs_release(dev_link_t *link);
72 static int avma1cs_event(event_t event, int priority,
73                           event_callback_args_t *args);
74
75 /*
76    The attach() and detach() entry points are used to create and destroy
77    "instances" of the driver, where each instance represents everything
78    needed to manage one actual PCMCIA card.
79 */
80
81 static dev_link_t *avma1cs_attach(void);
82 static void avma1cs_detach(struct pcmcia_device *p_dev);
83
84 /*
85    The dev_info variable is the "key" that is used to match up this
86    device driver with appropriate cards, through the card configuration
87    database.
88 */
89
90 static dev_info_t dev_info = "avma1_cs";
91
92 /*
93    A linked list of "instances" of the skeleton device.  Each actual
94    PCMCIA card corresponds to one device instance, and is described
95    by one dev_link_t structure (defined in ds.h).
96
97    You may not want to use a linked list for this -- for example, the
98    memory card driver uses an array of dev_link_t pointers, where minor
99    device numbers are used to derive the corresponding array index.
100 */
101
102 static dev_link_t *dev_list = NULL;
103
104 /*
105    A dev_link_t structure has fields for most things that are needed
106    to keep track of a socket, but there will usually be some device
107    specific information that also needs to be kept track of.  The
108    'priv' pointer in a dev_link_t structure can be used to point to
109    a device-specific private data structure, like this.
110
111    A driver needs to provide a dev_node_t structure for each device
112    on a card.  In some cases, there is only one device per card (for
113    example, ethernet cards, modems).  In other cases, there may be
114    many actual or logical devices (SCSI adapters, memory cards with
115    multiple partitions).  The dev_node_t structures need to be kept
116    in a linked list starting at the 'dev' field of a dev_link_t
117    structure.  We allocate them in the card's private data structure,
118    because they generally can't be allocated dynamically.
119 */
120    
121 typedef struct local_info_t {
122     dev_node_t  node;
123 } local_info_t;
124
125 /*======================================================================
126
127     avma1cs_attach() creates an "instance" of the driver, allocating
128     local data structures for one device.  The device is registered
129     with Card Services.
130
131     The dev_link structure is initialized, but we don't actually
132     configure the card at this point -- we wait until we receive a
133     card insertion event.
134     
135 ======================================================================*/
136
137 static dev_link_t *avma1cs_attach(void)
138 {
139     client_reg_t client_reg;
140     dev_link_t *link;
141     local_info_t *local;
142     int ret;
143     
144     DEBUG(0, "avma1cs_attach()\n");
145
146     /* Initialize the dev_link_t structure */
147     link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
148     if (!link)
149         return NULL;
150     memset(link, 0, sizeof(struct dev_link_t));
151
152     /* Allocate space for private device-specific data */
153     local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
154     if (!local) {
155         kfree(link);
156         return NULL;
157     }
158     memset(local, 0, sizeof(local_info_t));
159     link->priv = local;
160
161     /* The io structure describes IO port mapping */
162     link->io.NumPorts1 = 16;
163     link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
164     link->io.NumPorts2 = 16;
165     link->io.Attributes2 = IO_DATA_PATH_WIDTH_16;
166     link->io.IOAddrLines = 5;
167
168     /* Interrupt setup */
169     link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
170     link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED;
171
172     link->irq.IRQInfo1 = IRQ_LEVEL_ID;
173
174     /* General socket configuration */
175     link->conf.Attributes = CONF_ENABLE_IRQ;
176     link->conf.Vcc = 50;
177     link->conf.IntType = INT_MEMORY_AND_IO;
178     link->conf.ConfigIndex = 1;
179     link->conf.Present = PRESENT_OPTION;
180
181     /* Register with Card Services */
182     link->next = dev_list;
183     dev_list = link;
184     client_reg.dev_info = &dev_info;
185     client_reg.Version = 0x0210;
186     client_reg.event_callback_args.client_data = link;
187     ret = pcmcia_register_client(&link->handle, &client_reg);
188     if (ret != 0) {
189         cs_error(link->handle, RegisterClient, ret);
190         avma1cs_detach(link->handle);
191         return NULL;
192     }
193
194     return link;
195 } /* avma1cs_attach */
196
197 /*======================================================================
198
199     This deletes a driver "instance".  The device is de-registered
200     with Card Services.  If it has been released, all local data
201     structures are freed.  Otherwise, the structures will be freed
202     when the device is released.
203
204 ======================================================================*/
205
206 static void avma1cs_detach(struct pcmcia_device *p_dev)
207 {
208     dev_link_t *link = dev_to_instance(p_dev);
209     dev_link_t **linkp;
210
211     DEBUG(0, "avma1cs_detach(0x%p)\n", link);
212
213     /* Locate device structure */
214     for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
215         if (*linkp == link) break;
216     if (*linkp == NULL)
217         return;
218
219     if (link->state & DEV_CONFIG)
220             avma1cs_release(link);
221
222     /* Unlink device structure, free pieces */
223     *linkp = link->next;
224     kfree(link->priv);
225     kfree(link);
226 } /* avma1cs_detach */
227
228 /*======================================================================
229
230     avma1cs_config() is scheduled to run after a CARD_INSERTION event
231     is received, to configure the PCMCIA socket, and to make the
232     ethernet device available to the system.
233     
234 ======================================================================*/
235
236 static int get_tuple(client_handle_t handle, tuple_t *tuple,
237                      cisparse_t *parse)
238 {
239     int i = pcmcia_get_tuple_data(handle, tuple);
240     if (i != CS_SUCCESS) return i;
241     return pcmcia_parse_tuple(handle, tuple, parse);
242 }
243
244 static int first_tuple(client_handle_t handle, tuple_t *tuple,
245                      cisparse_t *parse)
246 {
247     int i = pcmcia_get_first_tuple(handle, tuple);
248     if (i != CS_SUCCESS) return i;
249     return get_tuple(handle, tuple, parse);
250 }
251
252 static int next_tuple(client_handle_t handle, tuple_t *tuple,
253                      cisparse_t *parse)
254 {
255     int i = pcmcia_get_next_tuple(handle, tuple);
256     if (i != CS_SUCCESS) return i;
257     return get_tuple(handle, tuple, parse);
258 }
259
260 static void avma1cs_config(dev_link_t *link)
261 {
262     client_handle_t handle;
263     tuple_t tuple;
264     cisparse_t parse;
265     cistpl_cftable_entry_t *cf = &parse.cftable_entry;
266     local_info_t *dev;
267     int i;
268     u_char buf[64];
269     char devname[128];
270     IsdnCard_t  icard;
271     int busy = 0;
272     
273     handle = link->handle;
274     dev = link->priv;
275
276     DEBUG(0, "avma1cs_config(0x%p)\n", link);
277
278     /*
279        This reads the card's CONFIG tuple to find its configuration
280        registers.
281     */
282     do {
283         tuple.DesiredTuple = CISTPL_CONFIG;
284         i = pcmcia_get_first_tuple(handle, &tuple);
285         if (i != CS_SUCCESS) break;
286         tuple.TupleData = buf;
287         tuple.TupleDataMax = 64;
288         tuple.TupleOffset = 0;
289         i = pcmcia_get_tuple_data(handle, &tuple);
290         if (i != CS_SUCCESS) break;
291         i = pcmcia_parse_tuple(handle, &tuple, &parse);
292         if (i != CS_SUCCESS) break;
293         link->conf.ConfigBase = parse.config.base;
294     } while (0);
295     if (i != CS_SUCCESS) {
296         cs_error(link->handle, ParseTuple, i);
297         link->state &= ~DEV_CONFIG_PENDING;
298         return;
299     }
300     
301     /* Configure card */
302     link->state |= DEV_CONFIG;
303
304     do {
305
306         tuple.Attributes = 0;
307         tuple.TupleData = buf;
308         tuple.TupleDataMax = 254;
309         tuple.TupleOffset = 0;
310         tuple.DesiredTuple = CISTPL_VERS_1;
311
312         devname[0] = 0;
313         if( !first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 1 ) {
314             strlcpy(devname,parse.version_1.str + parse.version_1.ofs[1], 
315                         sizeof(devname));
316         }
317         /*
318          * find IO port
319          */
320         tuple.TupleData = (cisdata_t *)buf;
321         tuple.TupleOffset = 0; tuple.TupleDataMax = 255;
322         tuple.Attributes = 0;
323         tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
324         i = first_tuple(handle, &tuple, &parse);
325         while (i == CS_SUCCESS) {
326             if (cf->io.nwin > 0) {
327                 link->conf.ConfigIndex = cf->index;
328                 link->io.BasePort1 = cf->io.win[0].base;
329                 link->io.NumPorts1 = cf->io.win[0].len;
330                 link->io.NumPorts2 = 0;
331                 printk(KERN_INFO "avma1_cs: testing i/o %#x-%#x\n",
332                         link->io.BasePort1,
333                         link->io.BasePort1+link->io.NumPorts1 - 1);
334                 i = pcmcia_request_io(link->handle, &link->io);
335                 if (i == CS_SUCCESS) goto found_port;
336             }
337             i = next_tuple(handle, &tuple, &parse);
338         }
339
340 found_port:
341         if (i != CS_SUCCESS) {
342             cs_error(link->handle, RequestIO, i);
343             break;
344         }
345         
346         /*
347          * allocate an interrupt line
348          */
349         i = pcmcia_request_irq(link->handle, &link->irq);
350         if (i != CS_SUCCESS) {
351             cs_error(link->handle, RequestIRQ, i);
352             pcmcia_release_io(link->handle, &link->io);
353             break;
354         }
355         
356         /*
357          * configure the PCMCIA socket
358          */
359         i = pcmcia_request_configuration(link->handle, &link->conf);
360         if (i != CS_SUCCESS) {
361             cs_error(link->handle, RequestConfiguration, i);
362             pcmcia_release_io(link->handle, &link->io);
363             pcmcia_release_irq(link->handle, &link->irq);
364             break;
365         }
366
367     } while (0);
368
369     /* At this point, the dev_node_t structure(s) should be
370        initialized and arranged in a linked list at link->dev. */
371
372     strcpy(dev->node.dev_name, "A1");
373     dev->node.major = 45;
374     dev->node.minor = 0;
375     link->dev = &dev->node;
376     
377     link->state &= ~DEV_CONFIG_PENDING;
378     /* If any step failed, release any partially configured state */
379     if (i != 0) {
380         avma1cs_release(link);
381         return;
382     }
383
384     printk(KERN_NOTICE "avma1_cs: checking at i/o %#x, irq %d\n",
385                                 link->io.BasePort1, link->irq.AssignedIRQ);
386
387     icard.para[0] = link->irq.AssignedIRQ;
388     icard.para[1] = link->io.BasePort1;
389     icard.protocol = isdnprot;
390     icard.typ = ISDN_CTYPE_A1_PCMCIA;
391     
392     i = hisax_init_pcmcia(link, &busy, &icard);
393     if (i < 0) {
394         printk(KERN_ERR "avma1_cs: failed to initialize AVM A1 PCMCIA %d at i/o %#x\n", i, link->io.BasePort1);
395         avma1cs_release(link);
396         return;
397     }
398     dev->node.minor = i;
399
400 } /* avma1cs_config */
401
402 /*======================================================================
403
404     After a card is removed, avma1cs_release() will unregister the net
405     device, and release the PCMCIA configuration.  If the device is
406     still open, this will be postponed until it is closed.
407     
408 ======================================================================*/
409
410 static void avma1cs_release(dev_link_t *link)
411 {
412     local_info_t *local = link->priv;
413
414     DEBUG(0, "avma1cs_release(0x%p)\n", link);
415
416     /* no unregister function with hisax */
417     HiSax_closecard(local->node.minor);
418
419     /* Unlink the device chain */
420     link->dev = NULL;
421     
422     /* Don't bother checking to see if these succeed or not */
423     pcmcia_release_configuration(link->handle);
424     pcmcia_release_io(link->handle, &link->io);
425     pcmcia_release_irq(link->handle, &link->irq);
426     link->state &= ~DEV_CONFIG;
427 } /* avma1cs_release */
428
429 static int avma1cs_suspend(struct pcmcia_device *dev)
430 {
431         dev_link_t *link = dev_to_instance(dev);
432
433         link->state |= DEV_SUSPEND;
434         if (link->state & DEV_CONFIG)
435                 pcmcia_release_configuration(link->handle);
436
437         return 0;
438 }
439
440 static int avma1cs_resume(struct pcmcia_device *dev)
441 {
442         dev_link_t *link = dev_to_instance(dev);
443
444         link->state &= ~DEV_SUSPEND;
445         if (link->state & DEV_CONFIG)
446                 pcmcia_request_configuration(link->handle, &link->conf);
447
448         return 0;
449 }
450
451 /*======================================================================
452
453     The card status event handler.  Mostly, this schedules other
454     stuff to run after an event is received.  A CARD_REMOVAL event
455     also sets some flags to discourage the net drivers from trying
456     to talk to the card any more.
457
458     When a CARD_REMOVAL event is received, we immediately set a flag
459     to block future accesses to this device.  All the functions that
460     actually access the device should check this flag to make sure
461     the card is still present.
462     
463 ======================================================================*/
464
465 static int avma1cs_event(event_t event, int priority,
466                           event_callback_args_t *args)
467 {
468     dev_link_t *link = args->client_data;
469
470     DEBUG(1, "avma1cs_event(0x%06x)\n", event);
471     
472     switch (event) {
473         case CS_EVENT_CARD_INSERTION:
474             link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
475             avma1cs_config(link);
476             break;
477     }
478     return 0;
479 } /* avma1cs_event */
480
481 static struct pcmcia_device_id avma1cs_ids[] = {
482         PCMCIA_DEVICE_PROD_ID12("AVM", "ISDN A", 0x95d42008, 0xadc9d4bb),
483         PCMCIA_DEVICE_PROD_ID12("ISDN", "CARD", 0x8d9761c8, 0x01c5aa7b),
484         PCMCIA_DEVICE_NULL
485 };
486 MODULE_DEVICE_TABLE(pcmcia, avma1cs_ids);
487
488 static struct pcmcia_driver avma1cs_driver = {
489         .owner          = THIS_MODULE,
490         .drv            = {
491                 .name   = "avma1_cs",
492         },
493         .attach         = avma1cs_attach,
494         .event          = avma1cs_event,
495         .remove         = avma1cs_detach,
496         .id_table       = avma1cs_ids,
497         .suspend        = avma1cs_suspend,
498         .resume         = avma1cs_resume,
499 };
500  
501 /*====================================================================*/
502
503 static int __init init_avma1_cs(void)
504 {
505         return(pcmcia_register_driver(&avma1cs_driver));
506 }
507
508 static void __exit exit_avma1_cs(void)
509 {
510         pcmcia_unregister_driver(&avma1cs_driver);
511         BUG_ON(dev_list != NULL);
512 }
513
514 module_init(init_avma1_cs);
515 module_exit(exit_avma1_cs);