wireless: airo_cs build fixes
[safe/jmp/linux-2.6] / drivers / net / wireless / airo.c
index b5cd850..260fb99 100644 (file)
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <asm/uaccess.h>
-#include <net/ieee80211.h>
 #include <linux/kthread.h>
 #include <linux/freezer.h>
 
+#include <linux/ieee80211.h>
+#include <net/iw_handler.h>
+
 #include "airo.h"
 
 #define DRV_NAME "airo"
@@ -495,39 +497,41 @@ typedef struct {
  * so all rid access should use the read/writeXXXRid routines.
  */
 
-/* This is redundant for x86 archs, but it seems necessary for ARM */
-#pragma pack(1)
-
 /* This structure came from an email sent to me from an engineer at
    aironet for inclusion into this driver */
-typedef struct {
+typedef struct WepKeyRid WepKeyRid;
+struct WepKeyRid {
        __le16 len;
        __le16 kindex;
        u8 mac[ETH_ALEN];
        __le16 klen;
        u8 key[16];
-} WepKeyRid;
+} __attribute__ ((packed));
 
 /* These structures are from the Aironet's PC4500 Developers Manual */
-typedef struct {
+typedef struct Ssid Ssid;
+struct Ssid {
        __le16 len;
        u8 ssid[32];
-} Ssid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct SsidRid SsidRid;
+struct SsidRid {
        __le16 len;
        Ssid ssids[3];
-} SsidRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct ModulationRid ModulationRid;
+struct ModulationRid {
         __le16 len;
         __le16 modulation;
 #define MOD_DEFAULT cpu_to_le16(0)
 #define MOD_CCK cpu_to_le16(1)
 #define MOD_MOK cpu_to_le16(2)
-} ModulationRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct ConfigRid ConfigRid;
+struct ConfigRid {
        __le16 len; /* sizeof(ConfigRid) */
        __le16 opmode; /* operating mode */
 #define MODE_STA_IBSS cpu_to_le16(0)
@@ -648,9 +652,10 @@ typedef struct {
 #define MAGIC_STAY_IN_CAM (1<<10)
        u8 magicControl;
        __le16 autoWake;
-} ConfigRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct StatusRid StatusRid;
+struct StatusRid {
        __le16 len;
        u8 mac[ETH_ALEN];
        __le16 mode;
@@ -706,21 +711,23 @@ typedef struct {
 #define STAT_LEAPFAILED 91
 #define STAT_LEAPTIMEDOUT 92
 #define STAT_LEAPCOMPLETE 93
-} StatusRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct StatsRid StatsRid;
+struct StatsRid {
        __le16 len;
        __le16 spacer;
        __le32 vals[100];
-} StatsRid;
-
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct APListRid APListRid;
+struct APListRid {
        __le16 len;
        u8 ap[4][ETH_ALEN];
-} APListRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct CapabilityRid CapabilityRid;
+struct CapabilityRid {
        __le16 len;
        char oui[3];
        char zero;
@@ -747,17 +754,18 @@ typedef struct {
        __le16 bootBlockVer;
        __le16 requiredHard;
        __le16 extSoftCap;
-} CapabilityRid;
-
+} __attribute__ ((packed));
 
 /* Only present on firmware >= 5.30.17 */
-typedef struct {
+typedef struct BSSListRidExtra BSSListRidExtra;
+struct BSSListRidExtra {
   __le16 unknown[4];
   u8 fixed[12]; /* WLAN management frame */
   u8 iep[624];
-} BSSListRidExtra;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct BSSListRid BSSListRid;
+struct BSSListRid {
   __le16 len;
   __le16 index; /* First is 0 and 0xffff means end of list */
 #define RADIO_FH 1 /* Frequency hopping radio type */
@@ -788,33 +796,37 @@ typedef struct {
 
   /* Only present on firmware >= 5.30.17 */
   BSSListRidExtra extra;
-} BSSListRid;
+} __attribute__ ((packed));
 
 typedef struct {
   BSSListRid bss;
   struct list_head list;
 } BSSListElement;
 
-typedef struct {
+typedef struct tdsRssiEntry tdsRssiEntry;
+struct tdsRssiEntry {
   u8 rssipct;
   u8 rssidBm;
-} tdsRssiEntry;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct tdsRssiRid tdsRssiRid;
+struct tdsRssiRid {
   u16 len;
   tdsRssiEntry x[256];
-} tdsRssiRid;
+} __attribute__ ((packed));
 
-typedef struct {
-       u16 len;
-       u16 state;
-       u16 multicastValid;
+typedef struct MICRid MICRid;
+struct MICRid {
+       __le16 len;
+       __le16 state;
+       __le16 multicastValid;
        u8  multicast[16];
-       u16 unicastValid;
+       __le16 unicastValid;
        u8  unicast[16];
-} MICRid;
+} __attribute__ ((packed));
 
-typedef struct {
+typedef struct MICBuffer MICBuffer;
+struct MICBuffer {
        __be16 typelen;
 
        union {
@@ -829,15 +841,13 @@ typedef struct {
        } u;
        __be32 mic;
        __be32 seq;
-} MICBuffer;
+} __attribute__ ((packed));
 
 typedef struct {
        u8 da[ETH_ALEN];
        u8 sa[ETH_ALEN];
 } etherHead;
 
-#pragma pack()
-
 #define TXCTL_TXOK (1<<1) /* report if tx is ok */
 #define TXCTL_TXEX (1<<2) /* report if tx fails */
 #define TXCTL_802_3 (0<<3) /* 802.3 packet */
@@ -980,6 +990,14 @@ typedef struct {
        dma_addr_t host_addr;
 } TxFid;
 
+struct rx_hdr {
+       __le16 status, len;
+       u8 rssi[2];
+       u8 rate;
+       u8 freq;
+       __le16 tmp[4];
+} __attribute__ ((packed));
+
 typedef struct {
        unsigned int  ctl: 15;
        unsigned int  rdy: 1;
@@ -1069,10 +1087,6 @@ static WifiCtlHdr wifictlhdr8023 = {
        }
 };
 
-// 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 };
-
 // A few details needed for WEP (Wireless Equivalent Privacy)
 #define MAX_KEY_SIZE 13                        // 128 (?) bits
 #define MIN_KEY_SIZE  5                        // 40 bits RC4 - WEP
@@ -1081,12 +1095,6 @@ typedef struct wep_key_t {
        u8      key[16];        /* 40-bit and 104-bit keys */
 } wep_key_t;
 
-/* Backward compatibility */
-#ifndef IW_ENCODE_NOKEY
-#define IW_ENCODE_NOKEY         0x0800  /* Key is write only, so not present */
-#define IW_ENCODE_MODE  (IW_ENCODE_DISABLED | IW_ENCODE_RESTRICTED | IW_ENCODE_OPEN)
-#endif /* IW_ENCODE_NOKEY */
-
 /* List of Wireless Handlers (new API) */
 static const struct iw_handler_def     airo_handler_def;
 
@@ -1154,7 +1162,7 @@ struct airo_info {
           use the high bit to mark whether it is in use. */
 #define MAX_FIDS 6
 #define MPI_MAX_FIDS 1
-       int                           fids[MAX_FIDS];
+       u32                           fids[MAX_FIDS];
        ConfigRid config;
        char keyindex; // Used with auto wep
        char defindex; // Used with auto wep
@@ -1228,6 +1236,9 @@ struct airo_info {
 #define        PCI_SHARED_LEN          2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE
        char                    proc_name[IFNAMSIZ];
 
+       int                     wep_capable;
+       int                     max_wep_idx;
+
        /* WPA-related stuff */
        unsigned int bssListFirst;
        unsigned int bssListNext;
@@ -1270,6 +1281,7 @@ static int flashrestart(struct airo_info *ai,struct net_device *dev);
 #define airo_print_err(name, fmt, args...) \
        airo_print(KERN_ERR, name, fmt, ##args)
 
+#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash)
 
 /***********************************************************************
  *                              MIC ROUTINES                           *
@@ -1285,6 +1297,29 @@ 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);
 
+static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len,
+                           struct crypto_cipher *tfm)
+{
+       /* If the current MIC context is valid and its key is the same as
+        * the MIC register, there's nothing to do.
+        */
+       if (cur->valid && (memcmp(cur->key, key, key_len) == 0))
+               return;
+
+       /* Age current mic Context */
+       memcpy(old, cur, sizeof(*cur));
+
+       /* Initialize new context */
+       memcpy(cur->key, key, key_len);
+       cur->window  = 33; /* Window always points to the middle */
+       cur->rx      = 0;  /* Rx Sequence numbers */
+       cur->tx      = 0;  /* Tx sequence numbers */
+       cur->valid   = 1;  /* Key is now valid */
+
+       /* Give key to mic seed */
+       emmh32_setseed(&cur->seed, key, key_len, tfm);
+}
+
 /* micinit - Initialize mic seed */
 
 static void micinit(struct airo_info *ai)
@@ -1295,49 +1330,26 @@ static void micinit(struct airo_info *ai)
        PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0);
        up(&ai->sem);
 
-       ai->micstats.enabled = (mic_rid.state & 0x00FF) ? 1 : 0;
-
-       if (ai->micstats.enabled) {
-               /* Key must be valid and different */
-               if (mic_rid.multicastValid && (!ai->mod[0].mCtx.valid ||
-                   (memcmp (ai->mod[0].mCtx.key, mic_rid.multicast,
-                            sizeof(ai->mod[0].mCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].mCtx,&ai->mod[0].mCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].mCtx.key,mic_rid.multicast,sizeof(mic_rid.multicast));
-                       ai->mod[0].mCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].mCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].mCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].mCtx.valid   = 1;  //Key is now valid
-  
-                       /* Give key to mic seed */
-                       emmh32_setseed(&ai->mod[0].mCtx.seed,mic_rid.multicast,sizeof(mic_rid.multicast), ai->tfm);
-               }
-
-               /* Key must be valid and different */
-               if (mic_rid.unicastValid && (!ai->mod[0].uCtx.valid || 
-                   (memcmp(ai->mod[0].uCtx.key, mic_rid.unicast,
-                           sizeof(ai->mod[0].uCtx.key)) != 0))) {
-                       /* Age current mic Context */
-                       memcpy(&ai->mod[1].uCtx,&ai->mod[0].uCtx,sizeof(miccntx));
-                       /* Initialize new context */
-                       memcpy(&ai->mod[0].uCtx.key,mic_rid.unicast,sizeof(mic_rid.unicast));
-       
-                       ai->mod[0].uCtx.window  = 33; //Window always points to the middle
-                       ai->mod[0].uCtx.rx      = 0;  //Rx Sequence numbers
-                       ai->mod[0].uCtx.tx      = 0;  //Tx sequence numbers
-                       ai->mod[0].uCtx.valid   = 1;  //Key is now valid
-       
-                       //Give key to mic seed
-                       emmh32_setseed(&ai->mod[0].uCtx.seed, mic_rid.unicast, sizeof(mic_rid.unicast), ai->tfm);
-               }
-       } else {
-      /* So next time we have a valid key and mic is enabled, we will update
-       * the sequence number if the key is the same as before.
-       */
+       ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0;
+       if (!ai->micstats.enabled) {
+               /* So next time we have a valid key and mic is enabled, we will
+                * update the sequence number if the key is the same as before.
+                */
                ai->mod[0].uCtx.valid = 0;
                ai->mod[0].mCtx.valid = 0;
+               return;
+       }
+
+       if (mic_rid.multicastValid) {
+               age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx,
+                               mic_rid.multicast, sizeof(mic_rid.multicast),
+                               ai->tfm);
+       }
+
+       if (mic_rid.unicastValid) {
+               age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx,
+                               mic_rid.unicast, sizeof(mic_rid.unicast),
+                               ai->tfm);
        }
 }
 
@@ -1865,7 +1877,7 @@ static void try_auto_wep(struct airo_info *ai)
 }
 
 static int airo_open(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int rc = 0;
 
        if (test_bit(FLAG_FLASHING, &ai->flags))
@@ -1909,14 +1921,16 @@ static int airo_open(struct net_device *dev) {
        return 0;
 }
 
-static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t mpi_start_xmit(struct sk_buff *skb,
+                                       struct net_device *dev)
+{
        int npacks, pending;
        unsigned long flags;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (!skb) {
-               airo_print_err(dev->name, "%s: skb == NULL!",__FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!",__func__);
+               return NETDEV_TX_OK;
        }
        npacks = skb_queue_len (&ai->txq);
 
@@ -1924,10 +1938,10 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                netif_stop_queue (dev);
                if (npacks > MAXTXQ) {
                        dev->stats.tx_fifo_errors++;
-                       return 1;
+                       return NETDEV_TX_BUSY;
                }
                skb_queue_tail (&ai->txq, skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
 
        spin_lock_irqsave(&ai->aux_lock, flags);
@@ -1940,7 +1954,7 @@ static int mpi_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                set_bit(FLAG_PENDING_XMIT, &ai->flags);
                mpi_send_packet (dev);
        }
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 /*
@@ -1956,7 +1970,7 @@ static int mpi_send_packet (struct net_device *dev)
        unsigned char *buffer;
        s16 len;
        __le16 *payloadLen;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        u8 *sendbuf;
 
        /* get a packet to send */
@@ -1964,7 +1978,7 @@ static int mpi_send_packet (struct net_device *dev)
        if ((skb = skb_dequeue(&ai->txq)) == NULL) {
                airo_print_err(dev->name,
                        "%s: Dequeue'd zero in send_packet()",
-                       __FUNCTION__);
+                       __func__);
                return 0;
        }
 
@@ -2085,7 +2099,7 @@ static void get_tx_error(struct airo_info *ai, s32 fid)
 static void airo_end_xmit(struct net_device *dev) {
        u16 status;
        int i;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        struct sk_buff *skb = priv->xmit.skb;
        int fid = priv->xmit.fid;
        u32 *fids = priv->fids;
@@ -2108,15 +2122,17 @@ static void airo_end_xmit(struct net_device *dev) {
        dev_kfree_skb(skb);
 }
 
-static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t airo_start_xmit(struct sk_buff *skb,
+                                        struct net_device *dev)
+{
        s16 len;
        int i, j;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        u32 *fids = priv->fids;
 
        if ( skb == NULL ) {
-               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!", __func__);
+               return NETDEV_TX_OK;
        }
 
        /* Find a vacant FID */
@@ -2128,7 +2144,7 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
 
                if (i == MAX_FIDS / 2) {
                        dev->stats.tx_fifo_errors++;
-                       return 1;
+                       return NETDEV_TX_BUSY;
                }
        }
        /* check min length*/
@@ -2144,13 +2160,13 @@ static int airo_start_xmit(struct sk_buff *skb, struct net_device *dev) {
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit(dev);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void airo_end_xmit11(struct net_device *dev) {
        u16 status;
        int i;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        struct sk_buff *skb = priv->xmit11.skb;
        int fid = priv->xmit11.fid;
        u32 *fids = priv->fids;
@@ -2173,21 +2189,24 @@ static void airo_end_xmit11(struct net_device *dev) {
        dev_kfree_skb(skb);
 }
 
-static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
+static netdev_tx_t airo_start_xmit11(struct sk_buff *skb,
+                                          struct net_device *dev)
+{
        s16 len;
        int i, j;
-       struct airo_info *priv = dev->priv;
+       struct airo_info *priv = dev->ml_priv;
        u32 *fids = priv->fids;
 
        if (test_bit(FLAG_MPI, &priv->flags)) {
                /* Not implemented yet for MPI350 */
                netif_stop_queue(dev);
-               return -ENETDOWN;
+               dev_kfree_skb_any(skb);
+               return NETDEV_TX_OK;
        }
 
        if ( skb == NULL ) {
-               airo_print_err(dev->name, "%s: skb == NULL!", __FUNCTION__);
-               return 0;
+               airo_print_err(dev->name, "%s: skb == NULL!", __func__);
+               return NETDEV_TX_OK;
        }
 
        /* Find a vacant FID */
@@ -2199,7 +2218,7 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
 
                if (i == MAX_FIDS) {
                        dev->stats.tx_fifo_errors++;
-                       return 1;
+                       return NETDEV_TX_BUSY;
                }
        }
        /* check min length*/
@@ -2215,12 +2234,12 @@ static int airo_start_xmit11(struct sk_buff *skb, struct net_device *dev) {
                wake_up_interruptible(&priv->thr_wait);
        } else
                airo_end_xmit11(dev);
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 static void airo_read_stats(struct net_device *dev)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        StatsRid stats_rid;
        __le32 *vals = stats_rid.vals;
 
@@ -2254,7 +2273,7 @@ static void airo_read_stats(struct net_device *dev)
 
 static struct net_device_stats *airo_get_stats(struct net_device *dev)
 {
-       struct airo_info *local =  dev->priv;
+       struct airo_info *local =  dev->ml_priv;
 
        if (!test_bit(JOB_STATS, &local->jobs)) {
                /* Get stats out of the card if available */
@@ -2281,7 +2300,7 @@ static void airo_set_promisc(struct airo_info *ai) {
 }
 
 static void airo_set_multicast_list(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if ((dev->flags ^ ai->flags) & IFF_PROMISC) {
                change_bit(FLAG_PROMISC, &ai->flags);
@@ -2299,7 +2318,7 @@ static void airo_set_multicast_list(struct net_device *dev) {
 
 static int airo_set_mac_address(struct net_device *dev, void *p)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        struct sockaddr *addr = p;
 
        readConfigRid(ai, 1);
@@ -2339,7 +2358,7 @@ static void del_airo_dev(struct airo_info *ai)
 }
 
 static int airo_close(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        netif_stop_queue(dev);
 
@@ -2365,7 +2384,7 @@ static int airo_close(struct net_device *dev) {
 
 void stop_airo_card( struct net_device *dev, int freeres )
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        set_bit(FLAG_RADIO_DOWN, &ai->flags);
        disable_MAC(ai, 1);
@@ -2635,17 +2654,21 @@ static const struct header_ops airo_header_ops = {
        .parse = wll_header_parse,
 };
 
+static const struct net_device_ops airo11_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = airo_start_xmit11,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+};
+
 static void wifi_setup(struct net_device *dev)
 {
+       dev->netdev_ops = &airo11_netdev_ops;
        dev->header_ops = &airo_header_ops;
-       dev->hard_start_xmit = &airo_start_xmit11;
-       dev->get_stats = &airo_get_stats;
-       dev->set_mac_address = &airo_set_mac_address;
-       dev->do_ioctl = &airo_ioctl;
        dev->wireless_handlers = &airo_handler_def;
-       dev->change_mtu = &airo_change_mtu;
-       dev->open = &airo_open;
-       dev->stop = &airo_close;
 
        dev->type               = ARPHRD_IEEE80211;
        dev->hard_header_len    = ETH_HLEN;
@@ -2665,7 +2688,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
        struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup);
        if (!dev)
                return NULL;
-       dev->priv = ethdev->priv;
+       dev->ml_priv = ethdev->ml_priv;
        dev->irq = ethdev->irq;
        dev->base_addr = ethdev->base_addr;
        dev->wireless_data = ethdev->wireless_data;
@@ -2680,7 +2703,7 @@ static struct net_device *init_wifidev(struct airo_info *ai,
 }
 
 static int reset_card( struct net_device *dev , int lock) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (lock && down_interruptible(&ai->sem))
                return -1;
@@ -2728,27 +2751,30 @@ static void airo_networks_initialize(struct airo_info *ai)
                              &ai->network_free_list);
 }
 
-static int airo_test_wpa_capable(struct airo_info *ai)
-{
-       int status;
-       CapabilityRid cap_rid;
-
-       status = readCapabilityRid(ai, &cap_rid, 1);
-       if (status != SUCCESS) return 0;
+static const struct net_device_ops airo_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = airo_start_xmit,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
 
-       /* Only firmware versions 5.30.17 or better can do WPA */
-       if (le16_to_cpu(cap_rid.softVer) > 0x530
-         || (le16_to_cpu(cap_rid.softVer) == 0x530
-             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
-               airo_print_info("", "WPA is supported.");
-               return 1;
-       }
+static const struct net_device_ops mpi_netdev_ops = {
+       .ndo_open               = airo_open,
+       .ndo_stop               = airo_close,
+       .ndo_start_xmit         = mpi_start_xmit,
+       .ndo_get_stats          = airo_get_stats,
+       .ndo_set_multicast_list = airo_set_multicast_list,
+       .ndo_set_mac_address    = airo_set_mac_address,
+       .ndo_do_ioctl           = airo_ioctl,
+       .ndo_change_mtu         = airo_change_mtu,
+       .ndo_validate_addr      = eth_validate_addr,
+};
 
-       /* No WPA support */
-       airo_print_info("", "WPA unsupported (only firmware versions 5.30.17"
-               " and greater support WPA.  Detected %s)", cap_rid.prodVer);
-       return 0;
-}
 
 static struct net_device *_init_airo_card( unsigned short irq, int port,
                                           int is_pcmcia, struct pci_dev *pci,
@@ -2757,7 +2783,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        struct net_device *dev;
        struct airo_info *ai;
        int i, rc;
-       DECLARE_MAC_BUF(mac);
+       CapabilityRid cap_rid;
 
        /* Create the network device object. */
        dev = alloc_netdev(sizeof(*ai), "", ether_setup);
@@ -2766,7 +2792,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                return NULL;
        }
 
-       ai = dev->priv;
+       ai = dev->ml_priv = netdev_priv(dev);
        ai->wifidev = NULL;
        ai->flags = 1 << FLAG_RADIO_DOWN;
        ai->jobs = 0;
@@ -2787,22 +2813,16 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                goto err_out_free;
        airo_networks_initialize (ai);
 
+       skb_queue_head_init (&ai->txq);
+
        /* The Airo-specific entries in the device structure. */
-       if (test_bit(FLAG_MPI,&ai->flags)) {
-               skb_queue_head_init (&ai->txq);
-               dev->hard_start_xmit = &mpi_start_xmit;
-       } else
-               dev->hard_start_xmit = &airo_start_xmit;
-       dev->get_stats = &airo_get_stats;
-       dev->set_multicast_list = &airo_set_multicast_list;
-       dev->set_mac_address = &airo_set_mac_address;
-       dev->do_ioctl = &airo_ioctl;
+       if (test_bit(FLAG_MPI,&ai->flags))
+               dev->netdev_ops = &mpi_netdev_ops;
+       else
+               dev->netdev_ops = &airo_netdev_ops;
        dev->wireless_handlers = &airo_handler_def;
        ai->wireless_data.spy_data = &ai->spy_data;
        dev->wireless_data = &ai->wireless_data;
-       dev->change_mtu = &airo_change_mtu;
-       dev->open = &airo_open;
-       dev->stop = &airo_close;
        dev->irq = irq;
        dev->base_addr = port;
 
@@ -2827,7 +2847,7 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
        }
 
        if (probe) {
-               if ( setup_card( ai, dev->dev_addr, 1 ) != SUCCESS ) {
+               if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) {
                        airo_print_err(dev->name, "MAC could not be enabled" );
                        rc = -EIO;
                        goto err_out_map;
@@ -2837,38 +2857,59 @@ static struct net_device *_init_airo_card( unsigned short irq, int port,
                set_bit(FLAG_FLASHING, &ai->flags);
        }
 
+       strcpy(dev->name, "eth%d");
+       rc = register_netdev(dev);
+       if (rc) {
+               airo_print_err(dev->name, "Couldn't register_netdev");
+               goto err_out_map;
+       }
+       ai->wifidev = init_wifidev(ai, dev);
+       if (!ai->wifidev)
+               goto err_out_reg;
+
+       rc = readCapabilityRid(ai, &cap_rid, 1);
+       if (rc != SUCCESS) {
+               rc = -EIO;
+               goto err_out_wifi;
+       }
+       /* WEP capability discovery */
+       ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0;
+       ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0;
+
+       airo_print_info(dev->name, "Firmware version %x.%x.%02x",
+                       ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF),
+                       (le16_to_cpu(cap_rid.softVer) & 0xFF),
+                       le16_to_cpu(cap_rid.softSubVer));
+
        /* Test for WPA support */
-       if (airo_test_wpa_capable(ai)) {
+       /* Only firmware versions 5.30.17 or better can do WPA */
+       if (le16_to_cpu(cap_rid.softVer) > 0x530
+        || (le16_to_cpu(cap_rid.softVer) == 0x530
+             && le16_to_cpu(cap_rid.softSubVer) >= 17)) {
+               airo_print_info(ai->dev->name, "WPA supported.");
+
                set_bit(FLAG_WPA_CAPABLE, &ai->flags);
                ai->bssListFirst = RID_WPA_BSSLISTFIRST;
                ai->bssListNext = RID_WPA_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid);
        } else {
+               airo_print_info(ai->dev->name, "WPA unsupported with firmware "
+                       "versions older than 5.30.17.");
+
                ai->bssListFirst = RID_BSSLISTFIRST;
                ai->bssListNext = RID_BSSLISTNEXT;
                ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra);
        }
 
-       strcpy(dev->name, "eth%d");
-       rc = register_netdev(dev);
-       if (rc) {
-               airo_print_err(dev->name, "Couldn't register_netdev");
-               goto err_out_map;
-       }
-       ai->wifidev = init_wifidev(ai, dev);
-       if (!ai->wifidev)
-               goto err_out_reg;
-
        set_bit(FLAG_REGISTERED,&ai->flags);
-       airo_print_info(dev->name, "MAC enabled %s",
-                       print_mac(mac, dev->dev_addr));
+       airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
 
        /* 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,AIRO_DEF_MTU,i>=MAX_FIDS/2);
 
-       if (setup_proc_entry(dev, dev->priv) < 0)
+       if (setup_proc_entry(dev, dev->ml_priv) < 0)
                goto err_out_wifi;
 
        return dev;
@@ -2917,8 +2958,7 @@ static int waitbusy (struct airo_info *ai) {
 int reset_airo_card( struct net_device *dev )
 {
        int i;
-       struct airo_info *ai = dev->priv;
-       DECLARE_MAC_BUF(mac);
+       struct airo_info *ai = dev->ml_priv;
 
        if (reset_card (dev, 1))
                return -1;
@@ -2927,8 +2967,7 @@ int reset_airo_card( struct net_device *dev )
                airo_print_err(dev->name, "MAC could not be enabled");
                return -1;
        }
-       airo_print_info(dev->name, "MAC enabled %s",
-                       print_mac(mac, dev->dev_addr));
+       airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr);
        /* Allocate the transmit buffers if needed */
        if (!test_bit(FLAG_MPI,&ai->flags))
                for( i = 0; i < MAX_FIDS; i++ )
@@ -2942,7 +2981,7 @@ int reset_airo_card( struct net_device *dev )
 EXPORT_SYMBOL(reset_airo_card);
 
 static void airo_send_event(struct net_device *dev) {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        union iwreq_data wrqu;
        StatusRid status_rid;
 
@@ -3019,7 +3058,7 @@ out:
 
 static int airo_thread(void *data) {
        struct net_device *dev = data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int locked;
 
        set_freezable();
@@ -3129,315 +3168,354 @@ static int header_len(__le16 ctl)
        return 24;
 }
 
-static irqreturn_t airo_interrupt(int irq, void *dev_id)
+static void airo_handle_cisco_mic(struct airo_info *ai)
 {
-       struct net_device *dev = dev_id;
+       if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) {
+               set_bit(JOB_MIC, &ai->jobs);
+               wake_up_interruptible(&ai->thr_wait);
+       }
+}
+
+/* Airo Status codes */
+#define STAT_NOBEACON  0x8000 /* Loss of sync - missed beacons */
+#define STAT_MAXRETRIES        0x8001 /* Loss of sync - max retries */
+#define STAT_MAXARL    0x8002 /* Loss of sync - average retry level exceeded*/
+#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */
+#define STAT_TSFSYNC   0x8004 /* Loss of sync - TSF synchronization */
+#define STAT_DEAUTH    0x8100 /* low byte is 802.11 reason code */
+#define STAT_DISASSOC  0x8200 /* low byte is 802.11 reason code */
+#define STAT_ASSOC_FAIL        0x8400 /* low byte is 802.11 reason code */
+#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */
+#define STAT_ASSOC     0x0400 /* Associated */
+#define STAT_REASSOC    0x0600 /* Reassociated?  Only on firmware >= 5.30.17 */
+
+static void airo_print_status(const char *devname, u16 status)
+{
+       u8 reason = status & 0xFF;
+
+       switch (status) {
+       case STAT_NOBEACON:
+               airo_print_dbg(devname, "link lost (missed beacons)");
+               break;
+       case STAT_MAXRETRIES:
+       case STAT_MAXARL:
+               airo_print_dbg(devname, "link lost (max retries)");
+               break;
+       case STAT_FORCELOSS:
+               airo_print_dbg(devname, "link lost (local choice)");
+               break;
+       case STAT_TSFSYNC:
+               airo_print_dbg(devname, "link lost (TSF sync lost)");
+               break;
+       case STAT_DEAUTH:
+               airo_print_dbg(devname, "deauthenticated (reason: %d)", reason);
+               break;
+       case STAT_DISASSOC:
+               airo_print_dbg(devname, "disassociated (reason: %d)", reason);
+               break;
+       case STAT_ASSOC_FAIL:
+               airo_print_dbg(devname, "association failed (reason: %d)",
+                              reason);
+               break;
+       case STAT_AUTH_FAIL:
+               airo_print_dbg(devname, "authentication failed (reason: %d)",
+                              reason);
+               break;
+       default:
+               break;
+       }
+}
+
+static void airo_handle_link(struct airo_info *ai)
+{
+       union iwreq_data wrqu;
+       int scan_forceloss = 0;
        u16 status;
-       u16 fid;
-       struct airo_info *apriv = dev->priv;
-       u16 savedInterrupts = 0;
-       int handled = 0;
 
-       if (!netif_device_present(dev))
-               return IRQ_NONE;
+       /* Get new status and acknowledge the link change */
+       status = le16_to_cpu(IN4500(ai, LINKSTAT));
+       OUT4500(ai, EVACK, EV_LINK);
 
-       for (;;) {
-               status = IN4500( apriv, EVSTAT );
-               if ( !(status & STATUS_INTS) || status == 0xffff ) break;
+       if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0))
+               scan_forceloss = 1;
 
-               handled = 1;
+       airo_print_status(ai->dev->name, status);
 
-               if ( status & EV_AWAKE ) {
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-                       OUT4500( apriv, EVACK, EV_AWAKE );
-               }
+       if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) {
+               if (auto_wep)
+                       ai->expires = 0;
+               if (ai->list_bss_task)
+                       wake_up_process(ai->list_bss_task);
+               set_bit(FLAG_UPDATE_UNI, &ai->flags);
+               set_bit(FLAG_UPDATE_MULTI, &ai->flags);
 
-               if (!savedInterrupts) {
-                       savedInterrupts = IN4500( apriv, EVINTEN );
-                       OUT4500( apriv, EVINTEN, 0 );
+               if (down_trylock(&ai->sem) != 0) {
+                       set_bit(JOB_EVENT, &ai->jobs);
+                       wake_up_interruptible(&ai->thr_wait);
+               } else
+                       airo_send_event(ai->dev);
+       } else if (!scan_forceloss) {
+               if (auto_wep && !ai->expires) {
+                       ai->expires = RUN_AT(3*HZ);
+                       wake_up_interruptible(&ai->thr_wait);
                }
 
-               if ( status & EV_MIC ) {
-                       OUT4500( apriv, EVACK, EV_MIC );
-                       if (test_bit(FLAG_MIC_CAPABLE, &apriv->flags)) {
-                               set_bit(JOB_MIC, &apriv->jobs);
-                               wake_up_interruptible(&apriv->thr_wait);
-                       }
-               }
-               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!)
-                       */
-                       u16 newStatus = IN4500(apriv, LINKSTAT);
-                       OUT4500( apriv, EVACK, EV_LINK);
-                       /* Here is what newStatus means: */
-#define NOBEACON 0x8000 /* Loss of sync - missed beacons */
-#define MAXRETRIES 0x8001 /* Loss of sync - max retries */
-#define MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/
-#define FORCELOSS 0x8003 /* Loss of sync - host request */
-#define TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */
-#define DEAUTH 0x8100 /* Deauthentication (low byte is reason code) */
-#define DISASS 0x8200 /* Disassociation (low byte is reason code) */
-#define ASSFAIL 0x8400 /* Association failure (low byte is reason
-                         code) */
-#define AUTHFAIL 0x0300 /* Authentication failure (low byte is reason
-                          code) */
-#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 */
-#define RC_DEAUTH 3 /* Deauthenticated because sending station is
-                      leaving */
-#define RC_NOACT 4 /* Disassociated due to inactivity */
-#define RC_MAXLOAD 5 /* Disassociated because AP is unable to handle
-                       all currently associated stations */
-#define RC_BADCLASS2 6 /* Class 2 frame received from
-                         non-Authenticated station */
-#define RC_BADCLASS3 7 /* Class 3 frame received from
-                         non-Associated station */
-#define RC_STATLEAVE 8 /* Disassociated because sending station is
-                         leaving BSS */
-#define RC_NOAUTH 9 /* Station requesting (Re)Association is not
-                      Authenticated with the responding station */
-                       if (newStatus == FORCELOSS && apriv->scan_timeout > 0)
-                               scan_forceloss = 1;
-                       if(newStatus == ASSOCIATED || newStatus == REASSOCIATED) {
-                               if (auto_wep)
-                                       apriv->expires = 0;
-                               if (apriv->list_bss_task)
-                                       wake_up_process(apriv->list_bss_task);
-                               set_bit(FLAG_UPDATE_UNI, &apriv->flags);
-                               set_bit(FLAG_UPDATE_MULTI, &apriv->flags);
-
-                               if (down_trylock(&apriv->sem) != 0) {
-                                       set_bit(JOB_EVENT, &apriv->jobs);
-                                       wake_up_interruptible(&apriv->thr_wait);
-                               } else
-                                       airo_send_event(dev);
-                       } 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(ai->dev, SIOCGIWAP, &wrqu, NULL);
+       }
+}
 
-                               /* 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);
-                       }
-               }
+static void airo_handle_rx(struct airo_info *ai)
+{
+       struct sk_buff *skb = NULL;
+       __le16 fc, v, *buffer, tmpbuf[4];
+       u16 len, hdrlen = 0, gap, fid;
+       struct rx_hdr hdr;
+       int success = 0;
 
-               /* Check to see if there is something to receive */
-               if ( status & EV_RX  ) {
-                       struct sk_buff *skb = NULL;
-                       __le16 fc, v;
-                       u16 len, hdrlen = 0;
-#pragma pack(1)
-                       struct {
-                               __le16 status, len;
-                               u8 rssi[2];
-                               u8 rate;
-                               u8 freq;
-                               __le16 tmp[4];
-                       } hdr;
-#pragma pack()
-                       u16 gap;
-                       __le16 tmpbuf[4];
-                       __le16 *buffer;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               if (test_bit(FLAG_802_11, &apriv->flags))
-                                       mpi_receive_802_11(apriv);
-                               else
-                                       mpi_receive_802_3(apriv);
-                               OUT4500(apriv, EVACK, EV_RX);
-                               goto exitrx;
-                       }
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               if (test_bit(FLAG_802_11, &ai->flags))
+                       mpi_receive_802_11(ai);
+               else
+                       mpi_receive_802_3(ai);
+               OUT4500(ai, EVACK, EV_RX);
+               return;
+       }
 
-                       fid = IN4500( apriv, RXFID );
-
-                       /* Get the packet length */
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_setup (apriv, fid, 4, BAP0);
-                               bap_read (apriv, (__le16*)&hdr, sizeof(hdr), BAP0);
-                               /* Bad CRC. Ignore packet */
-                               if (le16_to_cpu(hdr.status) & 2)
-                                       hdr.len = 0;
-                               if (apriv->wifidev == NULL)
-                                       hdr.len = 0;
-                       } else {
-                               bap_setup (apriv, fid, 0x36, BAP0);
-                               bap_read (apriv, &hdr.len, 2, BAP0);
-                       }
-                       len = le16_to_cpu(hdr.len);
+       fid = IN4500(ai, RXFID);
 
-                       if (len > AIRO_DEF_MTU) {
-                               airo_print_err(apriv->dev->name, "Bad size %d", len);
-                               goto badrx;
-                       }
-                       if (len == 0)
-                               goto badrx;
+       /* Get the packet length */
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_setup (ai, fid, 4, BAP0);
+               bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0);
+               /* Bad CRC. Ignore packet */
+               if (le16_to_cpu(hdr.status) & 2)
+                       hdr.len = 0;
+               if (ai->wifidev == NULL)
+                       hdr.len = 0;
+       } else {
+               bap_setup(ai, fid, 0x36, BAP0);
+               bap_read(ai, &hdr.len, 2, BAP0);
+       }
+       len = le16_to_cpu(hdr.len);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               bap_read (apriv, &fc, sizeof(fc), BAP0);
-                               hdrlen = header_len(fc);
-                       } else
-                               hdrlen = ETH_ALEN * 2;
+       if (len > AIRO_DEF_MTU) {
+               airo_print_err(ai->dev->name, "Bad size %d", len);
+               goto done;
+       }
+       if (len == 0)
+               goto done;
 
-                       skb = dev_alloc_skb( len + hdrlen + 2 + 2 );
-                       if ( !skb ) {
-                               dev->stats.rx_dropped++;
-                               goto badrx;
-                       }
-                       skb_reserve(skb, 2); /* This way the IP header is aligned */
-                       buffer = (__le16*)skb_put (skb, len + hdrlen);
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               buffer[0] = fc;
-                               bap_read (apriv, buffer + 1, hdrlen - 2, BAP0);
-                               if (hdrlen == 24)
-                                       bap_read (apriv, tmpbuf, 6, BAP0);
-
-                               bap_read (apriv, &v, sizeof(v), BAP0);
-                               gap = le16_to_cpu(v);
-                               if (gap) {
-                                       if (gap <= 8) {
-                                               bap_read (apriv, tmpbuf, gap, BAP0);
-                                       } else {
-                                               airo_print_err(apriv->dev->name, "gaplen too "
-                                                       "big. Problems will follow...");
-                                       }
-                               }
-                               bap_read (apriv, buffer + hdrlen/2, len, BAP0);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               bap_read(ai, &fc, sizeof (fc), BAP0);
+               hdrlen = header_len(fc);
+       } else
+               hdrlen = ETH_ALEN * 2;
+
+       skb = dev_alloc_skb(len + hdrlen + 2 + 2);
+       if (!skb) {
+               ai->dev->stats.rx_dropped++;
+               goto done;
+       }
+
+       skb_reserve(skb, 2); /* This way the IP header is aligned */
+       buffer = (__le16 *) skb_put(skb, len + hdrlen);
+       if (test_bit(FLAG_802_11, &ai->flags)) {
+               buffer[0] = fc;
+               bap_read(ai, buffer + 1, hdrlen - 2, BAP0);
+               if (hdrlen == 24)
+                       bap_read(ai, tmpbuf, 6, BAP0);
+
+               bap_read(ai, &v, sizeof(v), BAP0);
+               gap = le16_to_cpu(v);
+               if (gap) {
+                       if (gap <= 8) {
+                               bap_read(ai, tmpbuf, gap, BAP0);
                        } else {
-                               MICBuffer micbuf;
-                               bap_read (apriv, buffer, ETH_ALEN*2, BAP0);
-                               if (apriv->micstats.enabled) {
-                                       bap_read (apriv,(__le16*)&micbuf,sizeof(micbuf),BAP0);
-                                       if (ntohs(micbuf.typelen) > 0x05DC)
-                                               bap_setup (apriv, fid, 0x44, BAP0);
-                                       else {
-                                               if (len <= sizeof(micbuf))
-                                                       goto badmic;
-
-                                               len -= sizeof(micbuf);
-                                               skb_trim (skb, len + hdrlen);
-                                       }
-                               }
-                               bap_read(apriv,buffer+ETH_ALEN,len,BAP0);
-                               if (decapsulate(apriv,&micbuf,(etherHead*)buffer,len)) {
-badmic:
-                                       dev_kfree_skb_irq (skb);
-badrx:
-                                       OUT4500( apriv, EVACK, EV_RX);
-                                       goto exitrx;
+                               airo_print_err(ai->dev->name, "gaplen too "
+                                       "big. Problems will follow...");
+                       }
+               }
+               bap_read(ai, buffer + hdrlen/2, len, BAP0);
+       } else {
+               MICBuffer micbuf;
+
+               bap_read(ai, buffer, ETH_ALEN * 2, BAP0);
+               if (ai->micstats.enabled) {
+                       bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0);
+                       if (ntohs(micbuf.typelen) > 0x05DC)
+                               bap_setup(ai, fid, 0x44, BAP0);
+                       else {
+                               if (len <= sizeof (micbuf)) {
+                                       dev_kfree_skb_irq(skb);
+                                       goto done;
                                }
+
+                               len -= sizeof(micbuf);
+                               skb_trim(skb, len + hdrlen);
                        }
+               }
+
+               bap_read(ai, buffer + ETH_ALEN, len, BAP0);
+               if (decapsulate(ai, &micbuf, (etherHead*) buffer, len))
+                       dev_kfree_skb_irq (skb);
+               else
+                       success = 1;
+       }
+
 #ifdef WIRELESS_SPY
