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