Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / net / wireless / airo.c
index fb10a2d..00764dd 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/interrupt.h>
 #include <linux/in.h>
 #include <linux/bitops.h>
+#include <linux/scatterlist.h>
+#include <linux/crypto.h>
 #include <asm/io.h>
 #include <asm/system.h>
 
@@ -46,6 +48,8 @@
 #include <linux/pci.h>
 #include <asm/uaccess.h>
 
+#include "airo.h"
+
 #ifdef CONFIG_PCI
 static struct pci_device_id card_ids[] = {
        { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, },
@@ -84,14 +88,6 @@ static struct pci_driver airo_driver = {
 #include <linux/delay.h>
 #endif
 
-/* Support Cisco MIC feature */
-#define MICSUPPORT
-
-#if defined(MICSUPPORT) && !defined(CONFIG_CRYPTO)
-#warning MIC support requires Crypto API
-#undef MICSUPPORT
-#endif
-
 /* Hack to do some power saving */
 #define POWER_ON_DOWN
 
@@ -773,6 +769,11 @@ typedef struct {
   u16 atimWindow;
 } BSSListRid;
 
+typedef struct {
+  BSSListRid bss;
+  struct list_head list;
+} BSSListElement;
+
 typedef struct {
   u8 rssipct;
   u8 rssidBm;
@@ -900,12 +901,13 @@ typedef struct aironet_ioctl {
        unsigned char __user *data;     // d-data
 } aironet_ioctl;
 
-static char *swversion = "2.1";
+static char swversion[] = "2.1";
 #endif /* CISCO_EXT */
 
 #define NUM_MODULES       2
 #define MIC_MSGLEN_MAX    2400
 #define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX
+#define AIRO_DEF_MTU      2312
 
 typedef struct {
        u32   size;            // size
@@ -1040,13 +1042,12 @@ typedef struct {
        u16 status;
 } WifiCtlHdr;
 
-WifiCtlHdr wifictlhdr8023 = {
+static WifiCtlHdr wifictlhdr8023 = {
        .ctlhdr = {
                .ctl    = HOST_DONT_RLSE,
        }
 };
 
-#ifdef WIRELESS_EXT
 // Frequency list (map channels to frequencies)
 static const long frequency_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442,
                                2447, 2452, 2457, 2462, 2467, 2472, 2484 };
@@ -1067,7 +1068,6 @@ typedef struct wep_key_t {
 
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def     airo_handler_def;
-#endif /* WIRELESS_EXT */
 
 static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)";
 
@@ -1110,16 +1110,13 @@ static irqreturn_t airo_interrupt( int irq, void* dev_id, struct pt_regs
 static int airo_thread(void *data);
 static void timer_func( struct net_device *dev );
 static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-#ifdef WIRELESS_EXT
-struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
+static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev);
 static void airo_read_wireless_stats (struct airo_info *local);
-#endif /* WIRELESS_EXT */
 #ifdef CISCO_EXT
 static int readrids(struct net_device *dev, aironet_ioctl *comp);
 static int writerids(struct net_device *dev, aironet_ioctl *comp);
-int flashcard(struct net_device *dev, aironet_ioctl *comp);
+static int flashcard(struct net_device *dev, aironet_ioctl *comp);
 #endif /* CISCO_EXT */
-#ifdef MICSUPPORT
 static void micinit(struct airo_info *ai);
 static int micsetup(struct airo_info *ai);
 static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len);
@@ -1128,8 +1125,7 @@ static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket,
 static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi);
 static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm);
 
-#include <linux/crypto.h>
-#endif
+static void airo_networks_free(struct airo_info *ai);
 
 struct airo_info {
        struct net_device_stats stats;
@@ -1162,7 +1158,7 @@ struct airo_info {
 #define FLAG_COMMIT    13
 #define FLAG_RESET     14
 #define FLAG_FLASHING  15
-#define JOB_MASK       0x1ff0000
+#define JOB_MASK       0x2ff0000
 #define JOB_DIE                16
 #define JOB_XMIT       17
 #define JOB_XMIT11     18
@@ -1172,6 +1168,7 @@ struct airo_info {
 #define JOB_EVENT      22
 #define JOB_AUTOWEP    23
 #define JOB_WSTATS     24
+#define JOB_SCAN_RESULTS  25
        int (*bap_read)(struct airo_info*, u16 *pu16Dst, int bytelen,
                        int whichbap);
        unsigned short *flash;
@@ -1187,18 +1184,14 @@ struct airo_info {
                int fid;
        } xmit, xmit11;
        struct net_device *wifidev;
-#ifdef WIRELESS_EXT
        struct iw_statistics    wstats;         // wireless stats
-       unsigned long           scan_timestamp; /* Time started to scan */
+       unsigned long           scan_timeout;   /* Time scan should be read */
        struct iw_spy_data      spy_data;
        struct iw_public_data   wireless_data;
-#endif /* WIRELESS_EXT */
-#ifdef MICSUPPORT
        /* MIC stuff */
        struct crypto_tfm       *tfm;
        mic_module              mod[2];
        mic_statistics          micstats;
-#endif
        HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors
        HostTxDesc txfids[MPI_MAX_FIDS];
        HostRidDesc config_desc;
@@ -1209,11 +1202,15 @@ struct airo_info {
        unsigned char           __iomem *pciaux;
        unsigned char           *shared;
        dma_addr_t              shared_dma;
-       int                     power;
+       pm_message_t            power;
        SsidRid                 *SSID;
        APListRid               *APList;
 #define        PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
        char                    proc_name[IFNAMSIZ];
+
+       struct list_head network_list;
+       struct list_head network_free_list;
+       BSSListElement *networks;
 };
 
 static inline int bap_read(struct airo_info *ai, u16 *pu16Dst, int bytelen,
@@ -1226,7 +1223,28 @@ static int setup_proc_entry( struct net_device *dev,
 static int takedown_proc_entry( struct net_device *dev,
                                struct airo_info *apriv );
 
-#ifdef MICSUPPORT
+static int cmdreset(struct airo_info *ai);
+static int setflashmode (struct airo_info *ai);
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime);
+static int flashputbuf(struct airo_info *ai);
+static int flashrestart(struct airo_info *ai,struct net_device *dev);
+
+#define airo_print(type, name, fmt, args...) \
+       { printk(type "airo(%s): " fmt "\n", name, ##args); }
+
+#define airo_print_info(name, fmt, args...) \
+       airo_print(KERN_INFO, name, fmt, ##args)
+
+#define airo_print_dbg(name, fmt, args...) \
+       airo_print(KERN_DEBUG, name, fmt, ##args)
+
+#define airo_print_warn(name, fmt, args...) \
+       airo_print(KERN_WARNING, name, fmt, ##args)
+
+#define airo_print_err(name, fmt, args...) \
+       airo_print(KERN_ERR, name, fmt, ##args)
+
+
 /***********************************************************************
  *                              MIC ROUTINES                           *
  ***********************************************************************
@@ -1234,10 +1252,11 @@ static int takedown_proc_entry( struct net_device *dev,
 
 static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq);
 static void MoveWindow(miccntx *context, u32 micSeq);
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
-void emmh32_init(emmh32_context *context);
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
-void emmh32_final(emmh32_context *context, u8 digest[4]);
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *);
+static void emmh32_init(emmh32_context *context);
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len);
+static void emmh32_final(emmh32_context *context, u8 digest[4]);
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime);
 
 /* micinit - Initialize mic seed */
 
@@ -1301,10 +1320,10 @@ static int micsetup(struct airo_info *ai) {
        int i;
 
        if (ai->tfm == NULL)
-               ai->tfm = crypto_alloc_tfm("aes", 0);
+               ai->tfm = crypto_alloc_tfm("aes", CRYPTO_TFM_REQ_MAY_SLEEP);
 
         if (ai->tfm == NULL) {
-                printk(KERN_ERR "airo: failed to load transform for AES\n");
+                airo_print_err(ai->dev->name, "failed to load transform for AES");
                 return ERROR;
         }
 
@@ -1315,7 +1334,7 @@ static int micsetup(struct airo_info *ai) {
        return SUCCESS;
 }
 
-char micsnap[]= {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
+static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02};
 
 /*===========================================================================
  * Description: Mic a packet
@@ -1570,7 +1589,7 @@ static void MoveWindow(miccntx *context, u32 micSeq)
 static unsigned char aes_counter[16];
 
 /* expand the key to fill the MMH coefficient array */
-void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
+static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto_tfm *tfm)
 {
   /* take the keying material, expand if necessary, truncate at 16-bytes */
   /* run through AES counter mode to generate context->coeff[] */
@@ -1589,11 +1608,9 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
                aes_counter[12] = (u8)(counter >> 24);
                counter++;
                memcpy (plain, aes_counter, 16);
-               sg[0].page = virt_to_page(plain);
-               sg[0].offset = ((long) plain & ~PAGE_MASK);
-               sg[0].length = 16;
+               sg_set_buf(sg, plain, 16);
                crypto_cipher_encrypt(tfm, sg, sg, 16);
-               cipher = kmap(sg[0].page) + sg[0].offset;
+               cipher = kmap(sg->page) + sg->offset;
                for (j=0; (j<16) && (i< (sizeof(context->coeff)/sizeof(context->coeff[0]))); ) {
                        context->coeff[i++] = ntohl(*(u32 *)&cipher[j]);
                        j += 4;
@@ -1602,7 +1619,7 @@ void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, struct crypto
 }
 
 /* prepare for calculation of a new mic */
-void emmh32_init(emmh32_context *context)
+static void emmh32_init(emmh32_context *context)
 {
        /* prepare for new mic calculation */
        context->accum = 0;
@@ -1610,7 +1627,7 @@ void emmh32_init(emmh32_context *context)
 }
 
 /* add some bytes to the mic calculation */
-void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
+static void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
 {
        int     coeff_position, byte_position;
   
@@ -1652,7 +1669,7 @@ void emmh32_update(emmh32_context *context, u8 *pOctets, int len)
 static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L };
 
 /* calculate the mic */
-void emmh32_final(emmh32_context *context, u8 digest[4])
+static void emmh32_final(emmh32_context *context, u8 digest[4])
 {
        int     coeff_position, byte_position;
        u32     val;
@@ -1684,7 +1701,6 @@ void emmh32_final(emmh32_context *context, u8 digest[4])
        digest[2] = (val>>8) & 0xFF;
        digest[3] = val & 0xFF;
 }
-#endif
 
 static int readBSSListRid(struct airo_info *ai, int first,
                      BSSListRid *list) {
@@ -1739,11 +1755,11 @@ static int writeWepKeyRid(struct airo_info*ai, WepKeyRid *pwkr, int perm, int lo
        wkr.kindex = cpu_to_le16(wkr.kindex);
        wkr.klen = cpu_to_le16(wkr.klen);
        rc = PC4500_writerid(ai, RID_WEP_TEMP, &wkr, sizeof(wkr), lock);
-       if (rc!=SUCCESS) printk(KERN_ERR "airo:  WEP_TEMP set %x\n", rc);
+       if (rc!=SUCCESS) airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc);
        if (perm) {
                rc = PC4500_writerid(ai, RID_WEP_PERM, &wkr, sizeof(wkr), lock);
                if (rc!=SUCCESS) {
-                       printk(KERN_ERR "airo:  WEP_PERM set %x\n", rc);
+                       airo_print_err(ai->dev->name, "WEP_PERM set %x", rc);
                }
        }
        return rc;
@@ -1922,7 +1938,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
        struct airo_info *ai = dev->priv;
 
        if (!skb) {
-               printk(KERN_ERR "airo: %s: skb==NULL\n",__FUNCTION__);
+               airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
                return 0;
        }
        npacks = skb_queue_len (&ai->txq);
@@ -1968,8 +1984,8 @@ static int mpi_send_packet (struct net_device *dev)
        /* get a packet to send */
 
        if ((skb = skb_dequeue(&ai->txq)) == 0) {
-               printk (KERN_ERR
-                       "airo: %s: Dequeue'd zero in send_packet()\n",
+               airo_print_err(dev->name,
+                       "%s: Dequeue'd zero in send_packet()",
                        __FUNCTION__);
                return 0;
        }
@@ -2003,7 +2019,6 @@ static int mpi_send_packet (struct net_device *dev)
         * Firmware automaticly puts 802 header on so
         * we don't need to account for it in the length
         */
-#ifdef MICSUPPORT
        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
                (ntohs(((u16 *)buffer)[6]) != 0x888E)) {
                MICBuffer pMic;
@@ -2020,9 +2035,7 @@ static int mpi_send_packet (struct net_device *dev)
                memcpy (sendbuf, &pMic, sizeof(pMic));
                sendbuf += sizeof(pMic);
                memcpy (sendbuf, buffer, len - sizeof(etherHead));
-       } else
-#endif
-       {
+       } else {
                *payloadLen = cpu_to_le16(len - sizeof(etherHead));
 
                dev->trans_start = jiffies;
@@ -2040,7 +2053,7 @@ static int mpi_send_packet (struct net_device *dev)
        return 1;
 }
 
-static void get_tx_error(struct airo_info *ai, u32 fid)
+static void get_tx_error(struct airo_info *ai, s32 fid)
 {
        u16 status;
 
@@ -2124,7 +2137,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
        u32 *fids = priv->fids;
 
        if ( skb == NULL ) {
-               printk( KERN_ERR "airo:  skb == NULL!!!\n" );
+               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
                return 0;
        }
 
@@ -2195,7 +2208,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
        }
 
        if ( skb == NULL ) {
-               printk( KERN_ERR "airo:  skb == NULL!!!\n" );
+               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
                return 0;
        }
 
@@ -2232,7 +2245,7 @@ static void airo_read_stats(struct airo_info *ai) {
        u32 *vals = stats_rid.vals;
 
        clear_bit(JOB_STATS, &ai->flags);
-       if (ai->power) {
+       if (ai->power.event) {
                up(&ai->sem);
                return;
        }
@@ -2255,7 +2268,7 @@ static void airo_read_stats(struct airo_info *ai) {
        ai->stats.rx_fifo_errors = vals[0];
 }
 
-struct net_device_stats *airo_get_stats(struct net_device *dev)
+static struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
        struct airo_info *local =  dev->priv;
 
@@ -2374,20 +2387,18 @@ void stop_airo_card( struct net_device *dev, int freeres )
        /*
         * Clean out tx queue
         */
-       if (test_bit(FLAG_MPI, &ai->flags) && skb_queue_len (&ai->txq) > 0) {
+       if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) {
                struct sk_buff *skb = NULL;
                for (;(skb = skb_dequeue(&ai->txq));)
                        dev_kfree_skb(skb);
        }
 
-       if (ai->flash)
-               kfree(ai->flash);
-       if (ai->rssi)
-               kfree(ai->rssi);
-       if (ai->APList)
-               kfree(ai->APList);
-       if (ai->SSID)
-               kfree(ai->SSID);
+       airo_networks_free (ai);
+
+       kfree(ai->flash);
+       kfree(ai->rssi);
+       kfree(ai->APList);
+       kfree(ai->SSID);
        if (freeres) {
                /* PCMCIA frees this stuff, so only for PCI and ISA */
                release_region( dev->base_addr, 64 );
@@ -2402,10 +2413,7 @@ void stop_airo_card( struct net_device *dev, int freeres )
                                ai->shared, ai->shared_dma);
                }
         }
-#ifdef MICSUPPORT
-       if (ai->tfm)
-               crypto_free_tfm(ai->tfm);
-#endif
+       crypto_free_tfm(ai->tfm);
        del_airo_dev( dev );
        free_netdev( dev );
 }
@@ -2414,7 +2422,7 @@ EXPORT_SYMBOL(stop_airo_card);
 
 static int add_airo_dev( struct net_device *dev );
 
-int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
+static int wll_header_parse(struct sk_buff *skb, unsigned char *haddr)
 {
        memcpy(haddr, skb->mac.raw + 10, ETH_ALEN);
        return ETH_ALEN;
@@ -2457,7 +2465,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
        cmd.parm2 = MPI_MAX_FIDS;
        rc=issuecommand(ai, &cmd, &rsp);
        if (rc != SUCCESS) {
-               printk(KERN_ERR "airo:  Couldn't allocate RX FID\n");
+               airo_print_err(ai->dev->name, "Couldn't allocate RX FID");
                return rc;
        }
 
@@ -2485,7 +2493,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
 
        rc=issuecommand(ai, &cmd, &rsp);
        if (rc != SUCCESS) {
-               printk(KERN_ERR "airo:  Couldn't allocate TX FID\n");
+               airo_print_err(ai->dev->name, "Couldn't allocate TX FID");
                return rc;
        }
 
@@ -2499,7 +2507,7 @@ static int mpi_init_descriptors (struct airo_info *ai)
        cmd.parm2 = 1; /* Magic number... */
        rc=issuecommand(ai, &cmd, &rsp);
        if (rc != SUCCESS) {
-               printk(KERN_ERR "airo:  Couldn't allocate RID\n");
+               airo_print_err(ai->dev->name, "Couldn't allocate RID");
                return rc;
        }
 
@@ -2521,7 +2529,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        unsigned long mem_start, mem_len, aux_start, aux_len;
        int rc = -1;
        int i;
-       unsigned char *busaddroff,*vpackoff;
+       dma_addr_t busaddroff;
+       unsigned char *vpackoff;
        unsigned char __iomem *pciaddroff;
 
        mem_start = pci_resource_start(pci, 1);
@@ -2530,25 +2539,25 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        aux_len = AUXMEMSIZE;
 
        if (!request_mem_region(mem_start, mem_len, name)) {
-               printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+               airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
                       (int)mem_start, (int)mem_len, name);
                goto out;
        }
        if (!request_mem_region(aux_start, aux_len, name)) {
-               printk(KERN_ERR "airo: Couldn't get region %x[%x] for %s\n",
+               airo_print_err(ai->dev->name, "Couldn't get region %x[%x] for %s",
                       (int)aux_start, (int)aux_len, name);
                goto free_region1;
        }
 
        ai->pcimem = ioremap(mem_start, mem_len);
        if (!ai->pcimem) {
-               printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+               airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
                       (int)mem_start, (int)mem_len, name);
                goto free_region2;
        }
        ai->pciaux = ioremap(aux_start, aux_len);
        if (!ai->pciaux) {
-               printk(KERN_ERR "airo: Couldn't map region %x[%x] for %s\n",
+               airo_print_err(ai->dev->name, "Couldn't map region %x[%x] for %s",
                       (int)aux_start, (int)aux_len, name);
                goto free_memmap;
        }
@@ -2556,7 +2565,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        /* Reserve PKTSIZE for each fid and 2K for the Rids */
        ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma);
        if (!ai->shared) {
-               printk(KERN_ERR "airo: Couldn't alloc_consistent %d\n",
+               airo_print_err(ai->dev->name, "Couldn't alloc_consistent %d",
                       PCI_SHARED_LEN);
                goto free_auxmap;
        }
@@ -2564,7 +2573,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        /*
         * Setup descriptor RX, TX, CONFIG
         */
-       busaddroff = (unsigned char *)ai->shared_dma;
+       busaddroff = ai->shared_dma;
        pciaddroff = ai->pciaux + AUX_OFFSET;
        vpackoff   = ai->shared;
 
@@ -2573,7 +2582,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
                ai->rxfids[i].pending = 0;
                ai->rxfids[i].card_ram_off = pciaddroff;
                ai->rxfids[i].virtual_host_addr = vpackoff;
-               ai->rxfids[i].rx_desc.host_addr = (dma_addr_t) busaddroff;
+               ai->rxfids[i].rx_desc.host_addr = busaddroff;
                ai->rxfids[i].rx_desc.valid = 1;
                ai->rxfids[i].rx_desc.len = PKTSIZE;
                ai->rxfids[i].rx_desc.rdy = 0;
@@ -2588,7 +2597,7 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
                ai->txfids[i].card_ram_off = pciaddroff;
                ai->txfids[i].virtual_host_addr = vpackoff;
                ai->txfids[i].tx_desc.valid = 1;
-               ai->txfids[i].tx_desc.host_addr = (dma_addr_t) busaddroff;
+               ai->txfids[i].tx_desc.host_addr = busaddroff;
                memcpy(ai->txfids[i].virtual_host_addr,
                        &wifictlhdr8023, sizeof(wifictlhdr8023));
 
@@ -2601,8 +2610,8 @@ static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci,
        /* Rid descriptor setup */
        ai->config_desc.card_ram_off = pciaddroff;
        ai->config_desc.virtual_host_addr = vpackoff;
-       ai->config_desc.rid_desc.host_addr = (dma_addr_t) busaddroff;
-       ai->ridbus = (dma_addr_t)busaddroff;
+       ai->config_desc.rid_desc.host_addr = busaddroff;
+       ai->ridbus = busaddroff;
        ai->config_desc.rid_desc.rid = 0;
        ai->config_desc.rid_desc.len = RIDSIZE;
        ai->config_desc.rid_desc.valid = 1;
@@ -2641,16 +2650,14 @@ static void wifi_setup(struct net_device *dev)
        dev->get_stats = &airo_get_stats;
        dev->set_mac_address = &airo_set_mac_address;
        dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
        dev->wireless_handlers = &airo_handler_def;
-#endif /* WIRELESS_EXT */
        dev->change_mtu = &airo_change_mtu;
        dev->open = &airo_open;
        dev->stop = &airo_close;
 
        dev->type               = ARPHRD_IEEE80211;
        dev->hard_header_len    = ETH_HLEN;
-       dev->mtu                = 2312;
+       dev->mtu                = AIRO_DEF_MTU;
        dev->addr_len           = ETH_ALEN;
        dev->tx_queue_len       = 100; 
 
@@ -2669,9 +2676,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
        dev->priv = ethdev->priv;
        dev->irq = ethdev->irq;
        dev->base_addr = ethdev->base_addr;
-#ifdef WIRELESS_EXT
        dev->wireless_data = ethdev->wireless_data;
-#endif /* WIRELESS_EXT */
        memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len);
        err = register_netdev(dev);
        if (err<0) {
@@ -2681,7 +2686,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
        return dev;
 }
 
-int reset_card( struct net_device *dev , int lock) {
+static int reset_card( struct net_device *dev , int lock) {
        struct airo_info *ai = dev->priv;
 
        if (lock && down_interruptible(&ai->sem))
@@ -2696,9 +2701,45 @@ int reset_card( struct net_device *dev , int lock) {
        return 0;
 }
 
-struct net_device *_init_airo_card( unsigned short irq, int port,
-                                   int is_pcmcia, struct pci_dev *pci,
-                                   struct device *dmdev )
+#define MAX_NETWORK_COUNT      64
+static int airo_networks_allocate(struct airo_info *ai)
+{
+       if (ai->networks)
+               return 0;
+
+       ai->networks =
+           kzalloc(MAX_NETWORK_COUNT * sizeof(BSSListElement),
+                   GFP_KERNEL);
+       if (!ai->networks) {
+               airo_print_warn(ai->dev->name, "Out of memory allocating beacons");
+               return -ENOMEM;
+       }
+
+       return 0;
+}
+
+static void airo_networks_free(struct airo_info *ai)
+{
+       if (!ai->networks)
+               return;
+       kfree(ai->networks);
+       ai->networks = NULL;
+}
+
+static void airo_networks_initialize(struct airo_info *ai)
+{
+       int i;
+
+       INIT_LIST_HEAD(&ai->network_free_list);
+       INIT_LIST_HEAD(&ai->network_list);
+       for (i = 0; i < MAX_NETWORK_COUNT; i++)
+               list_add_tail(&ai->networks[i].list,
+                             &ai->network_free_list);
+}
+
+static struct net_device *_init_airo_card( unsigned short irq, int port,
+                                          int is_pcmcia, struct pci_dev *pci,
+                                          struct device *dmdev )
 {
        struct net_device *dev;
        struct airo_info *ai;
@@ -2707,22 +2748,22 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
        /* Create the network device object. */
         dev = alloc_etherdev(sizeof(*ai));
         if (!dev) {
-               printk(KERN_ERR "airo:  Couldn't alloc_etherdev\n");
+               airo_print_err("", "Couldn't alloc_etherdev");
                return NULL;
         }
        if (dev_alloc_name(dev, dev->name) < 0) {
-               printk(KERN_ERR "airo:  Couldn't get name!\n");
+               airo_print_err("", "Couldn't get name!");
                goto err_out_free;
        }
 
        ai = dev->priv;
        ai->wifidev = NULL;
        ai->flags = 0;
+       ai->dev = dev;
        if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) {
-               printk(KERN_DEBUG "airo: Found an MPI350 card\n");
+               airo_print_dbg(dev->name, "Found an MPI350 card");
                set_bit(FLAG_MPI, &ai->flags);
        }
-        ai->dev = dev;
        spin_lock_init(&ai->aux_lock);
        sema_init(&ai->sem, 1);
        ai->config.len = 0;
@@ -2732,13 +2773,15 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
        ai->thr_pid = kernel_thread(airo_thread, dev, CLONE_FS | CLONE_FILES);
        if (ai->thr_pid < 0)
                goto err_out_free;
-#ifdef MICSUPPORT
        ai->tfm = NULL;
-#endif
        rc = add_airo_dev( dev );
        if (rc)
                goto err_out_thr;
 
+       if (airo_networks_allocate (ai))
+               goto err_out_unlink;
+       airo_networks_initialize (ai);
+
        /* The Airo-specific entries in the device structure. */
        if (test_bit(FLAG_MPI,&ai->flags)) {
                skb_queue_head_init (&ai->txq);
@@ -2749,11 +2792,9 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
        dev->set_multicast_list = &airo_set_multicast_list;
        dev->set_mac_address = &airo_set_mac_address;
        dev->do_ioctl = &airo_ioctl;
-#ifdef WIRELESS_EXT
        dev->wireless_handlers = &airo_handler_def;
        ai->wireless_data.spy_data = &ai->spy_data;
        dev->wireless_data = &ai->wireless_data;
-#endif /* WIRELESS_EXT */
        dev->change_mtu = &airo_change_mtu;
        dev->open = &airo_open;
        dev->stop = &airo_close;
@@ -2762,33 +2803,33 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
 
        SET_NETDEV_DEV(dev, dmdev);
 
-
-       if (test_bit(FLAG_MPI,&ai->flags))
-               reset_card (dev, 1);
+       reset_card (dev, 1);
+       msleep(400);
 
        rc = request_irq( dev->irq, airo_interrupt, SA_SHIRQ, dev->name, dev );
        if (rc) {
-               printk(KERN_ERR "airo: register interrupt %d failed, rc %d\n", irq, rc );
+               airo_print_err(dev->name, "register interrupt %d failed, rc %d",
+                               irq, rc);
                goto err_out_unlink;
        }
        if (!is_pcmcia) {
                if (!request_region( dev->base_addr, 64, dev->name )) {
                        rc = -EBUSY;
-                       printk(KERN_ERR "airo: Couldn't request region\n");
+                       airo_print_err(dev->name, "Couldn't request region");
                        goto err_out_irq;
                }
        }
 
        if (test_bit(FLAG_MPI,&ai->flags)) {
                if (mpi_map_card(ai, pci, dev->name)) {
-                       printk(KERN_ERR "airo: Could not map memory\n");
+                       airo_print_err(dev->name, "Could not map memory");
                        goto err_out_res;
                }
        }
 
        if (probe) {
                if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
-                       printk( KERN_ERR "airo: MAC could not be enabled\n" );
+                       airo_print_err(dev->name, "MAC could not be enabled" );
                        rc = -EIO;
                        goto err_out_map;
                }
@@ -2799,21 +2840,20 @@ struct net_device *_init_airo_card( unsigned short irq, int port,
 
        rc = register_netdev(dev);
        if (rc) {
-               printk(KERN_ERR "airo: Couldn't register_netdev\n");
+               airo_print_err(dev->name, "Couldn't register_netdev");
                goto err_out_map;
        }
        ai->wifidev = init_wifidev(ai, dev);
 
        set_bit(FLAG_REGISTERED,&ai->flags);
-       printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n",
-               dev->name,
+       airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
                dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
                dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5] );
 
        /* Allocate the transmit buffers */
        if (probe && !test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
-                       ai->fids[i] = transmit_allocate(ai,2312,i>=MAX_FIDS/2);
+                       ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
        setup_proc_entry( dev, dev->priv ); /* XXX check for failure */
        netif_start_queue(dev);
@@ -2870,16 +2910,16 @@ int reset_airo_card( struct net_device *dev )
                return -1;
 
        if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) {
-               printk( KERN_ERR "airo: MAC could not be enabled\n" );
+               airo_print_err(dev->name, "MAC could not be enabled");
                return -1;
        }
-       printk( KERN_INFO "airo: MAC enabled %s %x:%x:%x:%x:%x:%x\n", dev->name,
+       airo_print_info(dev->name, "MAC enabled %x:%x:%x:%x:%x:%x",
                        dev->dev_addr[0], dev->dev_addr[1], dev->dev_addr[2],
                        dev->dev_addr[3], dev->dev_addr[4], dev->dev_addr[5]);
        /* Allocate the transmit buffers if needed */
        if (!test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
-                       ai->fids[i] = transmit_allocate (ai,2312,i>=MAX_FIDS/2);
+                       ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
        enable_interrupts( ai );
        netif_wake_queue(dev);
@@ -2905,6 +2945,65 @@ static void airo_send_event(struct net_device *dev) {
        wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
 }
 
+static void airo_process_scan_results (struct airo_info *ai) {
+       union iwreq_data        wrqu;
+       BSSListRid BSSList;
+       int rc;
+       BSSListElement * loop_net;
+       BSSListElement * tmp_net;
+
+       /* Blow away current list of scan results */
+       list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) {
+               list_move_tail (&loop_net->list, &ai->network_free_list);
+               /* Don't blow away ->list, just BSS data */
+               memset (loop_net, 0, sizeof (loop_net->bss));
+       }
+
+       /* Try to read the first entry of the scan result */
+       rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 0);
+       if((rc) || (BSSList.index == 0xffff)) {
+               /* No scan results */
+               goto out;
+       }
+
+       /* Read and parse all entries */
+       tmp_net = NULL;
+       while((!rc) && (BSSList.index != 0xffff)) {
+               /* Grab a network off the free list */
+               if (!list_empty(&ai->network_free_list)) {
+                       tmp_net = list_entry(ai->network_free_list.next,
+                                           BSSListElement, list);
+                       list_del(ai->network_free_list.next);
+               }
+
+               if (tmp_net != NULL) {
+                       memcpy(tmp_net, &BSSList, sizeof(tmp_net->bss));
+                       list_add_tail(&tmp_net->list, &ai->network_list);
+                       tmp_net = NULL;
+               }
+
+               /* Read next entry */
+               rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
+                                   &BSSList, sizeof(BSSList), 0);
+       }
+
+out:
+       ai->scan_timeout = 0;
+       clear_bit(JOB_SCAN_RESULTS, &ai->flags);
+       up(&ai->sem);
+
+       /* Send an empty event to user space.
+        * We don't send the received data on
+        * the event because it would require
+        * us to do complex transcoding, and
+        * we want to minimise the work done in
+        * the irq handler. Use a request to
+        * extract the data - Jean II */
+       wrqu.data.length = 0;
+       wrqu.data.flags = 0;
+       wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL);
+}
+
 static int airo_thread(void *data) {
        struct net_device *dev = data;
        struct airo_info *ai = dev->priv;
@@ -2918,7 +3017,7 @@ static int airo_thread(void *data) {
                        flush_signals(current);
 
                /* make swsusp happy with our thread */
-               try_to_freeze(PF_FREEZE);
+               try_to_freeze();
 
                if (test_bit(JOB_DIE, &ai->flags))
                        break;
@@ -2934,13 +3033,26 @@ static int airo_thread(void *data) {
                                set_current_state(TASK_INTERRUPTIBLE);
                                if (ai->flags & JOB_MASK)
                                        break;
-                               if (ai->expires) {
-                                       if (time_after_eq(jiffies,ai->expires)){
+                               if (ai->expires || ai->scan_timeout) {
+                                       if (ai->scan_timeout &&
+                                                       time_after_eq(jiffies,ai->scan_timeout)){
+                                               set_bit(JOB_SCAN_RESULTS,&ai->flags);
+                                               break;
+                                       } else if (ai->expires &&
+                                                       time_after_eq(jiffies,ai->expires)){
                                                set_bit(JOB_AUTOWEP,&ai->flags);
                                                break;
                                        }
                                        if (!signal_pending(current)) {
-                                               schedule_timeout(ai->expires - jiffies);
+                                               unsigned long wake_at;
+                                               if (!ai->expires || !ai->scan_timeout) {
+                                                       wake_at = max(ai->expires,
+                                                               ai->scan_timeout);
+                                               } else {
+                                                       wake_at = min(ai->expires,
+                                                               ai->scan_timeout);
+                                               }
+                                               schedule_timeout(wake_at - jiffies);
                                                continue;
                                        }
                                } else if (!signal_pending(current)) {
@@ -2962,7 +3074,7 @@ static int airo_thread(void *data) {
                        break;
                }
 
-               if (ai->power || test_bit(FLAG_FLASHING, &ai->flags)) {
+               if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) {
                        up(&ai->sem);
                        continue;
                }
@@ -2977,14 +3089,16 @@ static int airo_thread(void *data) {
                        airo_read_wireless_stats(ai);
                else if (test_bit(JOB_PROMISC, &ai->flags))
                        airo_set_promisc(ai);
-#ifdef MICSUPPORT
                else if (test_bit(JOB_MIC, &ai->flags))
                        micinit(ai);
-#endif
                else if (test_bit(JOB_EVENT, &ai->flags))
                        airo_send_event(dev);
                else if (test_bit(JOB_AUTOWEP, &ai->flags))
                        timer_func(dev);
+               else if (test_bit(JOB_SCAN_RESULTS, &ai->flags))
+                       airo_process_scan_results(ai);
+               else  /* Shouldn't get here, but we make sure to unlock */
+                       up(&ai->sem);
        }
        complete_and_exit (&ai->thr_exited, 0);
 }
@@ -3018,15 +3132,14 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
 
                if ( status & EV_MIC ) {
                        OUT4500( apriv, EVACK, EV_MIC );
-#ifdef MICSUPPORT
                        if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
                                set_bit(JOB_MIC, &apriv->flags);
                                wake_up_interruptible(&apriv->thr_wait);
                        }
-#endif
                }
                if ( status & EV_LINK ) {
                        union iwreq_data        wrqu;
+                       int scan_forceloss = 0;
                        /* The link status has changed, if you want to put a
                           monitor hook in, do it here.  (Remember that
                           interrupts are still disabled!)
@@ -3045,7 +3158,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                          code) */
 #define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
                           code) */
-#define ASSOCIATED 0x0400 /* Assocatied */
+#define ASSOCIATED 0x0400 /* Associated */
+#define REASSOCIATED 0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
 #define RC_RESERVED 0 /* Reserved return code */
 #define RC_NOREASON 1 /* Unspecified reason */
 #define RC_AUTHINV 2 /* Previous authentication invalid */
@@ -3062,48 +3176,30 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                          leaving BSS */
 #define RC_NOAUTH 9 /* Station requesting (Re)Association is not
                       Authenticated with the responding station */
-                       if (newStatus != ASSOCIATED) {
-                               if (auto_wep && !apriv->expires) {
-                                       apriv->expires = RUN_AT(3*HZ);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               }
-                       } else {
-                               struct task_struct *task = apriv->task;
+                       if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
+                               scan_forceloss = 1;
+                       if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
                                if (auto_wep)
                                        apriv->expires = 0;
-                               if (task)
-                                       wake_up_process (task);
+                               if (apriv->task)
+                                       wake_up_process (apriv->task);
                                set_bit(FLAG_UPDATE_UNI, &apriv->flags);
                                set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-                       }
-                       /* Question : is ASSOCIATED the only status
-                        * that is valid ? We want to catch handover
-                        * and reassociations as valid status
-                        * Jean II */
-                       if(newStatus == ASSOCIATED) {
-                               if (apriv->scan_timestamp) {
-                                       /* Send an empty event to user space.
-                                        * We don't send the received data on
-                                        * the event because it would require
-                                        * us to do complex transcoding, and
-                                        * we want to minimise the work done in
-                                        * the irq handler. Use a request to
-                                        * extract the data - Jean II */
-                                       wrqu.data.length = 0;
-                                       wrqu.data.flags = 0;
-                                       wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
-                                       apriv->scan_timestamp = 0;
-                               }
+
                                if (down_trylock(&apriv->sem) != 0) {
                                        set_bit(JOB_EVENT, &apriv->flags);
                                        wake_up_interruptible(&apriv->thr_wait);
                                } else
                                        airo_send_event(dev);
-                       } else {
-                               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
-                               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+                       } else if (!scan_forceloss) {
+                               if (auto_wep && !apriv->expires) {
+                                       apriv->expires = RUN_AT(3*HZ);
+                                       wake_up_interruptible(&apriv->thr_wait);
+                               }
 
                                /* Send event to user space */
+                               memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+                               wrqu.ap_addr.sa_family = ARPHRD_ETHER;
                                wireless_send_event(dev, SIOCGIWAP, &wrqu,NULL);
                        }
                }
@@ -3151,8 +3247,8 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                        }
                        len = le16_to_cpu(hdr.len);
 
-                       if (len > 2312) {
-                               printk( KERN_ERR "airo: Bad size %d\n", len );
+                       if (len > AIRO_DEF_MTU) {
+                               airo_print_err(apriv->dev->name, "Bad size %d", len);
                                goto badrx;
                        }
                        if (len == 0)
@@ -3195,18 +3291,17 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                                bap_read (apriv, &gap, sizeof(gap), BAP0);
                                gap = le16_to_cpu(gap);
                                if (gap) {
-                                       if (gap <= 8)
+                                       if (gap <= 8) {
                                                bap_read (apriv, tmpbuf, gap, BAP0);
-                                       else
-                                               printk(KERN_ERR "airo: gaplen too big. Problems will follow...\n");
+                                       } else {
+                                               airo_print_err(apriv->dev->name, "gaplen too "
+                                                       "big. Problems will follow...");
+                                       }
                                }
                                bap_read (apriv, buffer + hdrlen/2, len, BAP0);
                        } else {
-#ifdef MICSUPPORT
                                MICBuffer micbuf;
-#endif
                                bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-#ifdef MICSUPPORT
                                if (apriv->micstats.enabled) {
                                        bap_read (apriv,(u16*)&micbuf,sizeof(micbuf),BAP0);
                                        if (ntohs(micbuf.typelen) > 0x05DC)
@@ -3219,15 +3314,10 @@ static irqreturn_t airo_interrupt ( int irq, void* dev_id, struct pt_regs *regs)
                                                skb_trim (skb, len + hdrlen);
                                        }
                                }
-#endif
                                bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-#ifdef MICSUPPORT
                                if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
 badmic:
                                        dev_kfree_skb_irq (skb);
-#else
-                               if (0) {
-#endif
 badrx:
                                        OUT4500( apriv, EVACK, EV_RX);
                                        goto exitrx;
@@ -3252,7 +3342,7 @@ badrx:
                                wstats.noise = apriv->wstats.qual.noise;
                                wstats.updated = IW_QUAL_LEVEL_UPDATED
                                        | IW_QUAL_QUAL_UPDATED
-                                       | IW_QUAL_NOISE_UPDATED;
+                                       | IW_QUAL_DBM;
                                /* Update spy records */
                                wireless_spy_update(dev, sa, &wstats);
                        }
@@ -3287,7 +3377,7 @@ exitrx:
                                if (status & EV_TXEXC)
                                        get_tx_error(apriv, -1);
                                spin_lock_irqsave(&apriv->aux_lock, flags);
-                               if (skb_queue_len (&apriv->txq)) {
+                               if (!skb_queue_empty(&apriv->txq)) {
                                        spin_unlock_irqrestore(&apriv->aux_lock,flags);
                                        mpi_send_packet (dev);
                                } else {
@@ -3323,12 +3413,13 @@ exitrx:
                                }
                        } else {
                                OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
-                               printk( KERN_ERR "airo: Unallocated FID was used to xmit\n" );
+                               airo_print_err(apriv->dev->name, "Unallocated FID was "
+                                       "used to xmit" );
                        }
                }
 exittx:
                if ( status & ~STATUS_INTS & ~IGNORE_INTS )
-                       printk( KERN_WARNING "airo: Got weird status %x\n",
+                       airo_print_warn(apriv->dev->name, "Got weird status %x",
                                status & ~STATUS_INTS & ~IGNORE_INTS );
        }
 
@@ -3401,8 +3492,8 @@ static int enable_MAC( struct airo_info *ai, Resp *rsp, int lock ) {
            up(&ai->sem);
 
        if (rc)
-               printk(KERN_ERR "%s: Cannot enable MAC, err=%d\n",
-                       __FUNCTION__,rc);
+               airo_print_err(ai->dev->name, "%s: Cannot enable MAC, err=%d",
+                       __FUNCTION__, rc);
        return rc;
 }
 
@@ -3438,10 +3529,8 @@ static void mpi_receive_802_3(struct airo_info *ai)
        int len = 0;
        struct sk_buff *skb;
        char *buffer;
-#ifdef MICSUPPORT
        int off = 0;
        MICBuffer micbuf;
-#endif
 
        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
        /* Make sure we got something */
@@ -3456,7 +3545,6 @@ static void mpi_receive_802_3(struct airo_info *ai)
                        goto badrx;
                }
                buffer = skb_put(skb,len);
-#ifdef MICSUPPORT
                memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2);
                if (ai->micstats.enabled) {
                        memcpy(&micbuf,
@@ -3478,9 +3566,6 @@ badmic:
                        dev_kfree_skb_irq (skb);
                        goto badrx;
                }
-#else
-               memcpy(buffer, ai->rxfids[0].virtual_host_addr, len);
-#endif
 #ifdef WIRELESS_SPY
                if (ai->spy_data.spy_number > 0) {
                        char *sa;
@@ -3537,8 +3622,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
        if (ai->wifidev == NULL)
                hdr.len = 0;
        len = le16_to_cpu(hdr.len);
-       if (len > 2312) {
-               printk( KERN_ERR "airo: Bad size %d\n", len );
+       if (len > AIRO_DEF_MTU) {
+               airo_print_err(ai->dev->name, "Bad size %d", len);
                goto badrx;
        }
        if (len == 0)
@@ -3579,8 +3664,8 @@ void mpi_receive_802_11 (struct airo_info *ai)
                if (gap <= 8)
                        ptr += gap;
                else
-                       printk(KERN_ERR
-                           "airo: gaplen too big. Problems will follow...\n");
+                       airo_print_err(ai->dev->name,
+                           "gaplen too big. Problems will follow...");
        }
        memcpy ((char *)buffer + hdrlen, ptr, len);
        ptr += len;
@@ -3598,7 +3683,7 @@ void mpi_receive_802_11 (struct airo_info *ai)
                wstats.noise = ai->wstats.qual.noise;
                wstats.updated = IW_QUAL_QUAL_UPDATED
                        | IW_QUAL_LEVEL_UPDATED
-                       | IW_QUAL_NOISE_UPDATED;
+                       | IW_QUAL_DBM;
                /* Update spy records */
                wireless_spy_update(ai->dev, sa, &wstats);
        }
@@ -3631,10 +3716,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
        int rc;
 
        memset( &mySsid, 0, sizeof( mySsid ) );
-       if (ai->flash) {
-               kfree (ai->flash);
-               ai->flash = NULL;
-       }
+       kfree (ai->flash);
+       ai->flash = NULL;
 
        /* The NOP is the first step in getting the card going */
        cmd.cmd = NOP;
@@ -3654,15 +3737,15 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                if (issuecommand(ai, &cmd, &rsp) != SUCCESS) {
                        if (lock)
                                up(&ai->sem);
-                       printk(KERN_ERR "airo: Error checking for AUX port\n");
+                       airo_print_err(ai->dev->name, "Error checking for AUX port");
                        return ERROR;
                }
                if (!aux_bap || rsp.status & 0xff00) {
                        ai->bap_read = fast_bap_read;
-                       printk(KERN_DEBUG "airo: Doing fast bap_reads\n");
+                       airo_print_dbg(ai->dev->name, "Doing fast bap_reads");
                } else {
                        ai->bap_read = aux_bap_read;
-                       printk(KERN_DEBUG "airo: Doing AUX bap_reads\n");
+                       airo_print_dbg(ai->dev->name, "Doing AUX bap_reads");
                }
        }
        if (lock)
@@ -3671,14 +3754,10 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                tdsRssiRid rssi_rid;
                CapabilityRid cap_rid;
 
-               if (ai->APList) {
-                       kfree(ai->APList);
-                       ai->APList = NULL;
-               }
-               if (ai->SSID) {
-                       kfree(ai->SSID);
-                       ai->SSID = NULL;
-               }
+               kfree(ai->APList);
+               ai->APList = NULL;
+               kfree(ai->SSID);
+               ai->SSID = NULL;
                // general configuration (read/modify/write)
                status = readConfigRid(ai, lock);
                if ( status != SUCCESS ) return ERROR;
@@ -3692,26 +3771,23 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                                memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */
                }
                else {
-                       if (ai->rssi) {
-                               kfree(ai->rssi);
-                               ai->rssi = NULL;
-                       }
+                       kfree(ai->rssi);
+                       ai->rssi = NULL;
                        if (cap_rid.softCap & 8)
                                ai->config.rmode |= RXMODE_NORMALIZED_RSSI;
                        else
-                               printk(KERN_WARNING "airo: unknown received signal level scale\n");
+                               airo_print_warn(ai->dev->name, "unknown received signal "
+                                               "level scale");
                }
                ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS;
                ai->config.authType = AUTH_OPEN;
                ai->config.modulation = MOD_CCK;
 
-#ifdef MICSUPPORT
                if ((cap_rid.len>=sizeof(cap_rid)) && (cap_rid.extSoftCap&1) &&
                    (micsetup(ai) == SUCCESS)) {
                        ai->config.opmode |= MODE_MIC;
                        set_bit(FLAG_MIC_CAPABLE, &ai->flags);
                }
-#endif
 
                /* Save off the MAC */
                for( i = 0; i < ETH_ALEN; i++ ) {
@@ -3764,7 +3840,8 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
 
        status = enable_MAC(ai, &rsp, lock);
        if ( status != SUCCESS || (rsp.status & 0xFF00) != 0) {
-               printk( KERN_ERR "airo: Bad MAC enable reason = %x, rid = %x, offset = %d\n", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
+               airo_print_err(ai->dev->name, "Bad MAC enable reason = %x, rid = %x,"
+                       " offset = %d", rsp.rsp0, rsp.rsp1, rsp.rsp2 );
                return ERROR;
        }
 
@@ -3807,8 +3884,8 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
        }
 
        if ( max_tries == -1 ) {
-               printk( KERN_ERR
-                       "airo: Max tries exceeded when issueing command\n" );
+               airo_print_err(ai->dev->name,
+                       "Max tries exceeded when issueing command");
                if (IN4500(ai, COMMAND) & COMMAND_BUSY)
                        OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
                return ERROR;
@@ -3820,11 +3897,11 @@ static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) {
        pRsp->rsp1 = IN4500(ai, RESP1);
        pRsp->rsp2 = IN4500(ai, RESP2);
        if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) {
-               printk (KERN_ERR "airo: cmd= %x\n", pCmd->cmd);
-               printk (KERN_ERR "airo: status= %x\n", pRsp->status);
-               printk (KERN_ERR "airo: Rsp0= %x\n", pRsp->rsp0);
-               printk (KERN_ERR "airo: Rsp1= %x\n", pRsp->rsp1);
-               printk (KERN_ERR "airo: Rsp2= %x\n", pRsp->rsp2);
+               airo_print_err(ai->dev->name, "cmd= %x\n", pCmd->cmd);
+               airo_print_err(ai->dev->name, "status= %x\n", pRsp->status);
+               airo_print_err(ai->dev->name, "Rsp0= %x\n", pRsp->rsp0);
+               airo_print_err(ai->dev->name, "Rsp1= %x\n", pRsp->rsp1);
+               airo_print_err(ai->dev->name, "Rsp2= %x\n", pRsp->rsp2);
        }
 
        // clear stuck command busy if necessary
@@ -3857,15 +3934,15 @@ static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap )
                        }
                } else if ( status & BAP_ERR ) {
                        /* invalid rid or offset */
-                       printk( KERN_ERR "airo: BAP error %x %d\n",
+                       airo_print_err(ai->dev->name, "BAP error %x %d",
                                status, whichbap );
                        return ERROR;
                } else if (status & BAP_DONE) { // success
                        return SUCCESS;
                }
                if ( !(max_tries--) ) {
-                       printk( KERN_ERR
-                               "airo: BAP setup error too many retries\n" );
+                       airo_print_err(ai->dev->name,
+                               "airo: BAP setup error too many retries\n");
                        return ERROR;
                }
                // -- PC4500 missed it, try again
@@ -4020,8 +4097,8 @@ static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, in
                len = min(len, (int)le16_to_cpu(*(u16*)pBuf)) - 2;
 
                if ( len <= 2 ) {
-                       printk( KERN_ERR
-                       "airo: Rid %x has a length of %d which is too short\n",
+                       airo_print_err(ai->dev->name,
+                               "Rid %x has a length of %d which is too short",
                                (int)rid, (int)len );
                        rc = ERROR;
                        goto done;
@@ -4053,9 +4130,9 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                Cmd cmd;
                Resp rsp;
 
-               if (test_bit(FLAG_ENABLED, &ai->flags))
-                       printk(KERN_ERR
-                               "%s: MAC should be disabled (rid=%04x)\n",
+               if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid))
+                       airo_print_err(ai->dev->name,
+                               "%s: MAC should be disabled (rid=%04x)",
                                __FUNCTION__, rid);
                memset(&cmd, 0, sizeof(cmd));
                memset(&rsp, 0, sizeof(rsp));
@@ -4071,7 +4148,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                        &ai->config_desc.rid_desc, sizeof(Rid));
 
                if (len < 4 || len > 2047) {
-                       printk(KERN_ERR "%s: len=%d\n",__FUNCTION__,len);
+                       airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
                        rc = -1;
                } else {
                        memcpy((char *)ai->config_desc.virtual_host_addr,
@@ -4079,10 +4156,10 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
 
                        rc = issuecommand(ai, &cmd, &rsp);
                        if ((rc & 0xff00) != 0) {
-                               printk(KERN_ERR "%s: Write rid Error %d\n",
-                                       __FUNCTION__,rc);
-                               printk(KERN_ERR "%s: Cmd=%04x\n",
-                                               __FUNCTION__,cmd.cmd);
+                               airo_print_err(ai->dev->name, "%s: Write rid Error %d",
+                                               __FUNCTION__, rc);
+                               airo_print_err(ai->dev->name, "%s: Cmd=%04x",
+                                               __FUNCTION__, cmd.cmd);
                        }
 
                        if ((rsp.status & 0x7f00))
@@ -4181,20 +4258,17 @@ static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket)
        len >>= 16;
 
        if (len <= ETH_ALEN * 2) {
-               printk( KERN_WARNING "Short packet %d\n", len );
+               airo_print_warn(ai->dev->name, "Short packet %d", len);
                return ERROR;
        }
        len -= ETH_ALEN * 2;
 
-#ifdef MICSUPPORT
        if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && 
            (ntohs(((u16 *)pPacket)[6]) != 0x888E)) {
                if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS)
                        return ERROR;
                miclen = sizeof(pMic);
        }
-#endif
-
        // packet is destination[6], source[6], payload[len-12]
        // write the payload length and dst/src/payload
        if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR;
@@ -4248,7 +4322,7 @@ static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket)
        }
 
        if (len < hdrlen) {
-               printk( KERN_WARNING "Short packet %d\n", len );
+               airo_print_warn(ai->dev->name, "Short packet %d", len);
                return ERROR;
        }
 
@@ -4551,9 +4625,8 @@ static int proc_status_open( struct inode *inode, struct file *file ) {
        StatusRid status_rid;
        int i;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
@@ -4631,9 +4704,8 @@ static int proc_stats_rid_open( struct inode *inode,
        int i, j;
        u32 *vals = stats.vals;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
@@ -4647,15 +4719,14 @@ static int proc_stats_rid_open( struct inode *inode,
                    i*4<stats.len; i++){
                if (!statsLabels[i]) continue;
                if (j+strlen(statsLabels[i])+16>4096) {
-                       printk(KERN_WARNING
-                              "airo: Potentially disasterous buffer overflow averted!\n");
+                       airo_print_warn(apriv->dev->name,
+                              "Potentially disasterous buffer overflow averted!");
                        break;
                }
                j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], vals[i]);
        }
        if (i*4>=stats.len){
-               printk(KERN_WARNING
-                      "airo: Got a short rid\n");
+               airo_print_warn(apriv->dev->name, "Got a short rid");
        }
        data->readlen = j;
        return 0;
@@ -4817,7 +4888,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
 
                        line += 14;
                        v = get_dec_u16(line, &i, 4);
-                       v = (v<0) ? 0 : ((v>2312) ? 2312 : v);
+                       v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
                        ai->config.rtsThres = (u16)v;
                        set_bit (FLAG_COMMIT, &ai->flags);
                } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) {
@@ -4851,7 +4922,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
 
                        line += 15;
                        v = get_dec_u16(line, &i, 4);
-                       v = (v<256) ? 256 : ((v>2312) ? 2312 : v);
+                       v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v);
                        v = v & 0xfffe; /* Make sure its even */
                        ai->config.fragThresh = (u16)v;
                        set_bit (FLAG_COMMIT, &ai->flags);
@@ -4861,8 +4932,7 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
                        case 'd':  ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break;
                        case 'c':  ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break;
                        case 'm':  ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break;
-                       default:
-                               printk( KERN_WARNING "airo: Unknown modulation\n" );
+                       default: airo_print_warn(ai->dev->name, "Unknown modulation");
                        }
                } else if (!strncmp(line, "Preamble: ", 10)) {
                        line += 10;
@@ -4870,10 +4940,10 @@ static void proc_config_on_close( struct inode *inode, struct file *file ) {
                        case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break;
                        case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break;
                        case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break;
-                       default: printk(KERN_WARNING "airo: Unknown preamble\n");
+                       default: airo_print_warn(ai->dev->name, "Unknown preamble");
                        }
                } else {
-                       printk( KERN_WARNING "Couldn't figure out %s\n", line );
+                       airo_print_warn(ai->dev->name, "Couldn't figure out %s", line);
                }
                while( line[0] && line[0] != '\n' ) line++;
                if ( line[0] ) line++;
@@ -4897,20 +4967,18 @@ static int proc_config_open( struct inode *inode, struct file *file ) {
        struct airo_info *ai = dev->priv;
        int i;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
        }
-       if ((data->wbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) {
+       if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) {
                kfree (data->rbuffer);
                kfree (file->private_data);
                return -ENOMEM;
        }
-       memset( data->wbuffer, 0, 2048 );
        data->maxwritelen = 2048;
        data->on_close = proc_config_on_close;
 
@@ -5013,7 +5081,7 @@ static void proc_SSID_on_close( struct inode *inode, struct file *file ) {
        enable_MAC(ai, &rsp, 1);
 }
 
-inline static u8 hexVal(char c) {
+static inline u8 hexVal(char c) {
        if (c>='0' && c<='9') return c -= '0';
        if (c>='a' && c<='f') return c -= 'a'-10;
        if (c>='A' && c<='F') return c -= 'A'-10;
@@ -5101,7 +5169,6 @@ static int set_wep_key(struct airo_info *ai, u16 index,
                wkr.len = sizeof(wkr);
                wkr.kindex = 0xffff;
                wkr.mac[0] = (char)index;
-               if (perm) printk(KERN_INFO "Setting transmit key to %d\n", index);
                if (perm) ai->defindex = (char)index;
        } else {
 // We are actually setting the key
@@ -5110,12 +5177,11 @@ static int set_wep_key(struct airo_info *ai, u16 index,
                wkr.klen = keylen;
                memcpy( wkr.key, key, keylen );
                memcpy( wkr.mac, macaddr, ETH_ALEN );
-               printk(KERN_INFO "Setting key %d\n", index);
        }
 
-       disable_MAC(ai, lock);
+       if (perm) disable_MAC(ai, lock);
        writeWepKeyRid(ai, &wkr, perm, lock);
-       enable_MAC(ai, &rsp, lock);
+       if (perm) enable_MAC(ai, &rsp, lock);
        return 0;
 }
 
@@ -5143,7 +5209,7 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
                }
                j = 2;
        } else {
-               printk(KERN_ERR "airo:  WepKey passed invalid key index\n");
+               airo_print_err(ai->dev->name, "WepKey passed invalid key index");
                return;
        }
 
@@ -5171,24 +5237,21 @@ static int proc_wepkey_open( struct inode *inode, struct file *file ) {
        int j=0;
        int rc;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        memset(&wkr, 0, sizeof(wkr));
        data = (struct proc_data *)file->private_data;
-       if ((data->rbuffer = kmalloc( 180, GFP_KERNEL )) == NULL) {
+       if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
                return -ENOMEM;
        }
-       memset(data->rbuffer, 0, 180);
        data->writelen = 0;
        data->maxwritelen = 80;
-       if ((data->wbuffer = kmalloc( 80, GFP_KERNEL )) == NULL) {
+       if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) {
                kfree (data->rbuffer);
                kfree (file->private_data);
                return -ENOMEM;
        }
-       memset( data->wbuffer, 0, 80 );
        data->on_close = proc_wepkey_on_close;
 
        ptr = data->rbuffer;
@@ -5219,9 +5282,8 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) {
        char *ptr;
        SsidRid SSID_rid;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
@@ -5229,12 +5291,11 @@ static int proc_SSID_open( struct inode *inode, struct file *file ) {
        }
        data->writelen = 0;
        data->maxwritelen = 33*3;
-       if ((data->wbuffer = kmalloc( 33*3, GFP_KERNEL )) == NULL) {
+       if ((data->wbuffer = kzalloc( 33*3, GFP_KERNEL )) == NULL) {
                kfree (data->rbuffer);
                kfree (file->private_data);
                return -ENOMEM;
        }
-       memset( data->wbuffer, 0, 33*3 );
        data->on_close = proc_SSID_on_close;
 
        readSsidRid(ai, &SSID_rid);
@@ -5263,9 +5324,8 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
        char *ptr;
        APListRid APList_rid;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
@@ -5273,12 +5333,11 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
        }
        data->writelen = 0;
        data->maxwritelen = 4*6*3;
-       if ((data->wbuffer = kmalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
+       if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) {
                kfree (data->rbuffer);
                kfree (file->private_data);
                return -ENOMEM;
        }
-       memset( data->wbuffer, 0, data->maxwritelen );
        data->on_close = proc_APList_on_close;
 
        readAPListRid(ai, &APList_rid);
@@ -5313,9 +5372,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
        /* If doLoseSync is not 1, we won't do a Lose Sync */
        int doLoseSync = -1;
 
-       if ((file->private_data = kmalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
+       if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
-       memset(file->private_data, 0, sizeof(struct proc_data));
        data = (struct proc_data *)file->private_data;
        if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) {
                kfree (file->private_data);
@@ -5374,11 +5432,13 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
 
 static int proc_close( struct inode *inode, struct file *file )
 {
-       struct proc_data *data = (struct proc_data *)file->private_data;
-       if ( data->on_close != NULL ) data->on_close( inode, file );
-       if ( data->rbuffer ) kfree( data->rbuffer );
-       if ( data->wbuffer ) kfree( data->wbuffer );
-       kfree( data );
+       struct proc_data *data = file->private_data;
+
+       if (data->on_close != NULL)
+               data->on_close(inode, file);
+       kfree(data->rbuffer);
+       kfree(data->wbuffer);
+       kfree(data);
        return 0;
 }
 
@@ -5499,9 +5559,9 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
        cmd.cmd=HOSTSLEEP;
        issuecommand(ai, &cmd, &rsp);
 
-       pci_enable_wake(pdev, state, 1);
+       pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
        pci_save_state(pdev);
-       return pci_set_power_state(pdev, state);
+       return pci_set_power_state(pdev, pci_choose_state(pdev, state));
 }
 
 static int airo_pci_resume(struct pci_dev *pdev)
@@ -5509,12 +5569,13 @@ static int airo_pci_resume(struct pci_dev *pdev)
        struct net_device *dev = pci_get_drvdata(pdev);
        struct airo_info *ai = dev->priv;
        Resp rsp;
+       pci_power_t prev_state = pdev->current_state;
 
-       pci_set_power_state(pdev, 0);
+       pci_set_power_state(pdev, PCI_D0);
        pci_restore_state(pdev);
-       pci_enable_wake(pdev, ai->power, 0);
+       pci_enable_wake(pdev, PCI_D0, 0);
 
-       if (ai->power > 1) {
+       if (prev_state != PCI_D1) {
                reset_card(dev, 0);
                mpi_init_descriptors(ai);
                setup_card(ai, dev->dev_addr, 0);
@@ -5541,7 +5602,7 @@ static int airo_pci_resume(struct pci_dev *pdev)
        }
        writeConfigRid(ai, 0);
        enable_MAC(ai, &rsp, 0);
-       ai->power = 0;
+       ai->power = PMSG_ON;
        netif_device_attach(dev);
        netif_wake_queue(dev);
        enable_interrupts(ai);
@@ -5561,17 +5622,16 @@ static int __init airo_init_module( void )
         airo_entry->gid = proc_gid;
 
        for( i = 0; i < 4 && io[i] && irq[i]; i++ ) {
-               printk( KERN_INFO
-                       "airo:  Trying to configure ISA adapter at irq=%d io=0x%x\n",
-                       irq[i], io[i] );
+               airo_print_info("", "Trying to configure ISA adapter at irq=%d "
+                       "io=0x%x", irq[i], io[i] );
                if (init_airo_card( irq[i], io[i], 0, NULL ))
                        have_isa_dev = 1;
        }
 
 #ifdef CONFIG_PCI
-       printk( KERN_INFO "airo:  Probing for PCI adapters\n" );
+       airo_print_info("", "Probing for PCI adapters");
        pci_register_driver(&airo_driver);
-       printk( KERN_INFO "airo:  Finished probing for PCI adapters\n" );
+       airo_print_info("", "Finished probing for PCI adapters");
 #endif
 
        /* Always exit with success, as we are a library module
@@ -5583,7 +5643,7 @@ static int __init airo_init_module( void )
 static void __exit airo_cleanup_module( void )
 {
        while( airo_devices ) {
-               printk( KERN_INFO "airo: Unregistering %s\n", airo_devices->dev->name );
+               airo_print_info(airo_devices->dev->name, "Unregistering...\n");
                stop_airo_card( airo_devices->dev, 1 );
        }
 #ifdef CONFIG_PCI
@@ -5592,7 +5652,6 @@ static void __exit airo_cleanup_module( void )
        remove_proc_entry("aironet", proc_root_driver);
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Initial Wireless Extension code for Aironet driver by :
  *     Jean Tourrilhes <jt@hpl.hp.com> - HPL - 17 November 00
@@ -5694,13 +5753,14 @@ static int airo_set_freq(struct net_device *dev,
                int channel = fwrq->m;
                /* We should do a better check than that,
                 * based on the card capability !!! */
-               if((channel < 1) || (channel > 16)) {
-                       printk(KERN_DEBUG "%s: New channel value of %d is invalid!\n", dev->name, fwrq->m);
+               if((channel < 1) || (channel > 14)) {
+                       airo_print_dbg(dev->name, "New channel value of %d is invalid!",
+                               fwrq->m);
                        rc = -EINVAL;
                } else {
                        readConfigRid(local, 1);
                        /* Yes ! We can set it !!! */
-                       local->config.channelSet = (u16)(channel - 1);
+                       local->config.channelSet = (u16) channel;
                        set_bit (FLAG_COMMIT, &local->flags);
                }
        }
@@ -5718,6 +5778,7 @@ static int airo_get_freq(struct net_device *dev,
 {
        struct airo_info *local = dev->priv;
        StatusRid status_rid;           /* Card status info */
+       int ch;
 
        readConfigRid(local, 1);
        if ((local->config.opmode & 0xFF) == MODE_STA_ESS)
@@ -5725,16 +5786,14 @@ static int airo_get_freq(struct net_device *dev,
        else
                readStatusRid(local, &status_rid, 1);
 
-#ifdef WEXT_USECHANNELS
-       fwrq->m = ((int)status_rid.channel) + 1;
-       fwrq->e = 0;
-#else
-       {
-               int f = (int)status_rid.channel;
-               fwrq->m = frequency_list[f] * 100000;
+       ch = (int)status_rid.channel;
+       if((ch > 0) && (ch < 15)) {
+               fwrq->m = frequency_list[ch - 1] * 100000;
                fwrq->e = 1;
+       } else {
+               fwrq->m = ch;
+               fwrq->e = 0;
        }
-#endif
 
        return 0;
 }
@@ -5809,7 +5868,7 @@ static int airo_get_essid(struct net_device *dev,
        /* If none, we may want to get the one that was set */
 
        /* Push it out ! */
-       dwrq->length = status_rid.SSIDlen + 1;
+       dwrq->length = status_rid.SSIDlen;
        dwrq->flags = 1; /* active */
 
        return 0;
@@ -5828,11 +5887,13 @@ static int airo_set_wap(struct net_device *dev,
        Cmd cmd;
        Resp rsp;
        APListRid APList_rid;
-       static const unsigned char bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
+       static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+       static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
        if (awrq->sa_family != ARPHRD_ETHER)
                return -EINVAL;
-       else if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
+       else if (!memcmp(any, awrq->sa_data, ETH_ALEN) ||
+                !memcmp(off, awrq->sa_data, ETH_ALEN)) {
                memset(&cmd, 0, sizeof(cmd));
                cmd.cmd=CMD_LOSE_SYNC;
                if (down_interruptible(&local->sem))
@@ -6018,8 +6079,8 @@ static int airo_set_rts(struct net_device *dev,
        int rthr = vwrq->value;
 
        if(vwrq->disabled)
-               rthr = 2312;
-       if((rthr < 0) || (rthr > 2312)) {
+               rthr = AIRO_DEF_MTU;
+       if((rthr < 0) || (rthr > AIRO_DEF_MTU)) {
                return -EINVAL;
        }
        readConfigRid(local, 1);
@@ -6042,7 +6103,7 @@ static int airo_get_rts(struct net_device *dev,
 
        readConfigRid(local, 1);
        vwrq->value = local->config.rtsThres;
-       vwrq->disabled = (vwrq->value >= 2312);
+       vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
        vwrq->fixed = 1;
 
        return 0;
@@ -6061,8 +6122,8 @@ static int airo_set_frag(struct net_device *dev,
        int fthr = vwrq->value;
 
        if(vwrq->disabled)
-               fthr = 2312;
-       if((fthr < 256) || (fthr > 2312)) {
+               fthr = AIRO_DEF_MTU;
+       if((fthr < 256) || (fthr > AIRO_DEF_MTU)) {
                return -EINVAL;
        }
        fthr &= ~0x1;   /* Get an even value - is it really needed ??? */
@@ -6086,7 +6147,7 @@ static int airo_get_frag(struct net_device *dev,
 
        readConfigRid(local, 1);
        vwrq->value = local->config.fragThresh;
-       vwrq->disabled = (vwrq->value >= 2312);
+       vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU);
        vwrq->fixed = 1;
 
        return 0;
@@ -6196,6 +6257,8 @@ static int airo_set_encode(struct net_device *dev,
 {
        struct airo_info *local = dev->priv;
        CapabilityRid cap_rid;          /* Card capability info */
+       int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       u16 currentAuthType = local->config.authType;
 
        /* Is WEP supported ? */
        readCapabilityRid(local, &cap_rid, 1);
@@ -6238,7 +6301,7 @@ static int airo_set_encode(struct net_device *dev,
                        /* Copy the key in the driver */
                        memcpy(key.key, extra, dwrq->length);
                        /* Send the key to the card */
-                       set_wep_key(local, index, key.key, key.len, 1, 1);
+                       set_wep_key(local, index, key.key, key.len, perm, 1);
                }
                /* WE specify that if a valid key is set, encryption
                 * should be enabled (user may turn it off later)
@@ -6246,13 +6309,12 @@ static int airo_set_encode(struct net_device *dev,
                if((index == current_index) && (key.len > 0) &&
                   (local->config.authType == AUTH_OPEN)) {
                        local->config.authType = AUTH_ENCRYPT;
-                       set_bit (FLAG_COMMIT, &local->flags);
                }
        } else {
                /* Do we want to just set the transmit key index ? */
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
                if ((index >= 0) && (index < ((cap_rid.softCap & 0x80)?4:1))) {
-                       set_wep_key(local, index, NULL, 0, 1, 1);
+                       set_wep_key(local, index, NULL, 0, perm, 1);
                } else
                        /* Don't complain if only change the mode */
                        if(!dwrq->flags & IW_ENCODE_MODE) {
@@ -6267,7 +6329,7 @@ static int airo_set_encode(struct net_device *dev,
        if(dwrq->flags & IW_ENCODE_OPEN)
                local->config.authType = AUTH_ENCRYPT;  // Only Wep
        /* Commit the changes to flags if needed */
-       if(dwrq->flags & IW_ENCODE_MODE)
+       if (local->config.authType != currentAuthType)
                set_bit (FLAG_COMMIT, &local->flags);
        return -EINPROGRESS;            /* Call commit handler */
 }
@@ -6320,6 +6382,272 @@ static int airo_get_encode(struct net_device *dev,
        return 0;
 }
 
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended Encryption parameters
+ */
+static int airo_set_encodeext(struct net_device *dev,
+                          struct iw_request_info *info,
+                           union iwreq_data *wrqu,
+                           char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       CapabilityRid cap_rid;          /* Card capability info */
+       int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       u16 currentAuthType = local->config.authType;
+       int idx, key_len, alg = ext->alg, set_key = 1;
+       wep_key_t key;
+
+       /* Is WEP supported ? */
+       readCapabilityRid(local, &cap_rid, 1);
+       /* Older firmware doesn't support this...
+       if(!(cap_rid.softCap & 2)) {
+               return -EOPNOTSUPP;
+       } */
+       readConfigRid(local, 1);
+
+       /* Determine and validate the key index */
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = get_wep_key(local, 0xffff);
+
+       if (encoding->flags & IW_ENCODE_DISABLED)
+               alg = IW_ENCODE_ALG_NONE;
+
+       if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
+               /* Only set transmit key index here, actual
+                * key is set below if needed.
+                */
+               set_wep_key(local, idx, NULL, 0, perm, 1);
+               set_key = ext->key_len > 0 ? 1 : 0;
+       }
+
+       if (set_key) {
+               /* Set the requested key first */
+               memset(key.key, 0, MAX_KEY_SIZE);
+               switch (alg) {
+               case IW_ENCODE_ALG_NONE:
+                       key.len = 0;
+                       break;
+               case IW_ENCODE_ALG_WEP:
+                       if (ext->key_len > MIN_KEY_SIZE) {
+                               key.len = MAX_KEY_SIZE;
+                       } else if (ext->key_len > 0) {
+                               key.len = MIN_KEY_SIZE;
+                       } else {
+                               return -EINVAL;
+                       }
+                       key_len = min (ext->key_len, key.len);
+                       memcpy(key.key, ext->key, key_len);
+                       break;
+               default:
+                       return -EINVAL;
+               }
+               /* Send the key to the card */
+               set_wep_key(local, idx, key.key, key.len, perm, 1);
+       }
+
+       /* Read the flags */
+       if(encoding->flags & IW_ENCODE_DISABLED)
+               local->config.authType = AUTH_OPEN;     // disable encryption
+       if(encoding->flags & IW_ENCODE_RESTRICTED)
+               local->config.authType = AUTH_SHAREDKEY;        // Only Both
+       if(encoding->flags & IW_ENCODE_OPEN)
+               local->config.authType = AUTH_ENCRYPT;  // Only Wep
+       /* Commit the changes to flags if needed */
+       if (local->config.authType != currentAuthType)
+               set_bit (FLAG_COMMIT, &local->flags);
+
+       return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended Encryption parameters
+ */
+static int airo_get_encodeext(struct net_device *dev,
+                           struct iw_request_info *info,
+                           union iwreq_data *wrqu,
+                           char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_point *encoding = &wrqu->encoding;
+       struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
+       CapabilityRid cap_rid;          /* Card capability info */
+       int idx, max_key_len;
+
+       /* Is it supported ? */
+       readCapabilityRid(local, &cap_rid, 1);
+       if(!(cap_rid.softCap & 2)) {
+               return -EOPNOTSUPP;
+       }
+       readConfigRid(local, 1);
+
+       max_key_len = encoding->length - sizeof(*ext);
+       if (max_key_len < 0)
+               return -EINVAL;
+
+       idx = encoding->flags & IW_ENCODE_INDEX;
+       if (idx) {
+               if (idx < 1 || idx > ((cap_rid.softCap & 0x80) ? 4:1))
+                       return -EINVAL;
+               idx--;
+       } else
+               idx = get_wep_key(local, 0xffff);
+
+       encoding->flags = idx + 1;
+       memset(ext, 0, sizeof(*ext));
+
+       /* Check encryption mode */
+       switch(local->config.authType) {
+               case AUTH_ENCRYPT:
+                       encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+                       break;
+               case AUTH_SHAREDKEY:
+                       encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED;
+                       break;
+               default:
+               case AUTH_OPEN:
+                       encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED;
+                       break;
+       }
+       /* We can't return the key, so set the proper flag and return zero */
+       encoding->flags |= IW_ENCODE_NOKEY;
+       memset(extra, 0, 16);
+       
+       /* Copy the key to the user buffer */
+       ext->key_len = get_wep_key(local, idx);
+       if (ext->key_len > 16) {
+               ext->key_len=0;
+       }
+
+       return 0;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set extended authentication parameters
+ */
+static int airo_set_auth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_param *param = &wrqu->param;
+       u16 currentAuthType = local->config.authType;
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_WPA_VERSION:
+       case IW_AUTH_CIPHER_PAIRWISE:
+       case IW_AUTH_CIPHER_GROUP:
+       case IW_AUTH_KEY_MGMT:
+       case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+       case IW_AUTH_PRIVACY_INVOKED:
+               /*
+                * airo does not use these parameters
+                */
+               break;
+
+       case IW_AUTH_DROP_UNENCRYPTED:
+               if (param->value) {
+                       /* Only change auth type if unencrypted */
+                       if (currentAuthType == AUTH_OPEN)
+                               local->config.authType = AUTH_ENCRYPT;
+               } else {
+                       local->config.authType = AUTH_OPEN;
+               }
+
+               /* Commit the changes to flags if needed */
+               if (local->config.authType != currentAuthType)
+                       set_bit (FLAG_COMMIT, &local->flags);
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG: {
+                       /* FIXME: What about AUTH_OPEN?  This API seems to
+                        * disallow setting our auth to AUTH_OPEN.
+                        */
+                       if (param->value & IW_AUTH_ALG_SHARED_KEY) {
+                               local->config.authType = AUTH_SHAREDKEY;
+                       } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
+                               local->config.authType = AUTH_ENCRYPT;
+                       } else
+                               return -EINVAL;
+                       break;
+
+                       /* Commit the changes to flags if needed */
+                       if (local->config.authType != currentAuthType)
+                               set_bit (FLAG_COMMIT, &local->flags);
+               }
+
+       case IW_AUTH_WPA_ENABLED:
+               /* Silently accept disable of WPA */
+               if (param->value > 0)
+                       return -EOPNOTSUPP;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+       return -EINPROGRESS;
+}
+
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get extended authentication parameters
+ */
+static int airo_get_auth(struct net_device *dev,
+                              struct iw_request_info *info,
+                              union iwreq_data *wrqu, char *extra)
+{
+       struct airo_info *local = dev->priv;
+       struct iw_param *param = &wrqu->param;
+       u16 currentAuthType = local->config.authType;
+
+       switch (param->flags & IW_AUTH_INDEX) {
+       case IW_AUTH_DROP_UNENCRYPTED:
+               switch (currentAuthType) {
+               case AUTH_SHAREDKEY:
+               case AUTH_ENCRYPT:
+                       param->value = 1;
+                       break;
+               default:
+                       param->value = 0;
+                       break;
+               }
+               break;
+
+       case IW_AUTH_80211_AUTH_ALG:
+               switch (currentAuthType) {
+               case AUTH_SHAREDKEY:
+                       param->value = IW_AUTH_ALG_SHARED_KEY;
+                       break;
+               case AUTH_ENCRYPT:
+               default:
+                       param->value = IW_AUTH_ALG_OPEN_SYSTEM;
+                       break;
+               }
+               break;
+
+       case IW_AUTH_WPA_ENABLED:
+               param->value = 0;
+               break;
+
+       default:
+               return -EOPNOTSUPP;
+       }
+       return 0;
+}
+
+
 /*------------------------------------------------------------------*/
 /*
  * Wireless Handler : set Tx-Power
@@ -6483,22 +6811,20 @@ static int airo_get_range(struct net_device *dev,
                range->max_qual.qual = 100;     /* % */
        else
                range->max_qual.qual = airo_get_max_quality(&cap_rid);
-       range->max_qual.level = 0;      /* 0 means we use dBm  */
-       range->max_qual.noise = 0;
-       range->max_qual.updated = 0;
+       range->max_qual.level = 0x100 - 120;    /* -120 dBm */
+       range->max_qual.noise = 0x100 - 120;    /* -120 dBm */
 
        /* Experimental measurements - boundary 11/5.5 Mb/s */
        /* Note : with or without the (local->rssi), results
         * are somewhat different. - Jean II */
        if (local->rssi) {
-               range->avg_qual.qual = 50;      /* % */
-               range->avg_qual.level = 186;    /* -70 dBm */
+               range->avg_qual.qual = 50;              /* % */
+               range->avg_qual.level = 0x100 - 70;     /* -70 dBm */
        } else {
                range->avg_qual.qual = airo_get_avg_quality(&cap_rid);
-               range->avg_qual.level = 176;    /* -80 dBm */
+               range->avg_qual.level = 0x100 - 80;     /* -80 dBm */
        }
-       range->avg_qual.noise = 0;
-       range->avg_qual.updated = 0;
+       range->avg_qual.noise = 0x100 - 85;             /* -85 dBm */
 
        for(i = 0 ; i < 8 ; i++) {
                range->bitrate[i] = cap_rid.supportedRates[i] * 500000;
@@ -6516,9 +6842,9 @@ static int airo_get_range(struct net_device *dev,
                range->throughput = 1500 * 1000;
 
        range->min_rts = 0;
-       range->max_rts = 2312;
+       range->max_rts = AIRO_DEF_MTU;
        range->min_frag = 256;
-       range->max_frag = 2312;
+       range->max_frag = AIRO_DEF_MTU;
 
        if(cap_rid.softCap & 2) {
                // WEP: RC4 40 bits
@@ -6721,15 +7047,17 @@ static int airo_get_aplist(struct net_device *dev,
                if (local->rssi) {
                        qual[i].level = 0x100 - BSSList.dBm;
                        qual[i].qual = airo_dbm_to_pct( local->rssi, BSSList.dBm );
-                       qual[i].updated = IW_QUAL_QUAL_UPDATED;
+                       qual[i].updated = IW_QUAL_QUAL_UPDATED
+                                       | IW_QUAL_LEVEL_UPDATED
+                                       | IW_QUAL_DBM;
                } else {
                        qual[i].level = (BSSList.dBm + 321) / 2;
                        qual[i].qual = 0;
-                       qual[i].updated = IW_QUAL_QUAL_INVALID;
+                       qual[i].updated = IW_QUAL_QUAL_INVALID
+                                       | IW_QUAL_LEVEL_UPDATED
+                                       | IW_QUAL_DBM;
                }
                qual[i].noise = local->wstats.qual.noise;
-               qual[i].updated = IW_QUAL_LEVEL_UPDATED
-                               | IW_QUAL_NOISE_UPDATED;
                if (BSSList.index == 0xffff)
                        break;
        }
@@ -6777,6 +7105,7 @@ static int airo_set_scan(struct net_device *dev,
        struct airo_info *ai = dev->priv;
        Cmd cmd;
        Resp rsp;
+       int wake = 0;
 
        /* Note : you may have realised that, as this is a SET operation,
         * this is privileged and therefore a normal user can't
@@ -6786,17 +7115,25 @@ static int airo_set_scan(struct net_device *dev,
         * Jean II */
        if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN;
 
+       if (down_interruptible(&ai->sem))
+               return -ERESTARTSYS;
+
+       /* If there's already a scan in progress, don't
+        * trigger another one. */
+       if (ai->scan_timeout > 0)
+               goto out;
+
        /* Initiate a scan command */
+       ai->scan_timeout = RUN_AT(3*HZ);
        memset(&cmd, 0, sizeof(cmd));
        cmd.cmd=CMD_LISTBSS;
-       if (down_interruptible(&ai->sem))
-               return -ERESTARTSYS;
        issuecommand(ai, &cmd, &rsp);
-       ai->scan_timestamp = jiffies;
-       up(&ai->sem);
-
-       /* At this point, just return to the user. */
+       wake = 1;
 
+out:
+       up(&ai->sem);
+       if (wake)
+               wake_up_interruptible(&ai->thr_wait);
        return 0;
 }
 
@@ -6846,7 +7183,10 @@ static inline char *airo_translate_scan(struct net_device *dev,
        /* Add frequency */
        iwe.cmd = SIOCGIWFREQ;
        iwe.u.freq.m = le16_to_cpu(bss->dsChannel);
-       iwe.u.freq.m = frequency_list[iwe.u.freq.m] * 100000;
+       /* iwe.u.freq.m containt the channel (starting 1), our 
+        * frequency_list array start at index 0...
+        */
+       iwe.u.freq.m = frequency_list[iwe.u.freq.m - 1] * 100000;
        iwe.u.freq.e = 1;
        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
 
@@ -6855,15 +7195,17 @@ static inline char *airo_translate_scan(struct net_device *dev,
        if (ai->rssi) {
                iwe.u.qual.level = 0x100 - bss->dBm;
                iwe.u.qual.qual = airo_dbm_to_pct( ai->rssi, bss->dBm );
-               iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED;
+               iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED
+                               | IW_QUAL_LEVEL_UPDATED
+                               | IW_QUAL_DBM;
        } else {
                iwe.u.qual.level = (bss->dBm + 321) / 2;
                iwe.u.qual.qual = 0;
-               iwe.u.qual.updated = IW_QUAL_QUAL_INVALID;
+               iwe.u.qual.updated = IW_QUAL_QUAL_INVALID
+                               | IW_QUAL_LEVEL_UPDATED
+                               | IW_QUAL_DBM;
        }
        iwe.u.qual.noise = ai->wstats.qual.noise;
-       iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED
-                       | IW_QUAL_NOISE_UPDATED;
        current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
 
        /* Add encryption capability */
@@ -6911,59 +7253,38 @@ static int airo_get_scan(struct net_device *dev,
                         char *extra)
 {
        struct airo_info *ai = dev->priv;
-       BSSListRid BSSList;
-       int rc;
+       BSSListElement *net;
+       int err = 0;
        char *current_ev = extra;
 
-       /* When we are associated again, the scan has surely finished.
-        * Just in case, let's make sure enough time has elapsed since
-        * we started the scan. - Javier */
-       if(ai->scan_timestamp && time_before(jiffies,ai->scan_timestamp+3*HZ)) {
-               /* Important note : we don't want to block the caller
-                * until results are ready for various reasons.
-                * First, managing wait queues is complex and racy
-                * (there may be multiple simultaneous callers).
-                * Second, we grab some rtnetlink lock before comming
-                * here (in dev_ioctl()).
-                * Third, the caller can wait on the Wireless Event
-                * - Jean II */
+       /* If a scan is in-progress, return -EAGAIN */
+       if (ai->scan_timeout > 0)
                return -EAGAIN;
-       }
-       ai->scan_timestamp = 0;
-
-       /* There's only a race with proc_BSSList_open(), but its
-        * consequences are begnign. So I don't bother fixing it - Javier */
 
-       /* Try to read the first entry of the scan result */
-       rc = PC4500_readrid(ai, RID_BSSLISTFIRST, &BSSList, sizeof(BSSList), 1);
-       if((rc) || (BSSList.index == 0xffff)) {
-               /* Client error, no scan results...
-                * The caller need to restart the scan. */
-               return -ENODATA;
-       }
+       if (down_interruptible(&ai->sem))
+               return -EAGAIN;
 
-       /* Read and parse all entries */
-       while((!rc) && (BSSList.index != 0xffff)) {
+       list_for_each_entry (net, &ai->network_list, list) {
                /* Translate to WE format this entry */
                current_ev = airo_translate_scan(dev, current_ev,
                                                 extra + dwrq->length,
-                                                &BSSList);
+                                                &net->bss);
 
                /* Check if there is space for one more entry */
                if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) {
                        /* Ask user space to try again with a bigger buffer */
-                       return -E2BIG;
+                       err = -E2BIG;
+                       goto out;
                }
-
-               /* Read next entry */
-               rc = PC4500_readrid(ai, RID_BSSLISTNEXT,
-                                   &BSSList, sizeof(BSSList), 1);
        }
+
        /* Length of data */
        dwrq->length = (current_ev - extra);
        dwrq->flags = 0;        /* todo */
 
-       return 0;
+out:
+       up(&ai->sem);
+       return err;
 }
 
 /*------------------------------------------------------------------*/
@@ -7071,6 +7392,15 @@ static const iw_handler          airo_handler[] =
        (iw_handler) airo_get_encode,           /* SIOCGIWENCODE */
        (iw_handler) airo_set_power,            /* SIOCSIWPOWER */
        (iw_handler) airo_get_power,            /* SIOCGIWPOWER */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* -- hole -- */
+       (iw_handler) NULL,                      /* SIOCSIWGENIE */
+       (iw_handler) NULL,                      /* SIOCGIWGENIE */
+       (iw_handler) airo_set_auth,             /* SIOCSIWAUTH */
+       (iw_handler) airo_get_auth,             /* SIOCGIWAUTH */
+       (iw_handler) airo_set_encodeext,        /* SIOCSIWENCODEEXT */
+       (iw_handler) airo_get_encodeext,        /* SIOCGIWENCODEEXT */
+       (iw_handler) NULL,                      /* SIOCSIWPMKSA */
 };
 
 /* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here.
@@ -7096,8 +7426,6 @@ static const struct iw_handler_def        airo_handler_def =
        .get_wireless_stats = airo_get_wireless_stats,
 };
 
-#endif /* WIRELESS_EXT */
-
 /*
  * This defines the configuration part of the Wireless Extensions
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7116,7 +7444,7 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        int rc = 0;
        struct airo_info *ai = (struct airo_info *)dev->priv;
 
-       if (ai->power)
+       if (ai->power.event)
                return 0;
 
        switch (cmd) {
@@ -7176,7 +7504,6 @@ static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
        return rc;
 }
 
-#ifdef WIRELESS_EXT
 /*
  * Get the Wireless stats out of the driver
  * Note : irq and spinlock protection will occur in the subroutines
@@ -7195,7 +7522,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 
        /* Get stats out of the card */
        clear_bit(JOB_WSTATS, &local->flags);
-       if (local->power) {
+       if (local->power.event) {
                up(&local->sem);
                return;
        }
@@ -7216,13 +7543,12 @@ static void airo_read_wireless_stats(struct airo_info *local)
                local->wstats.qual.level = (status_rid.normalizedSignalStrength + 321) / 2;
                local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid);
        }
-       local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED;
        if (status_rid.len >= 124) {
                local->wstats.qual.noise = 0x100 - status_rid.noisedBm;
-               local->wstats.qual.updated |= IW_QUAL_NOISE_UPDATED;
+               local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
        } else {
                local->wstats.qual.noise = 0;
-               local->wstats.qual.updated |= IW_QUAL_NOISE_INVALID;
+               local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM;
        }
 
        /* Packets discarded in the wireless adapter due to wireless
@@ -7235,7 +7561,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
        local->wstats.miss.beacon = vals[34];
 }
 
-struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
+static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
        struct airo_info *local =  dev->priv;
 
@@ -7250,7 +7576,6 @@ struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 
        return &local->wstats;
 }
-#endif /* WIRELESS_EXT */
 
 #ifdef CISCO_EXT
 /*
@@ -7296,13 +7621,11 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
        case AIROGSTAT:     ridcode = RID_STATUS;       break;
        case AIROGSTATSD32: ridcode = RID_STATSDELTA;   break;
        case AIROGSTATSC32: ridcode = RID_STATS;        break;
-#ifdef MICSUPPORT
        case AIROGMICSTATS:
                if (copy_to_user(comp->data, &ai->micstats,
                                 min((int)comp->len,(int)sizeof(ai->micstats))))
                        return -EFAULT;
                return 0;
-#endif
        case AIRORRID:      ridcode = comp->ridnum;     break;
        default:
                return -EINVAL;
@@ -7334,9 +7657,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
 static int writerids(struct net_device *dev, aironet_ioctl *comp) {
        struct airo_info *ai = dev->priv;
        int  ridcode;
-#ifdef MICSUPPORT
         int  enabled;
-#endif
        Resp      rsp;
        static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
        unsigned char *iobuf;
@@ -7393,11 +7714,9 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
 
                PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1);
 
-#ifdef MICSUPPORT
                enabled = ai->micstats.enabled;
                memset(&ai->micstats,0,sizeof(ai->micstats));
                ai->micstats.enabled = enabled;
-#endif
 
                if (copy_to_user(comp->data, iobuf,
                                 min((int)comp->len, (int)RIDSIZE))) {
@@ -7450,14 +7769,8 @@ static int writerids(struct net_device *dev, aironet_ioctl *comp) {
  * Flash command switch table
  */
 
-int flashcard(struct net_device *dev, aironet_ioctl *comp) {
+static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
        int z;
-       int cmdreset(struct airo_info *);
-       int setflashmode(struct airo_info *);
-       int flashgchar(struct airo_info *,int,int);
-       int flashpchar(struct airo_info *,int,int);
-       int flashputbuf(struct airo_info *);
-       int flashrestart(struct airo_info *,struct net_device *);
 
        /* Only super-user can modify flash */
        if (!capable(CAP_NET_ADMIN))
@@ -7515,11 +7828,11 @@ int flashcard(struct net_device *dev, aironet_ioctl *comp) {
  * card.
  */
 
-int cmdreset(struct airo_info *ai) {
+static int cmdreset(struct airo_info *ai) {
        disable_MAC(ai, 1);
 
        if(!waitbusy (ai)){
-               printk(KERN_INFO "Waitbusy hang before RESET\n");
+               airo_print_info(ai->dev->name, "Waitbusy hang before RESET");
                return -EBUSY;
        }
 
@@ -7528,7 +7841,7 @@ int cmdreset(struct airo_info *ai) {
        ssleep(1);                      /* WAS 600 12/7/00 */
 
        if(!waitbusy (ai)){
-               printk(KERN_INFO "Waitbusy hang AFTER RESET\n");
+               airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET");
                return -EBUSY;
        }
        return 0;
@@ -7539,7 +7852,7 @@ int cmdreset(struct airo_info *ai) {
  * mode
  */
 
-int setflashmode (struct airo_info *ai) {
+static int setflashmode (struct airo_info *ai) {
        set_bit (FLAG_FLASHING, &ai->flags);
 
        OUT4500(ai, SWS0, FLASH_COMMAND);
@@ -7556,7 +7869,7 @@ int setflashmode (struct airo_info *ai) {
 
        if(!waitbusy(ai)) {
                clear_bit (FLAG_FLASHING, &ai->flags);
-               printk(KERN_INFO "Waitbusy hang after setflash mode\n");
+               airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode");
                return -EIO;
        }
        return 0;
@@ -7566,7 +7879,7 @@ int setflashmode (struct airo_info *ai) {
  * x 50us for  echo .
  */
 
-int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
+static int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
        int echo;
        int waittime;
 
@@ -7585,7 +7898,7 @@ int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
 
        /* timeout for busy clear wait */
        if(waittime <= 0 ){
-               printk(KERN_INFO "flash putchar busywait timeout! \n");
+               airo_print_info(ai->dev->name, "flash putchar busywait timeout!");
                return -EBUSY;
        }
 
@@ -7606,7 +7919,7 @@ int flashpchar(struct airo_info *ai,int byte,int dwelltime) {
  * Get a character from the card matching matchbyte
  * Step 3)
  */
-int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
+static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
        int           rchar;
        unsigned char rbyte=0;
 
@@ -7637,7 +7950,7 @@ int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){
  * send to the card
  */
 
-int flashputbuf(struct airo_info *ai){
+static int flashputbuf(struct airo_info *ai){
        int            nwords;
 
        /* Write stuff */
@@ -7659,7 +7972,7 @@ int flashputbuf(struct airo_info *ai){
 /*
  *
  */
-int flashrestart(struct airo_info *ai,struct net_device *dev){
+static int flashrestart(struct airo_info *ai,struct net_device *dev){
        int    i,status;
 
        ssleep(1);                      /* Added 12/7/00 */
@@ -7674,7 +7987,7 @@ int flashrestart(struct airo_info *ai,struct net_device *dev){
        if (!test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ ) {
                        ai->fids[i] = transmit_allocate
-                               ( ai, 2312, i >= MAX_FIDS / 2 );
+                               ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 );
                }
 
        ssleep(1);                      /* Added 12/7/00 */