-                       if (apriv->spy_data.spy_number > 0) {
-                               char *sa;
-                               struct iw_quality wstats;
-                               /* Prepare spy data : addr + qual */
-                               if (!test_bit(FLAG_802_11, &apriv->flags)) {
-                                       sa = (char*)buffer + 6;
-                                       bap_setup (apriv, fid, 8, BAP0);
-                                       bap_read (apriv, (__le16*)hdr.rssi, 2, BAP0);
-                               } else
-                                       sa = (char*)buffer + 10;
-                               wstats.qual = hdr.rssi[0];
-                               if (apriv->rssi)
-                                       wstats.level = 0x100 - apriv->rssi[hdr.rssi[1]].rssidBm;
-                               else
-                                       wstats.level = (hdr.rssi[1] + 321) / 2;
-                               wstats.noise = apriv->wstats.qual.noise;
-                               wstats.updated = IW_QUAL_LEVEL_UPDATED
-                                       | IW_QUAL_QUAL_UPDATED
-                                       | IW_QUAL_DBM;
-                               /* Update spy records */
-                               wireless_spy_update(dev, sa, &wstats);
-                       }
+       if (success && (ai->spy_data.spy_number > 0)) {
+               char *sa;
+               struct iw_quality wstats;
+
+               /* Prepare spy data : addr + qual */
+               if (!test_bit(FLAG_802_11, &ai->flags)) {
+                       sa = (char *) buffer + 6;
+                       bap_setup(ai, fid, 8, BAP0);
+                       bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0);
+               } else
+                       sa = (char *) buffer + 10;
+               wstats.qual = hdr.rssi[0];
+               if (ai->rssi)
+                       wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm;
+               else
+                       wstats.level = (hdr.rssi[1] + 321) / 2;
+               wstats.noise = ai->wstats.qual.noise;
+               wstats.updated =  IW_QUAL_LEVEL_UPDATED
+                               | IW_QUAL_QUAL_UPDATED
+                               | IW_QUAL_DBM;
+               /* Update spy records */
+               wireless_spy_update(ai->dev, sa, &wstats);
+       }
 #endif /* WIRELESS_SPY */
