Linux-2.6.12-rc2
[linux-flexiantxendom0-natty.git] / drivers / net / wireless / airo_cs.c
1 /*======================================================================
2
3     Aironet driver for 4500 and 4800 series cards
4
5     This code is released under both the GPL version 2 and BSD licenses.
6     Either license may be used.  The respective licenses are found at
7     the end of this file.
8
9     This code was developed by Benjamin Reed <breed@users.sourceforge.net>
10     including portions of which come from the Aironet PC4500
11     Developer's Reference Manual and used with permission.  Copyright
12     (C) 1999 Benjamin Reed.  All Rights Reserved.  Permission to use
13     code in the Developer's manual was granted for this driver by
14     Aironet.
15
16     In addition this module was derived from dummy_cs.
17     The initial developer of dummy_cs is David A. Hinds
18     <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
19     are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.    
20     
21 ======================================================================*/
22
23 #include <linux/config.h>
24 #ifdef __IN_PCMCIA_PACKAGE__
25 #include <pcmcia/k_compat.h>
26 #endif
27 #include <linux/init.h>
28 #include <linux/kernel.h>
29 #include <linux/module.h>
30 #include <linux/ptrace.h>
31 #include <linux/slab.h>
32 #include <linux/string.h>
33 #include <linux/timer.h>
34 #include <linux/netdevice.h>
35
36 #include <pcmcia/version.h>
37 #include <pcmcia/cs_types.h>
38 #include <pcmcia/cs.h>
39 #include <pcmcia/cistpl.h>
40 #include <pcmcia/cisreg.h>
41 #include <pcmcia/ds.h>
42
43 #include <asm/io.h>
44 #include <asm/system.h>
45
46 /*
47    All the PCMCIA modules use PCMCIA_DEBUG to control debugging.  If
48    you do not define PCMCIA_DEBUG at all, all the debug code will be
49    left out.  If you compile with PCMCIA_DEBUG=0, the debug code will
50    be present but disabled -- but it can then be enabled for specific
51    modules at load time with a 'pc_debug=#' option to insmod.
52 */
53 #ifdef PCMCIA_DEBUG
54 static int pc_debug = PCMCIA_DEBUG;
55 module_param(pc_debug, int, 0);
56 static char *version = "$Revision: 1.2 $";
57 #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args);
58 #else
59 #define DEBUG(n, args...)
60 #endif
61
62 /*====================================================================*/
63
64 MODULE_AUTHOR("Benjamin Reed");
65 MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \
66                    cards.  This is the module that links the PCMCIA card \
67                    with the airo module.");
68 MODULE_LICENSE("Dual BSD/GPL");
69 MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards");
70
71 /*====================================================================*/
72
73 /*
74    The event() function is this driver's Card Services event handler.
75    It will be called by Card Services when an appropriate card status
76    event is received.  The config() and release() entry points are
77    used to configure or release a socket, in response to card
78    insertion and ejection events.  They are invoked from the airo_cs
79    event handler. 
80 */
81
82 struct net_device *init_airo_card( int, int, int, struct device * );
83 void stop_airo_card( struct net_device *, int );
84 int reset_airo_card( struct net_device * );
85
86 static void airo_config(dev_link_t *link);
87 static void airo_release(dev_link_t *link);
88 static int airo_event(event_t event, int priority,
89                        event_callback_args_t *args);
90
91 /*
92    The attach() and detach() entry points are used to create and destroy
93    "instances" of the driver, where each instance represents everything
94    needed to manage one actual PCMCIA card.
95 */
96
97 static dev_link_t *airo_attach(void);
98 static void airo_detach(dev_link_t *);
99
100 /*
101    You'll also need to prototype all the functions that will actually
102    be used to talk to your device.  See 'pcmem_cs' for a good example
103    of a fully self-sufficient driver; the other drivers rely more or
104    less on other parts of the kernel.
105 */
106
107 /*
108    The dev_info variable is the "key" that is used to match up this
109    device driver with appropriate cards, through the card configuration
110    database.
111 */
112
113 static dev_info_t dev_info = "airo_cs";
114
115 /*
116    A linked list of "instances" of the  aironet device.  Each actual
117    PCMCIA card corresponds to one device instance, and is described
118    by one dev_link_t structure (defined in ds.h).
119
120    You may not want to use a linked list for this -- for example, the
121    memory card driver uses an array of dev_link_t pointers, where minor
122    device numbers are used to derive the corresponding array index.
123 */
124
125 static dev_link_t *dev_list = NULL;
126
127 /*
128    A dev_link_t structure has fields for most things that are needed
129    to keep track of a socket, but there will usually be some device
130    specific information that also needs to be kept track of.  The
131    'priv' pointer in a dev_link_t structure can be used to point to
132    a device-specific private data structure, like this.
133
134    A driver needs to provide a dev_node_t structure for each device
135    on a card.  In some cases, there is only one device per card (for
136    example, ethernet cards, modems).  In other cases, there may be
137    many actual or logical devices (SCSI adapters, memory cards with
138    multiple partitions).  The dev_node_t structures need to be kept
139    in a linked list starting at the 'dev' field of a dev_link_t
140    structure.  We allocate them in the card's private data structure,
141    because they generally shouldn't be allocated dynamically.
142
143    In this case, we also provide a flag to indicate if a device is
144    "stopped" due to a power management event, or card ejection.  The
145    device IO routines can use a flag like this to throttle IO to a
146    card that is not ready to accept it.
147 */
148    
149 typedef struct local_info_t {
150         dev_node_t      node;
151         struct net_device *eth_dev;
152 } local_info_t;
153
154 /*======================================================================
155   
156   airo_attach() creates an "instance" of the driver, allocating
157   local data structures for one device.  The device is registered
158   with Card Services.
159   
160   The dev_link structure is initialized, but we don't actually
161   configure the card at this point -- we wait until we receive a
162   card insertion event.
163   
164   ======================================================================*/
165
166 static dev_link_t *airo_attach(void)
167 {
168         client_reg_t client_reg;
169         dev_link_t *link;
170         local_info_t *local;
171         int ret;
172         
173         DEBUG(0, "airo_attach()\n");
174
175         /* Initialize the dev_link_t structure */
176         link = kmalloc(sizeof(struct dev_link_t), GFP_KERNEL);
177         if (!link) {
178                 printk(KERN_ERR "airo_cs: no memory for new device\n");
179                 return NULL;
180         }
181         memset(link, 0, sizeof(struct dev_link_t));
182         
183         /* Interrupt setup */
184         link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
185         link->irq.IRQInfo1 = IRQ_LEVEL_ID;
186         link->irq.Handler = NULL;
187         
188         /*
189           General socket configuration defaults can go here.  In this
190           client, we assume very little, and rely on the CIS for almost
191           everything.  In most clients, many details (i.e., number, sizes,
192           and attributes of IO windows) are fixed by the nature of the
193           device, and can be hard-wired here.
194         */
195         link->conf.Attributes = 0;
196         link->conf.Vcc = 50;
197         link->conf.IntType = INT_MEMORY_AND_IO;
198         
199         /* Allocate space for private device-specific data */
200         local = kmalloc(sizeof(local_info_t), GFP_KERNEL);
201         if (!local) {
202                 printk(KERN_ERR "airo_cs: no memory for new device\n");
203                 kfree (link);
204                 return NULL;
205         }
206         memset(local, 0, sizeof(local_info_t));
207         link->priv = local;
208         
209         /* Register with Card Services */
210         link->next = dev_list;
211         dev_list = link;
212         client_reg.dev_info = &dev_info;
213         client_reg.EventMask =
214                 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
215                 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
216                 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
217         client_reg.event_handler = &airo_event;
218         client_reg.Version = 0x0210;
219         client_reg.event_callback_args.client_data = link;
220         ret = pcmcia_register_client(&link->handle, &client_reg);
221         if (ret != 0) {
222                 cs_error(link->handle, RegisterClient, ret);
223                 airo_detach(link);
224                 return NULL;
225         }
226         
227         return link;
228 } /* airo_attach */
229
230 /*======================================================================
231   
232   This deletes a driver "instance".  The device is de-registered
233   with Card Services.  If it has been released, all local data
234   structures are freed.  Otherwise, the structures will be freed
235   when the device is released.
236   
237   ======================================================================*/
238
239 static void airo_detach(dev_link_t *link)
240 {
241         dev_link_t **linkp;
242         
243         DEBUG(0, "airo_detach(0x%p)\n", link);
244         
245         /* Locate device structure */
246         for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next)
247                 if (*linkp == link) break;
248         if (*linkp == NULL)
249                 return;
250         
251         if (link->state & DEV_CONFIG)
252                 airo_release(link);
253         
254         if ( ((local_info_t*)link->priv)->eth_dev ) {
255                 stop_airo_card( ((local_info_t*)link->priv)->eth_dev, 0 );
256         }
257         ((local_info_t*)link->priv)->eth_dev = NULL;   
258         
259         /* Break the link with Card Services */
260         if (link->handle)
261                 pcmcia_deregister_client(link->handle);
262         
263         
264         
265         /* Unlink device structure, free pieces */
266         *linkp = link->next;
267         if (link->priv) {
268                 kfree(link->priv);
269         }
270         kfree(link);
271         
272 } /* airo_detach */
273
274 /*======================================================================
275   
276   airo_config() is scheduled to run after a CARD_INSERTION event
277   is received, to configure the PCMCIA socket, and to make the
278   device available to the system.
279   
280   ======================================================================*/
281
282 #define CS_CHECK(fn, ret) \
283 do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0)
284
285 static void airo_config(dev_link_t *link)
286 {
287         client_handle_t handle;
288         tuple_t tuple;
289         cisparse_t parse;
290         local_info_t *dev;
291         int last_fn, last_ret;
292         u_char buf[64];
293         win_req_t req;
294         memreq_t map;
295         
296         handle = link->handle;
297         dev = link->priv;
298
299         DEBUG(0, "airo_config(0x%p)\n", link);
300         
301         /*
302           This reads the card's CONFIG tuple to find its configuration
303           registers.
304         */
305         tuple.DesiredTuple = CISTPL_CONFIG;
306         tuple.Attributes = 0;
307         tuple.TupleData = buf;
308         tuple.TupleDataMax = sizeof(buf);
309         tuple.TupleOffset = 0;
310         CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
311         CS_CHECK(GetTupleData, pcmcia_get_tuple_data(handle, &tuple));
312         CS_CHECK(ParseTuple, pcmcia_parse_tuple(handle, &tuple, &parse));
313         link->conf.ConfigBase = parse.config.base;
314         link->conf.Present = parse.config.rmask[0];
315         
316         /* Configure card */
317         link->state |= DEV_CONFIG;
318         
319         /*
320           In this loop, we scan the CIS for configuration table entries,
321           each of which describes a valid card configuration, including
322           voltage, IO window, memory window, and interrupt settings.
323           
324           We make no assumptions about the card to be configured: we use
325           just the information available in the CIS.  In an ideal world,
326           this would work for any PCMCIA card, but it requires a complete
327           and accurate CIS.  In practice, a driver usually "knows" most of
328           these things without consulting the CIS, and most client drivers
329           will only use the CIS to fill in implementation-defined details.
330         */
331         tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;
332         CS_CHECK(GetFirstTuple, pcmcia_get_first_tuple(handle, &tuple));
333         while (1) {
334                 cistpl_cftable_entry_t dflt = { 0 };
335                 cistpl_cftable_entry_t *cfg = &(parse.cftable_entry);
336                 if (pcmcia_get_tuple_data(handle, &tuple) != 0 ||
337                                 pcmcia_parse_tuple(handle, &tuple, &parse) != 0)
338                         goto next_entry;
339                 
340                 if (cfg->flags & CISTPL_CFTABLE_DEFAULT) dflt = *cfg;
341                 if (cfg->index == 0) goto next_entry;
342                 link->conf.ConfigIndex = cfg->index;
343                 
344                 /* Does this card need audio output? */
345                 if (cfg->flags & CISTPL_CFTABLE_AUDIO) {
346                         link->conf.Attributes |= CONF_ENABLE_SPKR;
347                         link->conf.Status = CCSR_AUDIO_ENA;
348                 }
349                 
350                 /* Use power settings for Vcc and Vpp if present */
351                 /*  Note that the CIS values need to be rescaled */
352                 if (cfg->vcc.present & (1<<CISTPL_POWER_VNOM))
353                         link->conf.Vcc = cfg->vcc.param[CISTPL_POWER_VNOM]/10000;
354                 else if (dflt.vcc.present & (1<<CISTPL_POWER_VNOM))
355                         link->conf.Vcc = dflt.vcc.param[CISTPL_POWER_VNOM]/10000;
356                 
357                 if (cfg->vpp1.present & (1<<CISTPL_POWER_VNOM))
358                         link->conf.Vpp1 = link->conf.Vpp2 =
359                                 cfg->vpp1.param[CISTPL_POWER_VNOM]/10000;
360                 else if (dflt.vpp1.present & (1<<CISTPL_POWER_VNOM))
361                         link->conf.Vpp1 = link->conf.Vpp2 =
362                                 dflt.vpp1.param[CISTPL_POWER_VNOM]/10000;
363                 
364                 /* Do we need to allocate an interrupt? */
365                 if (cfg->irq.IRQInfo1 || dflt.irq.IRQInfo1)
366                         link->conf.Attributes |= CONF_ENABLE_IRQ;
367                 
368                 /* IO window settings */
369                 link->io.NumPorts1 = link->io.NumPorts2 = 0;
370                 if ((cfg->io.nwin > 0) || (dflt.io.nwin > 0)) {
371                         cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt.io;
372                         link->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO;
373                         if (!(io->flags & CISTPL_IO_8BIT))
374                                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_16;
375                         if (!(io->flags & CISTPL_IO_16BIT))
376                                 link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;
377                         link->io.BasePort1 = io->win[0].base;
378                         link->io.NumPorts1 = io->win[0].len;
379                         if (io->nwin > 1) {
380                                 link->io.Attributes2 = link->io.Attributes1;
381                                 link->io.BasePort2 = io->win[1].base;
382                                 link->io.NumPorts2 = io->win[1].len;
383                         }
384                 }
385                 
386                 /* This reserves IO space but doesn't actually enable it */
387                 if (pcmcia_request_io(link->handle, &link->io) != 0)
388                         goto next_entry;
389                 
390                 /*
391                   Now set up a common memory window, if needed.  There is room
392                   in the dev_link_t structure for one memory window handle,
393                   but if the base addresses need to be saved, or if multiple
394                   windows are needed, the info should go in the private data
395                   structure for this device.
396                   
397                   Note that the memory window base is a physical address, and
398                   needs to be mapped to virtual space with ioremap() before it
399                   is used.
400                 */
401                 if ((cfg->mem.nwin > 0) || (dflt.mem.nwin > 0)) {
402                         cistpl_mem_t *mem =
403                                 (cfg->mem.nwin) ? &cfg->mem : &dflt.mem;
404                         req.Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM;
405                         req.Base = mem->win[0].host_addr;
406                         req.Size = mem->win[0].len;
407                         req.AccessSpeed = 0;
408                         if (pcmcia_request_window(&link->handle, &req, &link->win) != 0)
409                                 goto next_entry;
410                         map.Page = 0; map.CardOffset = mem->win[0].card_addr;
411                         if (pcmcia_map_mem_page(link->win, &map) != 0)
412                                 goto next_entry;
413                 }
414                 /* If we got this far, we're cool! */
415                 break;
416                 
417         next_entry:
418                 CS_CHECK(GetNextTuple, pcmcia_get_next_tuple(handle, &tuple));
419         }
420         
421     /*
422       Allocate an interrupt line.  Note that this does not assign a
423       handler to the interrupt, unless the 'Handler' member of the
424       irq structure is initialized.
425     */
426         if (link->conf.Attributes & CONF_ENABLE_IRQ)
427                 CS_CHECK(RequestIRQ, pcmcia_request_irq(link->handle, &link->irq));
428         
429         /*
430           This actually configures the PCMCIA socket -- setting up
431           the I/O windows and the interrupt mapping, and putting the
432           card and host interface into "Memory and IO" mode.
433         */
434         CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link->handle, &link->conf));
435         ((local_info_t*)link->priv)->eth_dev = 
436                 init_airo_card( link->irq.AssignedIRQ,
437                                 link->io.BasePort1, 1, &handle_to_dev(handle) );
438         if (!((local_info_t*)link->priv)->eth_dev) goto cs_failed;
439         
440         /*
441           At this point, the dev_node_t structure(s) need to be
442           initialized and arranged in a linked list at link->dev.
443         */
444         strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name );
445         dev->node.major = dev->node.minor = 0;
446         link->dev = &dev->node;
447         
448         /* Finally, report what we've done */
449         printk(KERN_INFO "%s: index 0x%02x: Vcc %d.%d",
450                dev->node.dev_name, link->conf.ConfigIndex,
451                link->conf.Vcc/10, link->conf.Vcc%10);
452         if (link->conf.Vpp1)
453                 printk(", Vpp %d.%d", link->conf.Vpp1/10, link->conf.Vpp1%10);
454         if (link->conf.Attributes & CONF_ENABLE_IRQ)
455                 printk(", irq %d", link->irq.AssignedIRQ);
456         if (link->io.NumPorts1)
457                 printk(", io 0x%04x-0x%04x", link->io.BasePort1,
458                        link->io.BasePort1+link->io.NumPorts1-1);
459         if (link->io.NumPorts2)
460                 printk(" & 0x%04x-0x%04x", link->io.BasePort2,
461                        link->io.BasePort2+link->io.NumPorts2-1);
462         if (link->win)
463                 printk(", mem 0x%06lx-0x%06lx", req.Base,
464                        req.Base+req.Size-1);
465         printk("\n");
466         
467         link->state &= ~DEV_CONFIG_PENDING;
468         return;
469         
470  cs_failed:
471         cs_error(link->handle, last_fn, last_ret);
472         airo_release(link);
473         
474 } /* airo_config */
475
476 /*======================================================================
477   
478   After a card is removed, airo_release() will unregister the
479   device, and release the PCMCIA configuration.  If the device is
480   still open, this will be postponed until it is closed.
481   
482   ======================================================================*/
483
484 static void airo_release(dev_link_t *link)
485 {
486         DEBUG(0, "airo_release(0x%p)\n", link);
487         
488         /* Unlink the device chain */
489         link->dev = NULL;
490         
491         /*
492           In a normal driver, additional code may be needed to release
493           other kernel data structures associated with this device. 
494         */
495         
496         /* Don't bother checking to see if these succeed or not */
497         if (link->win)
498                 pcmcia_release_window(link->win);
499         pcmcia_release_configuration(link->handle);
500         if (link->io.NumPorts1)
501                 pcmcia_release_io(link->handle, &link->io);
502         if (link->irq.AssignedIRQ)
503                 pcmcia_release_irq(link->handle, &link->irq);
504         link->state &= ~DEV_CONFIG;
505 }
506
507 /*======================================================================
508   
509   The card status event handler.  Mostly, this schedules other
510   stuff to run after an event is received.
511
512   When a CARD_REMOVAL event is received, we immediately set a
513   private flag to block future accesses to this device.  All the
514   functions that actually access the device should check this flag
515   to make sure the card is still present.
516   
517   ======================================================================*/
518
519 static int airo_event(event_t event, int priority,
520                       event_callback_args_t *args)
521 {
522         dev_link_t *link = args->client_data;
523         local_info_t *local = link->priv;
524         
525         DEBUG(1, "airo_event(0x%06x)\n", event);
526         
527         switch (event) {
528         case CS_EVENT_CARD_REMOVAL:
529                 link->state &= ~DEV_PRESENT;
530                 if (link->state & DEV_CONFIG) {
531                         netif_device_detach(local->eth_dev);
532                         airo_release(link);
533                 }
534                 break;
535         case CS_EVENT_CARD_INSERTION:
536                 link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;
537                 airo_config(link);
538                 break;
539         case CS_EVENT_PM_SUSPEND:
540                 link->state |= DEV_SUSPEND;
541                 /* Fall through... */
542         case CS_EVENT_RESET_PHYSICAL:
543                 if (link->state & DEV_CONFIG) {
544                         netif_device_detach(local->eth_dev);
545                         pcmcia_release_configuration(link->handle);
546                 }
547                 break;
548         case CS_EVENT_PM_RESUME:
549                 link->state &= ~DEV_SUSPEND;
550                 /* Fall through... */
551         case CS_EVENT_CARD_RESET:
552                 if (link->state & DEV_CONFIG) {
553                         pcmcia_request_configuration(link->handle, &link->conf);
554                         reset_airo_card(local->eth_dev);
555                         netif_device_attach(local->eth_dev);
556                 }
557                 break;
558         }
559         return 0;
560 } /* airo_event */
561
562 static struct pcmcia_driver airo_driver = {
563         .owner          = THIS_MODULE,
564         .drv            = {
565                 .name   = "airo_cs",
566         },
567         .attach         = airo_attach,
568         .detach         = airo_detach,
569 };
570
571 static int airo_cs_init(void)
572 {
573         return pcmcia_register_driver(&airo_driver);
574 }
575
576 static void airo_cs_cleanup(void)
577 {
578         pcmcia_unregister_driver(&airo_driver);
579         BUG_ON(dev_list != NULL);
580 }
581
582 /*
583     This program is free software; you can redistribute it and/or
584     modify it under the terms of the GNU General Public License
585     as published by the Free Software Foundation; either version 2
586     of the License, or (at your option) any later version.
587
588     This program is distributed in the hope that it will be useful,
589     but WITHOUT ANY WARRANTY; without even the implied warranty of
590     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
591     GNU General Public License for more details.
592
593     In addition:
594
595     Redistribution and use in source and binary forms, with or without
596     modification, are permitted provided that the following conditions
597     are met:
598
599     1. Redistributions of source code must retain the above copyright
600        notice, this list of conditions and the following disclaimer.
601     2. Redistributions in binary form must reproduce the above copyright
602        notice, this list of conditions and the following disclaimer in the
603        documentation and/or other materials provided with the distribution.
604     3. The name of the author may not be used to endorse or promote
605        products derived from this software without specific prior written
606        permission.
607
608     THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
609     IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
610     WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
611     ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
612     INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
613     (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
614     SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
615     HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
616     STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
617     IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
618     POSSIBILITY OF SUCH DAMAGE.    
619 */
620
621 module_init(airo_cs_init);
622 module_exit(airo_cs_cleanup);