-                       OUT4500( apriv, EVACK, EV_RX);
 
-                       if (test_bit(FLAG_802_11, &apriv->flags)) {
-                               skb_reset_mac_header(skb);
-                               skb->pkt_type = PACKET_OTHERHOST;
-                               skb->dev = apriv->wifidev;
-                               skb->protocol = htons(ETH_P_802_2);
-                       } else
-                               skb->protocol = eth_type_trans(skb,dev);
-                       skb->dev->last_rx = jiffies;
-                       skb->ip_summed = CHECKSUM_NONE;
+done:
+       OUT4500(ai, EVACK, EV_RX);
+
+       if (success) {
+               if (test_bit(FLAG_802_11, &ai->flags)) {
+                       skb_reset_mac_header(skb);
+                       skb->pkt_type = PACKET_OTHERHOST;
+                       skb->dev = ai->wifidev;
+                       skb->protocol = htons(ETH_P_802_2);
+               } else
+                       skb->protocol = eth_type_trans(skb, ai->dev);
+               skb->ip_summed = CHECKSUM_NONE;
+
+               netif_rx(skb);
+       }
+}
+
+static void airo_handle_tx(struct airo_info *ai, u16 status)
+{
+       int i, len = 0, index = -1;
+       u16 fid;
+
+       if (test_bit(FLAG_MPI, &ai->flags)) {
+               unsigned long flags;
+
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, -1);
 
-                       netif_rx( skb );
+               spin_lock_irqsave(&ai->aux_lock, flags);
+               if (!skb_queue_empty(&ai->txq)) {
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       mpi_send_packet(ai->dev);
+               } else {
+                       clear_bit(FLAG_PENDING_XMIT, &ai->flags);
+                       spin_unlock_irqrestore(&ai->aux_lock,flags);
+                       netif_wake_queue(ai->dev);
                }
-exitrx:
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               return;
+       }
 
-               /* Check to see if a packet has been transmitted */
-               if (  status & ( EV_TX|EV_TXCPY|EV_TXEXC ) ) {
-                       int i;
-                       int len = 0;
-                       int index = -1;
-
-                       if (test_bit(FLAG_MPI,&apriv->flags)) {
-                               unsigned long flags;
-
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, -1);
-                               spin_lock_irqsave(&apriv->aux_lock, flags);
-                               if (!skb_queue_empty(&apriv->txq)) {
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       mpi_send_packet (dev);
-                               } else {
-                                       clear_bit(FLAG_PENDING_XMIT, &apriv->flags);
-                                       spin_unlock_irqrestore(&apriv->aux_lock,flags);
-                                       netif_wake_queue (dev);
-                               }
-                               OUT4500( apriv, EVACK,
-                                       status & (EV_TX|EV_TXCPY|EV_TXEXC));
-                               goto exittx;
-                       }
+       fid = IN4500(ai, TXCOMPLFID);
 
-                       fid = IN4500(apriv, TXCOMPLFID);
+       for(i = 0; i < MAX_FIDS; i++) {
+               if ((ai->fids[i] & 0xffff) == fid) {
+                       len = ai->fids[i] >> 16;
+                       index = i;
+               }
+       }
 
-                       for( i = 0; i < MAX_FIDS; i++ ) {
-                               if ( ( apriv->fids[i] & 0xffff ) == fid ) {
-                                       len = apriv->fids[i] >> 16;
-                                       index = i;
-                               }
-                       }
-                       if (index != -1) {
-                               if (status & EV_TXEXC)
-                                       get_tx_error(apriv, index);
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXEXC));
-                               /* Set up to be used again */
-                               apriv->fids[index] &= 0xffff;
-                               if (index < MAX_FIDS / 2) {
-                                       if (!test_bit(FLAG_PENDING_XMIT, &apriv->flags))
-                                               netif_wake_queue(dev);
-                               } else {
-                                       if (!test_bit(FLAG_PENDING_XMIT11, &apriv->flags))
-                                               netif_wake_queue(apriv->wifidev);
-                               }
-                       } else {
-                               OUT4500( apriv, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
-                               airo_print_err(apriv->dev->name, "Unallocated FID was "
-                                       "used to xmit" );
-                       }
+       if (index != -1) {
+               if (status & EV_TXEXC)
+                       get_tx_error(ai, index);
+
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC));
+
+               /* Set up to be used again */
+               ai->fids[index] &= 0xffff;
+               if (index < MAX_FIDS / 2) {
+                       if (!test_bit(FLAG_PENDING_XMIT, &ai->flags))
+                               netif_wake_queue(ai->dev);
+               } else {
+                       if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags))
+                               netif_wake_queue(ai->wifidev);
+               }
+       } else {
+               OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC));
+               airo_print_err(ai->dev->name, "Unallocated FID was used to xmit");
+       }
+}
+
+static irqreturn_t airo_interrupt(int irq, void *dev_id)
+{
+       struct net_device *dev = dev_id;
+       u16 status, savedInterrupts = 0;
+       struct airo_info *ai = dev->ml_priv;
+       int handled = 0;
+
+       if (!netif_device_present(dev))
+               return IRQ_NONE;
+
+       for (;;) {
+               status = IN4500(ai, EVSTAT);
+               if (!(status & STATUS_INTS) || (status == 0xffff))
+                       break;
+
+               handled = 1;
+
+               if (status & EV_AWAKE) {
+                       OUT4500(ai, EVACK, EV_AWAKE);
+                       OUT4500(ai, EVACK, EV_AWAKE);
                }
-exittx:
-               if ( status & ~STATUS_INTS & ~IGNORE_INTS )
-                       airo_print_warn(apriv->dev->name, "Got weird status %x",
+
+               if (!savedInterrupts) {
+                       savedInterrupts = IN4500(ai, EVINTEN);
+                       OUT4500(ai, EVINTEN, 0);
+               }
+
+               if (status & EV_MIC) {
+                       OUT4500(ai, EVACK, EV_MIC);
+                       airo_handle_cisco_mic(ai);
+               }
+
+               if (status & EV_LINK) {
+                       /* Link status changed */
+                       airo_handle_link(ai);
+               }
+
+               /* Check to see if there is something to receive */
+               if (status & EV_RX)
+                       airo_handle_rx(ai);
+
+               /* Check to see if a packet has been transmitted */
+               if (status & (EV_TX | EV_TXCPY | EV_TXEXC))
+                       airo_handle_tx(ai, status);
+
+               if ( status & ~STATUS_INTS & ~IGNORE_INTS ) {
+                       airo_print_warn(ai->dev->name, "Got weird status %x",
                                status & ~STATUS_INTS & ~IGNORE_INTS );
+               }
        }
 
        if (savedInterrupts)
-               OUT4500( apriv, EVINTEN, savedInterrupts );
+               OUT4500(ai, EVINTEN, savedInterrupts);
 
-       /* done.. */
        return IRQ_RETVAL(handled);
 }
 
@@ -3599,7 +3677,6 @@ badmic:
 
                skb->ip_summed = CHECKSUM_NONE;
                skb->protocol = eth_type_trans(skb, ai->dev);
-               skb->dev->last_rx = jiffies;
                netif_rx(skb);
        }
 badrx:
@@ -3611,24 +3688,16 @@ badrx:
        }
 }
 
-void mpi_receive_802_11 (struct airo_info *ai)
+static void mpi_receive_802_11(struct airo_info *ai)
 {
        RxFid rxd;
        struct sk_buff *skb = NULL;
        u16 len, hdrlen = 0;
        __le16 fc;
-#pragma pack(1)
-       struct {
-               __le16 status, len;
-               u8 rssi[2];
-               u8 rate;
-               u8 freq;
-               __le16 tmp[4];
-       } hdr;
-#pragma pack()
+       struct rx_hdr hdr;
        u16 gap;
        u16 *buffer;
-       char *ptr = ai->rxfids[0].virtual_host_addr+4;
+       char *ptr = ai->rxfids[0].virtual_host_addr + 4;
 
        memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd));
        memcpy ((char *)&hdr, ptr, sizeof(hdr));
@@ -3693,9 +3762,9 @@ void mpi_receive_802_11 (struct airo_info *ai)
        skb->pkt_type = PACKET_OTHERHOST;
        skb->dev = ai->wifidev;
        skb->protocol = htons(ETH_P_802_2);
-       skb->dev->last_rx = jiffies;
        skb->ip_summed = CHECKSUM_NONE;
        netif_rx( skb );
+
 badrx:
        if (rxd.valid == 0) {
                rxd.valid = 1;
@@ -3710,7 +3779,6 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
        Cmd cmd;
        Resp rsp;
        int status;
-       int i;
        SsidRid mySsid;
        __le16 lastindex;
        WepKeyRid wkr;
@@ -3752,6 +3820,7 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
        if (lock)
                up(&ai->sem);
        if (ai->config.len == 0) {
+               int i;
                tdsRssiRid rssi_rid;
                CapabilityRid cap_rid;
 
@@ -3799,14 +3868,12 @@ static u16 setup_card(struct airo_info *ai, u8 *mac, int lock)
                /* Check to see if there are any insmod configured
                   rates to add */
                if ( rates[0] ) {
-                       int i = 0;
                        memset(ai->config.rates,0,sizeof(ai->config.rates));
                        for( i = 0; i < 8 && rates[i]; i++ ) {
                                ai->config.rates[i] = rates[i];
                        }
                }
                if ( basic_rate > 0 ) {
-                       int i;
                        for( i = 0; i < 8; i++ ) {
                                if ( ai->config.rates[i] == basic_rate ||
                                     !ai->config.rates ) {
@@ -4127,7 +4194,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                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);
+                               __func__, rid);
                memset(&cmd, 0, sizeof(cmd));
                memset(&rsp, 0, sizeof(rsp));
 
@@ -4142,7 +4209,7 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                        &ai->config_desc.rid_desc, sizeof(Rid));
 
                if (len < 4 || len > 2047) {
-                       airo_print_err(ai->dev->name, "%s: len=%d", __FUNCTION__, len);
+                       airo_print_err(ai->dev->name, "%s: len=%d", __func__, len);
                        rc = -1;
                } else {
                        memcpy((char *)ai->config_desc.virtual_host_addr,
@@ -4151,9 +4218,9 @@ static int PC4500_writerid(struct airo_info *ai, u16 rid,
                        rc = issuecommand(ai, &cmd, &rsp);
                        if ((rc & 0xff00) != 0) {
                                airo_print_err(ai->dev->name, "%s: Write rid Error %d",
-                                               __FUNCTION__, rc);
+                                               __func__, rc);
                                airo_print_err(ai->dev->name, "%s: Cmd=%04x",
-                                               __FUNCTION__, cmd.cmd);
+                                               __func__, cmd.cmd);
                        }
 
                        if ((rsp.status & 0x7f00))
@@ -4433,7 +4500,6 @@ static int setup_proc_entry( struct net_device *dev,
                goto fail;
        apriv->proc_entry->uid = proc_uid;
        apriv->proc_entry->gid = proc_gid;
-       apriv->proc_entry->owner = THIS_MODULE;
 
        /* Setup the StatsDelta */
        entry = proc_create_data("StatsDelta",
@@ -4604,7 +4670,7 @@ static int proc_status_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
        CapabilityRid cap_rid;
        StatusRid status_rid;
        u16 mode;
@@ -4687,11 +4753,11 @@ static int proc_stats_rid_open( struct inode *inode,
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
        StatsRid stats;
        int i, j;
        __le32 *vals = stats.vals;
-       int len = le16_to_cpu(stats.len);
+       int len;
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
@@ -4702,6 +4768,7 @@ static int proc_stats_rid_open( struct inode *inode,
        }
 
        readStatsRid(apriv, &stats, rid, 1);
+       len = le16_to_cpu(stats.len);
 
         j = 0;
        for(i=0; statsLabels[i]!=(char *)-1 && i*4<len; i++) {
@@ -4724,9 +4791,8 @@ static int proc_stats_rid_open( struct inode *inode,
 static int get_dec_u16( char *buffer, int *start, int limit ) {
        u16 value;
        int valid = 0;
-       for( value = 0; buffer[*start] >= '0' &&
-                    buffer[*start] <= '9' &&
-                    *start < limit; (*start)++ ) {
+       for (value = 0; *start < limit && buffer[*start] >= '0' &&
+                       buffer[*start] <= '9'; (*start)++) {
                valid = 1;
                value *= 10;
                value += buffer[*start] - '0';
@@ -4741,7 +4807,7 @@ static int airo_config_commit(struct net_device *dev,
 
 static inline int sniffing_mode(struct airo_info *ai)
 {
-       return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >=
+       return (le16_to_cpu(ai->config.rmode) & le16_to_cpu(RXMODE_MASK)) >=
                le16_to_cpu(RXMODE_RFMON);
 }
 
@@ -4750,7 +4816,7 @@ static void proc_config_on_close(struct inode *inode, struct file *file)
        struct proc_data *data = file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *line;
 
        if ( !data->writelen ) return;
@@ -4962,7 +5028,7 @@ static int proc_config_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        __le16 mode;
 
@@ -5053,7 +5119,7 @@ static void proc_SSID_on_close(struct inode *inode, struct file *file)
        struct proc_data *data = (struct proc_data *)file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        SsidRid SSID_rid;
        int i;
        char *p = data->wbuffer;
@@ -5096,7 +5162,7 @@ static void proc_APList_on_close( struct inode *inode, struct file *file ) {
        struct proc_data *data = (struct proc_data *)file->private_data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        APListRid APList_rid;
        int i;
 
@@ -5136,63 +5202,102 @@ static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data,
        return rc;
 }
 
-/* Returns the length of the key at the index.  If index == 0xffff
- * the index of the transmit key is returned.  If the key doesn't exist,
- * -1 will be returned.
+/* Returns the WEP key at the specified index, or -1 if that key does
+ * not exist.  The buffer is assumed to be at least 16 bytes in length.
  */
-static int get_wep_key(struct airo_info *ai, u16 index) {
+static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen)
+{
        WepKeyRid wkr;
        int rc;
        __le16 lastindex;
 
        rc = readWepKeyRid(ai, &wkr, 1, 1);
-       if (rc == SUCCESS) do {
+       if (rc != SUCCESS)
+               return -1;
+       do {
                lastindex = wkr.kindex;
-               if (wkr.kindex == cpu_to_le16(index)) {
-                       if (index == 0xffff) {
-                               return wkr.mac[0];
-                       }
-                       return le16_to_cpu(wkr.klen);
+               if (le16_to_cpu(wkr.kindex) == index) {
+                       int klen = min_t(int, buflen, le16_to_cpu(wkr.klen));
+                       memcpy(buf, wkr.key, klen);
+                       return klen;
                }
-               readWepKeyRid(ai, &wkr, 0, 1);
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
+       } while (lastindex != wkr.kindex);
+       return -1;
+}
+
+static int get_wep_tx_idx(struct airo_info *ai)
+{
+       WepKeyRid wkr;
+       int rc;
+       __le16 lastindex;
+
+       rc = readWepKeyRid(ai, &wkr, 1, 1);
+       if (rc != SUCCESS)
+               return -1;
+       do {
+               lastindex = wkr.kindex;
+               if (wkr.kindex == cpu_to_le16(0xffff))
+                       return wkr.mac[0];
+               rc = readWepKeyRid(ai, &wkr, 0, 1);
+               if (rc != SUCCESS)
+                       return -1;
        } while (lastindex != wkr.kindex);
        return -1;
 }
 
-static int set_wep_key(struct airo_info *ai, u16 index,
-                      const char *key, u16 keylen, int perm, int lock )
+static int set_wep_key(struct airo_info *ai, u16 index, const char *key,
+                      u16 keylen, int perm, int lock)
 {
        static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
        WepKeyRid wkr;
+       int rc;
+
+       WARN_ON(keylen == 0);
 
        memset(&wkr, 0, sizeof(wkr));
-       if (keylen == 0) {
-// We are selecting which key to use
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(0xffff);
-               wkr.mac[0] = (char)index;
-               if (perm) ai->defindex = (char)index;
-       } else {
-// We are actually setting the key
-               wkr.len = cpu_to_le16(sizeof(wkr));
-               wkr.kindex = cpu_to_le16(index);
-               wkr.klen = cpu_to_le16(keylen);
-               memcpy( wkr.key, key, keylen );
-               memcpy( wkr.mac, macaddr, ETH_ALEN );
-       }
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(index);
+       wkr.klen = cpu_to_le16(keylen);
+       memcpy(wkr.key, key, keylen);
+       memcpy(wkr.mac, macaddr, ETH_ALEN);
 
        if (perm) disable_MAC(ai, lock);
-       writeWepKeyRid(ai, &wkr, perm, lock);
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
        if (perm) enable_MAC(ai, lock);
-       return 0;
+       return rc;
+}
+
+static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock)
+{
+       WepKeyRid wkr;
+       int rc;
+
+       memset(&wkr, 0, sizeof(wkr));
+       wkr.len = cpu_to_le16(sizeof(wkr));
+       wkr.kindex = cpu_to_le16(0xffff);
+       wkr.mac[0] = (char)index;
+
+       if (perm) {
+               ai->defindex = (char)index;
+               disable_MAC(ai, lock);
+       }
+
+       rc = writeWepKeyRid(ai, &wkr, perm, lock);
+
+       if (perm)
+               enable_MAC(ai, lock);
+       return rc;
 }
 
 static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
-       int i;
+       struct airo_info *ai = dev->ml_priv;
+       int i, rc;
        char key[16];
        u16 index = 0;
        int j = 0;
@@ -5206,7 +5311,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
            (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) {
                index = data->wbuffer[0] - '0';
                if (data->wbuffer[1] == '\n') {
-                       set_wep_key(ai, index, NULL, 0, 1, 1);
+                       rc = set_wep_tx_idx(ai, index, 1, 1);
+                       if (rc < 0) {
+                               airo_print_err(ai->dev->name, "failed to set "
+                                              "WEP transmit index to %d: %d.",
+                                              index, rc);
+                       }
                        return;
                }
                j = 2;
@@ -5225,7 +5335,12 @@ static void proc_wepkey_on_close( struct inode *inode, struct file *file ) {
                        break;
                }
        }
-       set_wep_key(ai, index, key, i/3, 1, 1);
+
+       rc = set_wep_key(ai, index, key, i/3, 1, 1);
+       if (rc < 0) {
+               airo_print_err(ai->dev->name, "failed to set WEP key at index "
+                              "%d: %d.", index, rc);
+       }
 }
 
 static int proc_wepkey_open( struct inode *inode, struct file *file )
@@ -5233,7 +5348,7 @@ static int proc_wepkey_open( struct inode *inode, struct file *file )
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *ptr;
        WepKeyRid wkr;
        __le16 lastindex;
@@ -5282,7 +5397,7 @@ static int proc_SSID_open(struct inode *inode, struct file *file)
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        char *ptr;
        SsidRid SSID_rid;
@@ -5326,11 +5441,10 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        int i;
        char *ptr;
        APListRid APList_rid;
-       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
@@ -5354,8 +5468,7 @@ static int proc_APList_open( struct inode *inode, struct file *file ) {
 // We end when we find a zero MAC
                if ( !*(int*)APList_rid.ap[i] &&
                     !*(int*)&APList_rid.ap[i][2]) break;
-               ptr += sprintf(ptr, "%s\n",
-                              print_mac(mac, APList_rid.ap[i]));
+               ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]);
        }
        if (i==0) ptr += sprintf(ptr, "Not using specific APs\n");
 
@@ -5368,13 +5481,12 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
        struct proc_data *data;
        struct proc_dir_entry *dp = PDE(inode);
        struct net_device *dev = dp->data;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        char *ptr;
        BSSListRid BSSList_rid;
        int rc;
        /* If doLoseSync is not 1, we won't do a Lose Sync */
        int doLoseSync = -1;
-       DECLARE_MAC_BUF(mac);
 
        if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL)
                return -ENOMEM;
@@ -5411,8 +5523,8 @@ static int proc_BSSList_open( struct inode *inode, struct file *file ) {
            we have to add a spin lock... */
        rc = readBSSListRid(ai, doLoseSync, &BSSList_rid);
        while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) {
-               ptr += sprintf(ptr, "%s %*s rssi = %d",
-                              print_mac(mac, BSSList_rid.bssid),
+               ptr += sprintf(ptr, "%pM %*s rssi = %d",
+                              BSSList_rid.bssid,
                                (int)BSSList_rid.ssidLen,
                                BSSList_rid.ssid,
                                le16_to_cpu(BSSList_rid.dBm));
@@ -5447,7 +5559,7 @@ static int proc_close( struct inode *inode, struct file *file )
    associated we will check every minute to see if anything has
    changed. */
 static void timer_func( struct net_device *dev ) {
-       struct airo_info *apriv = dev->priv;
+       struct airo_info *apriv = dev->ml_priv;
 
 /* We don't have a link so try changing the authtype */
        readConfigRid(apriv, 0);
@@ -5459,13 +5571,13 @@ static void timer_func( struct net_device *dev ) {
                        break;
                case AUTH_SHAREDKEY:
                        if (apriv->keyindex < auto_wep) {
-                               set_wep_key(apriv, apriv->keyindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->keyindex, 0, 0);
                                apriv->config.authType = AUTH_SHAREDKEY;
                                apriv->keyindex++;
                        } else {
                                /* Drop to ENCRYPT */
                                apriv->keyindex = 0;
-                               set_wep_key(apriv, apriv->defindex, NULL, 0, 0, 0);
+                               set_wep_tx_idx(apriv, apriv->defindex, 0, 0);
                                apriv->config.authType = AUTH_ENCRYPT;
                        }
                        break;
@@ -5518,7 +5630,7 @@ static void __devexit airo_pci_remove(struct pci_dev *pdev)
 static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
 
@@ -5544,13 +5656,14 @@ static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 
        pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
        pci_save_state(pdev);
-       return pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       pci_set_power_state(pdev, pci_choose_state(pdev, state));
+       return 0;
 }
 
 static int airo_pci_resume(struct pci_dev *pdev)
 {
        struct net_device *dev = pci_get_drvdata(pdev);
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        pci_power_t prev_state = pdev->current_state;
 
        pci_set_power_state(pdev, PCI_D0);
@@ -5729,20 +5842,16 @@ static int airo_set_freq(struct net_device *dev,
                         struct iw_freq *fwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rc = -EINPROGRESS;          /* Call commit handler */
 
        /* If setting by frequency, convert to a channel */
-       if((fwrq->e == 1) &&
-          (fwrq->m >= (int) 2.412e8) &&
-          (fwrq->m <= (int) 2.487e8)) {
+       if(fwrq->e == 1) {
                int f = fwrq->m / 100000;
-               int c = 0;
-               while((c < 14) && (f != frequency_list[c]))
-                       c++;
+
                /* Hack to fall through... */
                fwrq->e = 0;
-               fwrq->m = c + 1;
+               fwrq->m = ieee80211_freq_to_dsss_chan(f);
        }
        /* Setting by channel number */
        if((fwrq->m > 1000) || (fwrq->e > 0))
@@ -5774,7 +5883,7 @@ static int airo_get_freq(struct net_device *dev,
                         struct iw_freq *fwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
        int ch;
 
@@ -5786,7 +5895,7 @@ static int airo_get_freq(struct net_device *dev,
 
        ch = le16_to_cpu(status_rid.channel);
        if((ch > 0) && (ch < 15)) {
-               fwrq->m = frequency_list[ch - 1] * 100000;
+               fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000;
                fwrq->e = 1;
        } else {
                fwrq->m = ch;
@@ -5805,27 +5914,26 @@ static int airo_set_essid(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        SsidRid SSID_rid;               /* SSIDs */
 
        /* Reload the list of current SSID */
        readSsidRid(local, &SSID_rid);
 
        /* Check if we asked for `any' */
-       if(dwrq->flags == 0) {
+       if (dwrq->flags == 0) {
                /* Just send an empty SSID list */
                memset(&SSID_rid, 0, sizeof(SSID_rid));
        } else {
-               int     index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+               unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
 
                /* Check the size of the string */
-               if(dwrq->length > IW_ESSID_MAX_SIZE) {
+               if (dwrq->length > IW_ESSID_MAX_SIZE)
                        return -E2BIG ;
-               }
+
                /* Check if index is valid */
-               if((index < 0) || (index >= 4)) {
+               if (index >= ARRAY_SIZE(SSID_rid.ssids))
                        return -EINVAL;
-               }
 
                /* Set the SSID */
                memset(SSID_rid.ssids[index].ssid, 0,
@@ -5851,7 +5959,7 @@ static int airo_get_essid(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -5879,7 +5987,7 @@ static int airo_set_wap(struct net_device *dev,
                        struct sockaddr *awrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
        APListRid APList_rid;
@@ -5916,7 +6024,7 @@ static int airo_get_wap(struct net_device *dev,
                        struct sockaddr *awrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -5937,7 +6045,7 @@ static int airo_set_nick(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        /* Check the size of the string */
        if(dwrq->length > 16) {
@@ -5960,7 +6068,7 @@ static int airo_get_nick(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        strncpy(extra, local->config.nodeName, 16);
@@ -5979,7 +6087,7 @@ static int airo_set_rate(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        CapabilityRid cap_rid;          /* Card capability info */
        u8      brate = 0;
        int     i;
@@ -6049,7 +6157,7 @@ static int airo_get_rate(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        StatusRid status_rid;           /* Card status info */
 
        readStatusRid(local, &status_rid, 1);
@@ -6071,7 +6179,7 @@ static int airo_set_rts(struct net_device *dev,
                        struct iw_param *vwrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rthr = vwrq->value;
 
        if(vwrq->disabled)
@@ -6095,7 +6203,7 @@ static int airo_get_rts(struct net_device *dev,
                        struct iw_param *vwrq,
                        char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.rtsThres);
@@ -6114,7 +6222,7 @@ static int airo_set_frag(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int fthr = vwrq->value;
 
        if(vwrq->disabled)
@@ -6139,7 +6247,7 @@ static int airo_get_frag(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.fragThresh);
@@ -6158,7 +6266,7 @@ static int airo_set_mode(struct net_device *dev,
                         __u32 *uwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int reset = 0;
 
        readConfigRid(local, 1);
@@ -6221,7 +6329,7 @@ static int airo_get_mode(struct net_device *dev,
                         __u32 *uwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        /* If not managed, assume it's ad-hoc */
@@ -6242,11 +6350,9 @@ static int airo_get_mode(struct net_device *dev,
        return 0;
 }
 
-static inline int valid_index(CapabilityRid *p, int index)
+static inline int valid_index(struct airo_info *ai, int index)
 {
-       if (index < 0)
-               return 0;
-       return index < (p->softCap & cpu_to_le16(0x80) ? 4 : 1);
+       return (index >= 0) && (index <= ai->max_wep_idx);
 }
 
 /*------------------------------------------------------------------*/
@@ -6258,17 +6364,14 @@ static int airo_set_encode(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
-       CapabilityRid cap_rid;          /* Card capability info */
-       int perm = ( dwrq->flags & IW_ENCODE_TEMP ? 0 : 1 );
+       struct airo_info *local = dev->ml_priv;
+       int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1);
        __le16 currentAuthType = local->config.authType;
+       int rc = 0;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Basic checking: do we have a key to set ?
@@ -6280,23 +6383,26 @@ static int airo_set_encode(struct net_device *dev,
        if (dwrq->length > 0) {
                wep_key_t key;
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               int current_index = get_wep_key(local, 0xffff);
+               int current_index;
+
                /* Check the size of the key */
                if (dwrq->length > MAX_KEY_SIZE) {
                        return -EINVAL;
                }
+
+               current_index = get_wep_tx_idx(local);
+               if (current_index < 0)
+                       current_index = 0;
+
                /* Check the index (none -> use current) */
-               if (!valid_index(&cap_rid, index))
+               if (!valid_index(local, index))
                        index = current_index;
+
                /* Set the length */
                if (dwrq->length > MIN_KEY_SIZE)
                        key.len = MAX_KEY_SIZE;
                else
-                       if (dwrq->length > 0)
-                               key.len = MIN_KEY_SIZE;
-                       else
-                               /* Disable the key */
-                               key.len = 0;
+                       key.len = MIN_KEY_SIZE;
                /* Check if the key is not marked as invalid */
                if(!(dwrq->flags & IW_ENCODE_NOKEY)) {
                        /* Cleanup */
@@ -6304,7 +6410,13 @@ 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, perm, 1);
+                       rc = set_wep_key(local, index, key.key, key.len, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP key at index %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
                }
                /* WE specify that if a valid key is set, encryption
                 * should be enabled (user may turn it off later)
@@ -6316,12 +6428,19 @@ static int airo_set_encode(struct net_device *dev,
        } else {
                /* Do we want to just set the transmit key index ? */
                int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-               if (valid_index(&cap_rid, index)) {
-                       set_wep_key(local, index, NULL, 0, perm, 1);
-               } else
+               if (valid_index(local, index)) {
+                       rc = set_wep_tx_idx(local, index, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name, "failed to set"
+                                              " WEP transmit index to %d: %d.",
+                                              index, rc);
+                               return rc;
+                       }
+               } else {
                        /* Don't complain if only change the mode */
                        if (!(dwrq->flags & IW_ENCODE_MODE))
                                return -EINVAL;
+               }
        }
        /* Read the flags */
        if(dwrq->flags & IW_ENCODE_DISABLED)
@@ -6345,16 +6464,16 @@ static int airo_get_encode(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
-       CapabilityRid cap_rid;          /* Card capability info */
+       int wep_key_len;
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
+
        /* Check encryption mode */
        switch(local->config.authType)  {
                case AUTH_ENCRYPT:
@@ -6373,14 +6492,22 @@ static int airo_get_encode(struct net_device *dev,
        memset(extra, 0, 16);
 
        /* Which key do we want ? -1 -> tx index */
-       if (!valid_index(&cap_rid, index))
-               index = get_wep_key(local, 0xffff);
+       if (!valid_index(local, index)) {
+               index = get_wep_tx_idx(local);
+               if (index < 0)
+                       index = 0;
+       }
        dwrq->flags |= index + 1;
+
        /* Copy the key to the user buffer */
-       dwrq->length = get_wep_key(local, index);
-       if (dwrq->length > 16) {
-               dwrq->length=0;
+       wep_key_len = get_wep_key(local, index, &buf[0], sizeof(buf));
+       if (wep_key_len < 0) {
+               dwrq->length = 0;
+       } else {
+               dwrq->length = wep_key_len;
+               memcpy(extra, buf, dwrq->length);
        }
+
        return 0;
 }
 
@@ -6393,31 +6520,30 @@ static int airo_set_encodeext(struct net_device *dev,
                            union iwreq_data *wrqu,
                            char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_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 );
        __le16 currentAuthType = local->config.authType;
-       int idx, key_len, alg = ext->alg, set_key = 1;
+       int idx, key_len, alg = ext->alg, set_key = 1, rc;
        wep_key_t key;
 
-       /* Is WEP supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       /* Older firmware doesn't support this...
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       } */
+
        readConfigRid(local, 1);
 
        /* Determine and validate the key index */
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        if (encoding->flags & IW_ENCODE_DISABLED)
                alg = IW_ENCODE_ALG_NONE;
@@ -6426,7 +6552,13 @@ static int airo_set_encodeext(struct net_device *dev,
                /* Only set transmit key index here, actual
                 * key is set below if needed.
                 */
-               set_wep_key(local, idx, NULL, 0, perm, 1);
+               rc = set_wep_tx_idx(local, idx, perm, 1);
+               if (rc < 0) {
+                       airo_print_err(local->dev->name, "failed to set "
+                                      "WEP transmit index to %d: %d.",
+                                      idx, rc);
+                       return rc;
+               }
                set_key = ext->key_len > 0 ? 1 : 0;
        }
 
@@ -6451,8 +6583,23 @@ static int airo_set_encodeext(struct net_device *dev,
                default:
                        return -EINVAL;
                }
-               /* Send the key to the card */
-               set_wep_key(local, idx, key.key, key.len, perm, 1);
+               if (key.len == 0) {
+                       rc = set_wep_tx_idx(local, idx, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name,
+                                              "failed to set WEP transmit index to %d: %d.",
+                                              idx, rc);
+                               return rc;
+                       }
+               } else {
+                       rc = set_wep_key(local, idx, key.key, key.len, perm, 1);
+                       if (rc < 0) {
+                               airo_print_err(local->dev->name,
+                                              "failed to set WEP key at index %d: %d.",
+                                              idx, rc);
+                               return rc;
+                       }
+               }
        }
 
        /* Read the flags */
@@ -6479,17 +6626,15 @@ static int airo_get_encodeext(struct net_device *dev,
                            union iwreq_data *wrqu,
                            char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_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;
+       int idx, max_key_len, wep_key_len;
+       u8 buf[16];
 
-       /* Is it supported ? */
-       readCapabilityRid(local, &cap_rid, 1);
-       if(!(cap_rid.softCap & cpu_to_le16(2))) {
+       if (!local->wep_capable)
                return -EOPNOTSUPP;
-       }
+
        readConfigRid(local, 1);
 
        max_key_len = encoding->length - sizeof(*ext);
@@ -6498,11 +6643,14 @@ static int airo_get_encodeext(struct net_device *dev,
 
        idx = encoding->flags & IW_ENCODE_INDEX;
        if (idx) {
-               if (!valid_index(&cap_rid, idx - 1))
+               if (!valid_index(local, idx - 1))
                        return -EINVAL;
                idx--;
-       } else
-               idx = get_wep_key(local, 0xffff);
+       } else {
+               idx = get_wep_tx_idx(local);
+               if (idx < 0)
+                       idx = 0;
+       }
 
        encoding->flags = idx + 1;
        memset(ext, 0, sizeof(*ext));
@@ -6525,9 +6673,12 @@ static int airo_get_encodeext(struct net_device *dev,
        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;
+       wep_key_len = get_wep_key(local, idx, &buf[0], sizeof(buf));
+       if (wep_key_len < 0) {
+               ext->key_len = 0;
+       } else {
+               ext->key_len = wep_key_len;
+               memcpy(extra, buf, ext->key_len);
        }
 
        return 0;
@@ -6542,7 +6693,7 @@ 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 airo_info *local = dev->ml_priv;
        struct iw_param *param = &wrqu->param;
        __le16 currentAuthType = local->config.authType;
 
@@ -6582,11 +6733,11 @@ static int airo_set_auth(struct net_device *dev,
                                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);
+                       break;
                }
 
        case IW_AUTH_WPA_ENABLED:
@@ -6610,7 +6761,7 @@ 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 airo_info *local = dev->ml_priv;
        struct iw_param *param = &wrqu->param;
        __le16 currentAuthType = local->config.authType;
 
@@ -6659,7 +6810,7 @@ static int airo_set_txpow(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        CapabilityRid cap_rid;          /* Card capability info */
        int i;
        int rc = -EINVAL;
@@ -6676,7 +6827,7 @@ static int airo_set_txpow(struct net_device *dev,
                return -EINVAL;
        }
        clear_bit (FLAG_RADIO_OFF, &local->flags);
-       for (i = 0; cap_rid.txPowerLevels[i] && (i < 8); i++)
+       for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++)
                if (v == cap_rid.txPowerLevels[i]) {
                        readConfigRid(local, 1);
                        local->config.txPower = v;
@@ -6696,7 +6847,7 @@ static int airo_get_txpow(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.txPower);
@@ -6716,7 +6867,7 @@ static int airo_set_retry(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        int rc = -EINVAL;
 
        if(vwrq->disabled) {
@@ -6754,7 +6905,7 @@ static int airo_get_retry(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        vwrq->disabled = 0;      /* Can't be disabled */
 
@@ -6785,7 +6936,7 @@ static int airo_get_range(struct net_device *dev,
                          struct iw_point *dwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct iw_range *range = (struct iw_range *) extra;
        CapabilityRid cap_rid;          /* Card capability info */
        int             i;
@@ -6803,8 +6954,8 @@ static int airo_get_range(struct net_device *dev,
        k = 0;
        for(i = 0; i < 14; i++) {
                range->freq[k].i = i + 1; /* List index */
-               range->freq[k].m = frequency_list[i] * 100000;
-               range->freq[k++].e = 1; /* Values in table in MHz -> * 10^5 * 10 */
+               range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000;
+               range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */
        }
        range->num_frequency = k;
 
@@ -6910,7 +7061,7 @@ static int airo_set_power(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        if (vwrq->disabled) {
@@ -6967,7 +7118,7 @@ static int airo_get_power(struct net_device *dev,
                          struct iw_param *vwrq,
                          char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        __le16 mode;
 
        readConfigRid(local, 1);
@@ -6998,7 +7149,7 @@ static int airo_set_sens(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        local->config.rssiThreshold =
@@ -7017,7 +7168,7 @@ static int airo_get_sens(struct net_device *dev,
                         struct iw_param *vwrq,
                         char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        readConfigRid(local, 1);
        vwrq->value = le16_to_cpu(local->config.rssiThreshold);
@@ -7037,13 +7188,17 @@ static int airo_get_aplist(struct net_device *dev,
                           struct iw_point *dwrq,
                           char *extra)
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
        struct sockaddr *address = (struct sockaddr *) extra;
-       struct iw_quality qual[IW_MAX_AP];
+       struct iw_quality *qual;
        BSSListRid BSSList;
        int i;
        int loseSync = capable(CAP_NET_ADMIN) ? 1: -1;
 
+       qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL);
+       if (!qual)
+               return -ENOMEM;
+
        for (i = 0; i < IW_MAX_AP; i++) {
                u16 dBm;
                if (readBSSListRid(local, loseSync, &BSSList))
@@ -7098,6 +7253,7 @@ static int airo_get_aplist(struct net_device *dev,
        }
        dwrq->length = i;
 
+       kfree(qual);
        return 0;
 }
 
@@ -7107,10 +7263,10 @@ static int airo_get_aplist(struct net_device *dev,
  */
 static int airo_set_scan(struct net_device *dev,
                         struct iw_request_info *info,
-                        struct iw_param *vwrq,
+                        struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        Cmd cmd;
        Resp rsp;
        int wake = 0;
@@ -7156,7 +7312,7 @@ static inline char *airo_translate_scan(struct net_device *dev,
                                        char *end_buf,
                                        BSSListRid *bss)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        struct iw_event         iwe;            /* Temporary buffer */
        __le16                  capabilities;
        char *                  current_val;    /* For rates */
@@ -7197,10 +7353,7 @@ 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 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.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000;
        iwe.u.freq.e = 1;
        current_ev = iwe_stream_add_event(info, current_ev, end_buf,
                                          &iwe, IW_EV_FREQ_LEN);
@@ -7274,56 +7427,53 @@ static inline char *airo_translate_scan(struct net_device *dev,
        if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) {
                unsigned int num_null_ies = 0;
                u16 length = sizeof (bss->extra.iep);
-               struct ieee80211_info_element *info_element =
-                       (struct ieee80211_info_element *) &bss->extra.iep;
+               u8 *ie = (void *)&bss->extra.iep;
 
-               while ((length >= sizeof(*info_element)) && (num_null_ies < 2)) {
-                       if (sizeof(*info_element) + info_element->len > length) {
+               while ((length >= 2) && (num_null_ies < 2)) {
+                       if (2 + ie[1] > length) {
                                /* Invalid element, don't continue parsing IE */
                                break;
                        }
 
-                       switch (info_element->id) {
-                       case MFIE_TYPE_SSID:
+                       switch (ie[0]) {
+                       case WLAN_EID_SSID:
                                /* Two zero-length SSID elements
                                 * mean we're done parsing elements */
-                               if (!info_element->len)
+                               if (!ie[1])
                                        num_null_ies++;
                                break;
 
-                       case MFIE_TYPE_GENERIC:
-                               if (info_element->len >= 4 &&
-                                   info_element->data[0] == 0x00 &&
-                                   info_element->data[1] == 0x50 &&
-                                   info_element->data[2] == 0xf2 &&
-                                   info_element->data[3] == 0x01) {
+                       case WLAN_EID_GENERIC:
+                               if (ie[1] >= 4 &&
+                                   ie[2] == 0x00 &&
+                                   ie[3] == 0x50 &&
+                                   ie[4] == 0xf2 &&
+                                   ie[5] == 0x01) {
                                        iwe.cmd = IWEVGENIE;
-                                       iwe.u.data.length = min(info_element->len + 2,
-                                                                 MAX_WPA_IE_LEN);
+                                       /* 64 is an arbitrary cut-off */
+                                       iwe.u.data.length = min(ie[1] + 2,
+                                                               64);
                                        current_ev = iwe_stream_add_point(
                                                        info, current_ev,
-                                                       end_buf, &iwe,
-                                                       (char *) info_element);
+                                                       end_buf, &iwe, ie);
                                }
                                break;
 
-                       case MFIE_TYPE_RSN:
+                       case WLAN_EID_RSN:
                                iwe.cmd = IWEVGENIE;
-                               iwe.u.data.length = min(info_element->len + 2,
-                                                         MAX_WPA_IE_LEN);
+                               /* 64 is an arbitrary cut-off */
+                               iwe.u.data.length = min(ie[1] + 2, 64);
                                current_ev = iwe_stream_add_point(
                                        info, current_ev, end_buf,
-                                       &iwe, (char *) info_element);
+                                       &iwe, ie);
                                break;
 
                        default:
                                break;
                        }
 
-                       length -= sizeof(*info_element) + info_element->len;
-                       info_element =
-                           (struct ieee80211_info_element *)&info_element->
-                           data[info_element->len];
+                       length -= 2 + ie[1];
+                       ie += 2 + ie[1];
                }
        }
        return current_ev;
@@ -7338,7 +7488,7 @@ static int airo_get_scan(struct net_device *dev,
                         struct iw_point *dwrq,
                         char *extra)
 {
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
        BSSListElement *net;
        int err = 0;
        char *current_ev = extra;
@@ -7382,7 +7532,7 @@ static int airo_config_commit(struct net_device *dev,
                              void *zwrq,                       /* NULL */
                              char *extra)                      /* NULL */
 {
-       struct airo_info *local = dev->priv;
+       struct airo_info *local = dev->ml_priv;
 
        if (!test_bit (FLAG_COMMIT, &local->flags))
                return 0;
@@ -7527,7 +7677,7 @@ static const struct iw_handler_def        airo_handler_def =
 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;
+       struct airo_info *ai = dev->ml_priv;
 
        if (ai->power.event)
                return 0;
@@ -7655,7 +7805,7 @@ static void airo_read_wireless_stats(struct airo_info *local)
 
 static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev)
 {
-       struct airo_info *local =  dev->priv;
+       struct airo_info *local =  dev->ml_priv;
 
        if (!test_bit(JOB_WSTATS, &local->jobs)) {
                /* Get stats out of the card if available */
@@ -7680,7 +7830,7 @@ static int readrids(struct net_device *dev, aironet_ioctl *comp) {
        unsigned short ridcode;
        unsigned char *iobuf;
        int len;
-       struct airo_info *ai = dev->priv;
+       struct airo_info *ai = dev->ml_priv;
 
        if (test_bit(FLAG_FLASHING, &ai->flags))
                return -EIO;
@@ -7746,7 +7896,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;
+       struct airo_info *ai = dev->ml_priv;
        int  ridcode;
         int  enabled;
        static int (* writer)(struct airo_info *, u16 rid, const void *, int, int);
@@ -7869,41 +8019,41 @@ static int flashcard(struct net_device *dev, aironet_ioctl *comp) {
        switch(comp->command)
        {
        case AIROFLSHRST:
-               return cmdreset((struct airo_info *)dev->priv);
+               return cmdreset((struct airo_info *)dev->ml_priv);
 
        case AIROFLSHSTFL:
-               if (!((struct airo_info *)dev->priv)->flash &&
-                       (((struct airo_info *)dev->priv)->flash = kmalloc (FLASHSIZE, GFP_KERNEL)) == NULL)
+               if (!AIRO_FLASH(dev) &&
+                   (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL)
                        return -ENOMEM;
-               return setflashmode((struct airo_info *)dev->priv);
+               return setflashmode((struct airo_info *)dev->ml_priv);
 
        case AIROFLSHGCHR: /* Get char from aux */
                if(comp->len != sizeof(int))
                        return -EINVAL;
                if (copy_from_user(&z,comp->data,comp->len))
                        return -EFAULT;
-               return flashgchar((struct airo_info *)dev->priv,z,8000);
+               return flashgchar((struct airo_info *)dev->ml_priv, z, 8000);
 
        case AIROFLSHPCHR: /* Send char to card. */
                if(comp->len != sizeof(int))
                        return -EINVAL;
                if (copy_from_user(&z,comp->data,comp->len))
                        return -EFAULT;
-               return flashpchar((struct airo_info *)dev->priv,z,8000);
+               return flashpchar((struct airo_info *)dev->ml_priv, z, 8000);
 
        case AIROFLPUTBUF: /* Send 32k to card */
-               if (!((struct airo_info *)dev->priv)->flash)
+               if (!AIRO_FLASH(dev))
                        return -ENOMEM;
                if(comp->len > FLASHSIZE)
                        return -EINVAL;
-               if(copy_from_user(((struct airo_info *)dev->priv)->flash,comp->data,comp->len))
+               if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len))
                        return -EFAULT;
 
-               flashputbuf((struct airo_info *)dev->priv);
+               flashputbuf((struct airo_info *)dev->ml_priv);
                return 0;
 
        case AIRORESTART:
-               if(flashrestart((struct airo_info *)dev->priv,dev))
+               if (flashrestart((struct airo_info *)dev->ml_priv, dev))
                        return -EIO;
                return 0;
        }