include cleanup: Update gfp.h and slab.h includes to prepare for breaking implicit...
[safe/jmp/linux-2.6] / drivers / net / wireless / orinoco / wext.c
index 74fdfce..fbcc6e1 100644 (file)
@@ -2,11 +2,13 @@
  *
  * See copyright notice in main.c
  */
+#include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
 #include <linux/wireless.h>
 #include <linux/ieee80211.h>
 #include <net/iw_handler.h>
+#include <net/cfg80211.h>
 
 #include "hermes.h"
 #include "hermes_rid.h"
 
 #define MAX_RID_LEN 1024
 
+/* Helper routine to record keys
+ * It is called under orinoco_lock so it may not sleep */
+static int orinoco_set_key(struct orinoco_private *priv, int index,
+                          enum orinoco_alg alg, const u8 *key, int key_len,
+                          const u8 *seq, int seq_len)
+{
+       kzfree(priv->keys[index].key);
+       kzfree(priv->keys[index].seq);
+
+       if (key_len) {
+               priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC);
+               if (!priv->keys[index].key)
+                       goto nomem;
+       } else
+               priv->keys[index].key = NULL;
+
+       if (seq_len) {
+               priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC);
+               if (!priv->keys[index].seq)
+                       goto free_key;
+       } else
+               priv->keys[index].seq = NULL;
+
+       priv->keys[index].key_len = key_len;
+       priv->keys[index].seq_len = seq_len;
+
+       if (key_len)
+               memcpy(priv->keys[index].key, key, key_len);
+       if (seq_len)
+               memcpy(priv->keys[index].seq, seq, seq_len);
+
+       switch (alg) {
+       case ORINOCO_ALG_TKIP:
+               priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP;
+               break;
+
+       case ORINOCO_ALG_WEP:
+               priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ?
+                       WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40;
+               break;
+
+       case ORINOCO_ALG_NONE:
+       default:
+               priv->keys[index].cipher = 0;
+               break;
+       }
+
+       return 0;
+
+free_key:
+       kfree(priv->keys[index].key);
+       priv->keys[index].key = NULL;
+
+nomem:
+       priv->keys[index].key_len = 0;
+       priv->keys[index].seq_len = 0;
+       priv->keys[index].cipher = 0;
+
+       return -ENOMEM;
+}
+
 static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        struct iw_statistics *wstats = &priv->wstats;
        int err;
@@ -51,7 +114,7 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
         * here so we're not safe to sleep here. */
        hermes_inquire(hw, HERMES_INQ_TALLIES);
 
-       if (priv->iw_mode == IW_MODE_ADHOC) {
+       if (priv->iw_mode == NL80211_IFTYPE_ADHOC) {
                memset(&wstats->qual, 0, sizeof(wstats->qual));
                /* If a spy address is defined, we report stats of the
                 * first spy address - Jean II */
@@ -87,31 +150,12 @@ static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev)
 /* Wireless extensions                                              */
 /********************************************************************/
 
-static int orinoco_ioctl_getname(struct net_device *dev,
-                                struct iw_request_info *info,
-                                char *name,
-                                char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       int numrates;
-       int err;
-
-       err = orinoco_hw_get_bitratelist(priv, &numrates, NULL, 0);
-
-       if (!err && (numrates > 2))
-               strcpy(name, "IEEE 802.11b");
-       else
-               strcpy(name, "IEEE 802.11-DS");
-
-       return 0;
-}
-
 static int orinoco_ioctl_setwap(struct net_device *dev,
                                struct iw_request_info *info,
                                struct sockaddr *ap_addr,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int err = -EINPROGRESS;         /* Call commit handler */
        unsigned long flags;
        static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -142,7 +186,7 @@ static int orinoco_ioctl_setwap(struct net_device *dev,
                goto out;
        }
 
-       if (priv->iw_mode != IW_MODE_INFRA) {
+       if (priv->iw_mode != NL80211_IFTYPE_STATION) {
                printk(KERN_WARNING "%s: Manual roaming supported only in "
                       "managed mode\n", dev->name);
                err = -EOPNOTSUPP;
@@ -172,9 +216,8 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
                                struct sockaddr *ap_addr,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
 
-       hermes_t *hw = &priv->hw;
        int err = 0;
        unsigned long flags;
 
@@ -182,197 +225,23 @@ static int orinoco_ioctl_getwap(struct net_device *dev,
                return -EBUSY;
 
        ap_addr->sa_family = ARPHRD_ETHER;
-       err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-                             ETH_ALEN, NULL, ap_addr->sa_data);
+       err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data);
 
        orinoco_unlock(priv, &flags);
 
        return err;
 }
 
-static int orinoco_ioctl_setmode(struct net_device *dev,
-                                struct iw_request_info *info,
-                                u32 *mode,
-                                char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       int err = -EINPROGRESS;         /* Call commit handler */
-       unsigned long flags;
-
-       if (priv->iw_mode == *mode)
-               return 0;
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       switch (*mode) {
-       case IW_MODE_ADHOC:
-               if (!priv->has_ibss && !priv->has_port3)
-                       err = -EOPNOTSUPP;
-               break;
-
-       case IW_MODE_INFRA:
-               break;
-
-       case IW_MODE_MONITOR:
-               if (priv->broken_monitor && !force_monitor) {
-                       printk(KERN_WARNING "%s: Monitor mode support is "
-                              "buggy in this firmware, not enabling\n",
-                              dev->name);
-                       err = -EOPNOTSUPP;
-               }
-               break;
-
-       default:
-               err = -EOPNOTSUPP;
-               break;
-       }
-
-       if (err == -EINPROGRESS) {
-               priv->iw_mode = *mode;
-               set_port_type(priv);
-       }
-
-       orinoco_unlock(priv, &flags);
-
-       return err;
-}
-
-static int orinoco_ioctl_getmode(struct net_device *dev,
-                                struct iw_request_info *info,
-                                u32 *mode,
-                                char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-
-       *mode = priv->iw_mode;
-       return 0;
-}
-
-static int orinoco_ioctl_getiwrange(struct net_device *dev,
-                                   struct iw_request_info *info,
-                                   struct iw_point *rrq,
-                                   char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       int err = 0;
-       struct iw_range *range = (struct iw_range *) extra;
-       int numrates;
-       int i, k;
-
-       rrq->length = sizeof(struct iw_range);
-       memset(range, 0, sizeof(struct iw_range));
-
-       range->we_version_compiled = WIRELESS_EXT;
-       range->we_version_source = 22;
-
-       /* Set available channels/frequencies */
-       range->num_channels = NUM_CHANNELS;
-       k = 0;
-       for (i = 0; i < NUM_CHANNELS; i++) {
-               if (priv->channel_mask & (1 << i)) {
-                       range->freq[k].i = i + 1;
-                       range->freq[k].m = (ieee80211_dsss_chan_to_freq(i + 1) *
-                                           100000);
-                       range->freq[k].e = 1;
-                       k++;
-               }
-
-               if (k >= IW_MAX_FREQUENCIES)
-                       break;
-       }
-       range->num_frequency = k;
-       range->sensitivity = 3;
-
-       if (priv->has_wep) {
-               range->max_encoding_tokens = ORINOCO_MAX_KEYS;
-               range->encoding_size[0] = SMALL_KEY_SIZE;
-               range->num_encoding_sizes = 1;
-
-               if (priv->has_big_wep) {
-                       range->encoding_size[1] = LARGE_KEY_SIZE;
-                       range->num_encoding_sizes = 2;
-               }
-       }
-
-       if (priv->has_wpa)
-               range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_CIPHER_TKIP;
-
-       if ((priv->iw_mode == IW_MODE_ADHOC) && (!SPY_NUMBER(priv))) {
-               /* Quality stats meaningless in ad-hoc mode */
-       } else {
-               range->max_qual.qual = 0x8b - 0x2f;
-               range->max_qual.level = 0x2f - 0x95 - 1;
-               range->max_qual.noise = 0x2f - 0x95 - 1;
-               /* Need to get better values */
-               range->avg_qual.qual = 0x24;
-               range->avg_qual.level = 0xC2;
-               range->avg_qual.noise = 0x9E;
-       }
-
-       err = orinoco_hw_get_bitratelist(priv, &numrates,
-                                        range->bitrate, IW_MAX_BITRATES);
-       if (err)
-               return err;
-       range->num_bitrates = numrates;
-
-       /* Set an indication of the max TCP throughput in bit/s that we can
-        * expect using this interface. May be use for QoS stuff...
-        * Jean II */
-       if (numrates > 2)
-               range->throughput = 5 * 1000 * 1000;    /* ~5 Mb/s */
-       else
-               range->throughput = 1.5 * 1000 * 1000;  /* ~1.5 Mb/s */
-
-       range->min_rts = 0;
-       range->max_rts = 2347;
-       range->min_frag = 256;
-       range->max_frag = 2346;
-
-       range->min_pmp = 0;
-       range->max_pmp = 65535000;
-       range->min_pmt = 0;
-       range->max_pmt = 65535 * 1000;  /* ??? */
-       range->pmp_flags = IW_POWER_PERIOD;
-       range->pmt_flags = IW_POWER_TIMEOUT;
-       range->pm_capa = (IW_POWER_PERIOD | IW_POWER_TIMEOUT |
-                         IW_POWER_UNICAST_R);
-
-       range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
-       range->retry_flags = IW_RETRY_LIMIT;
-       range->r_time_flags = IW_RETRY_LIFETIME;
-       range->min_retry = 0;
-       range->max_retry = 65535;       /* ??? */
-       range->min_r_time = 0;
-       range->max_r_time = 65535 * 1000;       /* ??? */
-
-       if (priv->firmware_type == FIRMWARE_TYPE_AGERE)
-               range->scan_capa = IW_SCAN_CAPA_ESSID;
-       else
-               range->scan_capa = IW_SCAN_CAPA_NONE;
-
-       /* Event capability (kernel) */
-       IW_EVENT_CAPA_SET_KERNEL(range->event_capa);
-       /* Event capability (driver) */
-       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWTHRSPY);
-       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP);
-       IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN);
-       IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP);
-
-       return 0;
-}
-
 static int orinoco_ioctl_setiwencode(struct net_device *dev,
                                     struct iw_request_info *info,
                                     struct iw_point *erq,
                                     char *keybuf)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int index = (erq->flags & IW_ENCODE_INDEX) - 1;
        int setindex = priv->tx_key;
-       int encode_alg = priv->encode_alg;
+       enum orinoco_alg encode_alg = priv->encode_alg;
        int restricted = priv->wep_restrict;
-       u16 xlen = 0;
        int err = -EINPROGRESS;         /* Call commit handler */
        unsigned long flags;
 
@@ -392,25 +261,17 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
                return -EBUSY;
 
        /* Clear any TKIP key we have */
-       if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_ALG_TKIP))
+       if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP))
                (void) orinoco_clear_tkip_key(priv, setindex);
 
        if (erq->length > 0) {
                if ((index < 0) || (index >= ORINOCO_MAX_KEYS))
                        index = priv->tx_key;
 
-               /* Adjust key length to a supported value */
-               if (erq->length > SMALL_KEY_SIZE)
-                       xlen = LARGE_KEY_SIZE;
-               else if (erq->length > 0)
-                       xlen = SMALL_KEY_SIZE;
-               else
-                       xlen = 0;
-
                /* Switch on WEP if off */
-               if ((encode_alg != IW_ENCODE_ALG_WEP) && (xlen > 0)) {
+               if (encode_alg != ORINOCO_ALG_WEP) {
                        setindex = index;
-                       encode_alg = IW_ENCODE_ALG_WEP;
+                       encode_alg = ORINOCO_ALG_WEP;
                }
        } else {
                /* Important note : if the user do "iwconfig eth0 enc off",
@@ -423,7 +284,7 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
                        }
                } else {
                        /* Set the index : Check that the key is valid */
-                       if (priv->keys[index].len == 0) {
+                       if (priv->keys[index].key_len == 0) {
                                err = -EINVAL;
                                goto out;
                        }
@@ -432,17 +293,15 @@ static int orinoco_ioctl_setiwencode(struct net_device *dev,
        }
 
        if (erq->flags & IW_ENCODE_DISABLED)
-               encode_alg = IW_ENCODE_ALG_NONE;
+               encode_alg = ORINOCO_ALG_NONE;
        if (erq->flags & IW_ENCODE_OPEN)
                restricted = 0;
        if (erq->flags & IW_ENCODE_RESTRICTED)
                restricted = 1;
 
        if (erq->pointer && erq->length > 0) {
-               priv->keys[index].len = cpu_to_le16(xlen);
-               memset(priv->keys[index].data, 0,
-                      sizeof(priv->keys[index].data));
-               memcpy(priv->keys[index].data, keybuf, erq->length);
+               err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf,
+                                     erq->length, NULL, 0);
        }
        priv->tx_key = setindex;
 
@@ -469,9 +328,8 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
                                     struct iw_point *erq,
                                     char *keybuf)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int index = (erq->flags & IW_ENCODE_INDEX) - 1;
-       u16 xlen = 0;
        unsigned long flags;
 
        if (!priv->has_wep)
@@ -493,11 +351,9 @@ static int orinoco_ioctl_getiwencode(struct net_device *dev,
        else
                erq->flags |= IW_ENCODE_OPEN;
 
-       xlen = le16_to_cpu(priv->keys[index].len);
-
-       erq->length = xlen;
+       erq->length = priv->keys[index].key_len;
 
-       memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
+       memcpy(keybuf, priv->keys[index].key, erq->length);
 
        orinoco_unlock(priv, &flags);
        return 0;
@@ -508,7 +364,7 @@ static int orinoco_ioctl_setessid(struct net_device *dev,
                                  struct iw_point *erq,
                                  char *essidbuf)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        unsigned long flags;
 
        /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
@@ -539,7 +395,7 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
                                  struct iw_point *erq,
                                  char *essidbuf)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int active;
        int err = 0;
        unsigned long flags;
@@ -562,59 +418,18 @@ static int orinoco_ioctl_getessid(struct net_device *dev,
        return 0;
 }
 
-static int orinoco_ioctl_setnick(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_point *nrq,
-                                char *nickbuf)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
-
-       if (nrq->length > IW_ESSID_MAX_SIZE)
-               return -E2BIG;
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       memset(priv->nick, 0, sizeof(priv->nick));
-       memcpy(priv->nick, nickbuf, nrq->length);
-
-       orinoco_unlock(priv, &flags);
-
-       return -EINPROGRESS;            /* Call commit handler */
-}
-
-static int orinoco_ioctl_getnick(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_point *nrq,
-                                char *nickbuf)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       unsigned long flags;
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE);
-       orinoco_unlock(priv, &flags);
-
-       nrq->length = strlen(priv->nick);
-
-       return 0;
-}
-
 static int orinoco_ioctl_setfreq(struct net_device *dev,
                                 struct iw_request_info *info,
                                 struct iw_freq *frq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int chan = -1;
        unsigned long flags;
        int err = -EINPROGRESS;         /* Call commit handler */
 
        /* In infrastructure mode the AP sets the channel */
-       if (priv->iw_mode == IW_MODE_INFRA)
+       if (priv->iw_mode == NL80211_IFTYPE_STATION)
                return -EBUSY;
 
        if ((frq->e == 0) && (frq->m <= 1000)) {
@@ -640,7 +455,7 @@ static int orinoco_ioctl_setfreq(struct net_device *dev,
                return -EBUSY;
 
        priv->channel = chan;
-       if (priv->iw_mode == IW_MODE_MONITOR) {
+       if (priv->iw_mode == NL80211_IFTYPE_MONITOR) {
                /* Fast channel change - no commit if successful */
                hermes_t *hw = &priv->hw;
                err = hermes_docmd_wait(hw, HERMES_CMD_TEST |
@@ -657,7 +472,7 @@ static int orinoco_ioctl_getfreq(struct net_device *dev,
                                 struct iw_freq *frq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int tmp;
 
        /* Locking done in there */
@@ -676,7 +491,7 @@ static int orinoco_ioctl_getsens(struct net_device *dev,
                                 struct iw_param *srq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        u16 val;
        int err;
@@ -705,7 +520,7 @@ static int orinoco_ioctl_setsens(struct net_device *dev,
                                 struct iw_param *srq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int val = srq->value;
        unsigned long flags;
 
@@ -728,7 +543,7 @@ static int orinoco_ioctl_setrts(struct net_device *dev,
                                struct iw_param *rrq,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int val = rrq->value;
        unsigned long flags;
 
@@ -752,7 +567,7 @@ static int orinoco_ioctl_getrts(struct net_device *dev,
                                struct iw_param *rrq,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
 
        rrq->value = priv->rts_thresh;
        rrq->disabled = (rrq->value == 2347);
@@ -766,7 +581,7 @@ static int orinoco_ioctl_setfrag(struct net_device *dev,
                                 struct iw_param *frq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int err = -EINPROGRESS;         /* Call commit handler */
        unsigned long flags;
 
@@ -806,7 +621,7 @@ static int orinoco_ioctl_getfrag(struct net_device *dev,
                                 struct iw_param *frq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        int err;
        u16 val;
@@ -847,7 +662,7 @@ static int orinoco_ioctl_setrate(struct net_device *dev,
                                 struct iw_param *rrq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int ratemode;
        int bitrate; /* 100s of kilobits */
        unsigned long flags;
@@ -881,7 +696,7 @@ static int orinoco_ioctl_getrate(struct net_device *dev,
                                 struct iw_param *rrq,
                                 char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int err = 0;
        int bitrate, automatic;
        unsigned long flags;
@@ -910,7 +725,7 @@ static int orinoco_ioctl_setpower(struct net_device *dev,
                                  struct iw_param *prq,
                                  char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int err = -EINPROGRESS;         /* Call commit handler */
        unsigned long flags;
 
@@ -964,7 +779,7 @@ static int orinoco_ioctl_getpower(struct net_device *dev,
                                  struct iw_param *prq,
                                  char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        int err = 0;
        u16 enable, period, timeout, mcast;
@@ -1018,13 +833,12 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
                                       union iwreq_data *wrqu,
                                       char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        struct iw_point *encoding = &wrqu->encoding;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int idx, alg = ext->alg, set_key = 1;
        unsigned long flags;
        int err = -EINVAL;
-       u16 key_len;
 
        if (orinoco_lock(priv, &flags) != 0)
                return -EBUSY;
@@ -1056,25 +870,18 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
                /* Set the requested key first */
                switch (alg) {
                case IW_ENCODE_ALG_NONE:
-                       priv->encode_alg = alg;
-                       priv->keys[idx].len = 0;
+                       priv->encode_alg = ORINOCO_ALG_NONE;
+                       err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE,
+                                             NULL, 0, NULL, 0);
                        break;
 
                case IW_ENCODE_ALG_WEP:
-                       if (ext->key_len > SMALL_KEY_SIZE)
-                               key_len = LARGE_KEY_SIZE;
-                       else if (ext->key_len > 0)
-                               key_len = SMALL_KEY_SIZE;
-                       else
+                       if (ext->key_len <= 0)
                                goto out;
 
-                       priv->encode_alg = alg;
-                       priv->keys[idx].len = cpu_to_le16(key_len);
-
-                       key_len = min(ext->key_len, key_len);
-
-                       memset(priv->keys[idx].data, 0, ORINOCO_MAX_KEY_SIZE);
-                       memcpy(priv->keys[idx].data, ext->key, key_len);
+                       priv->encode_alg = ORINOCO_ALG_WEP;
+                       err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP,
+                                             ext->key, ext->key_len, NULL, 0);
                        break;
 
                case IW_ENCODE_ALG_TKIP:
@@ -1082,21 +889,22 @@ static int orinoco_ioctl_set_encodeext(struct net_device *dev,
                        u8 *tkip_iv = NULL;
 
                        if (!priv->has_wpa ||
-                           (ext->key_len > sizeof(priv->tkip_key[0])))
+                           (ext->key_len > sizeof(struct orinoco_tkip_key)))
                                goto out;
 
-                       priv->encode_alg = alg;
-                       memset(&priv->tkip_key[idx], 0,
-                              sizeof(priv->tkip_key[idx]));
-                       memcpy(&priv->tkip_key[idx], ext->key, ext->key_len);
+                       priv->encode_alg = ORINOCO_ALG_TKIP;
 
                        if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
                                tkip_iv = &ext->rx_seq[0];
 
+                       err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP,
+                                             ext->key, ext->key_len, tkip_iv,
+                                             ORINOCO_SEQ_LEN);
+
                        err = __orinoco_hw_set_tkip_key(priv, idx,
                                 ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
-                                (u8 *) &priv->tkip_key[idx],
-                                tkip_iv, NULL);
+                                priv->keys[idx].key,
+                                tkip_iv, ORINOCO_SEQ_LEN, NULL, 0);
                        if (err)
                                printk(KERN_ERR "%s: Error %d setting TKIP key"
                                       "\n", dev->name, err);
@@ -1119,7 +927,7 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
                                       union iwreq_data *wrqu,
                                       char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        struct iw_point *encoding = &wrqu->encoding;
        struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
        int idx, max_key_len;
@@ -1145,22 +953,22 @@ static int orinoco_ioctl_get_encodeext(struct net_device *dev,
        encoding->flags = idx + 1;
        memset(ext, 0, sizeof(*ext));
 
-       ext->alg = priv->encode_alg;
        switch (priv->encode_alg) {
-       case IW_ENCODE_ALG_NONE:
+       case ORINOCO_ALG_NONE:
+               ext->alg = IW_ENCODE_ALG_NONE;
                ext->key_len = 0;
                encoding->flags |= IW_ENCODE_DISABLED;
                break;
-       case IW_ENCODE_ALG_WEP:
-               ext->key_len = min_t(u16, le16_to_cpu(priv->keys[idx].len),
-                                    max_key_len);
-               memcpy(ext->key, priv->keys[idx].data, ext->key_len);
+       case ORINOCO_ALG_WEP:
+               ext->alg = IW_ENCODE_ALG_WEP;
+               ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+               memcpy(ext->key, priv->keys[idx].key, ext->key_len);
                encoding->flags |= IW_ENCODE_ENABLED;
                break;
-       case IW_ENCODE_ALG_TKIP:
-               ext->key_len = min_t(u16, sizeof(struct orinoco_tkip_key),
-                                    max_key_len);
-               memcpy(ext->key, &priv->tkip_key[idx], ext->key_len);
+       case ORINOCO_ALG_TKIP:
+               ext->alg = IW_ENCODE_ALG_TKIP;
+               ext->key_len = min(priv->keys[idx].key_len, max_key_len);
+               memcpy(ext->key, priv->keys[idx].key, ext->key_len);
                encoding->flags |= IW_ENCODE_ENABLED;
                break;
        }
@@ -1176,7 +984,7 @@ static int orinoco_ioctl_set_auth(struct net_device *dev,
                                  struct iw_request_info *info,
                                  union iwreq_data *wrqu, char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        struct iw_param *param = &wrqu->param;
        unsigned long flags;
@@ -1254,7 +1062,7 @@ static int orinoco_ioctl_get_auth(struct net_device *dev,
                                  struct iw_request_info *info,
                                  union iwreq_data *wrqu, char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        struct iw_param *param = &wrqu->param;
        unsigned long flags;
        int ret = 0;
@@ -1294,7 +1102,7 @@ static int orinoco_ioctl_set_genie(struct net_device *dev,
                                   struct iw_request_info *info,
                                   union iwreq_data *wrqu, char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        u8 *buf;
        unsigned long flags;
 
@@ -1337,7 +1145,7 @@ static int orinoco_ioctl_get_genie(struct net_device *dev,
                                   struct iw_request_info *info,
                                   union iwreq_data *wrqu, char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        unsigned long flags;
        int err = 0;
 
@@ -1366,8 +1174,7 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
                                  struct iw_request_info *info,
                                  union iwreq_data *wrqu, char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
-       hermes_t *hw = &priv->hw;
+       struct orinoco_private *priv = ndev_priv(dev);
        struct iw_mlme *mlme = (struct iw_mlme *)extra;
        unsigned long flags;
        int ret = 0;
@@ -1381,19 +1188,11 @@ static int orinoco_ioctl_set_mlme(struct net_device *dev,
                break;
 
        case IW_MLME_DISASSOC:
-       {
-               struct {
-                       u8 addr[ETH_ALEN];
-                       __le16 reason_code;
-               } __attribute__ ((packed)) buf;
-
-               memcpy(buf.addr, mlme->addr.sa_data, ETH_ALEN);
-               buf.reason_code = cpu_to_le16(mlme->reason_code);
-               ret = HERMES_WRITE_RECORD(hw, USER_BAP,
-                                         HERMES_RID_CNFDISASSOCIATE,
-                                         &buf);
+
+               ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data,
+                                             mlme->reason_code);
                break;
-       }
+
        default:
                ret = -EOPNOTSUPP;
        }
@@ -1407,7 +1206,7 @@ static int orinoco_ioctl_getretry(struct net_device *dev,
                                  struct iw_param *rrq,
                                  char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        int err = 0;
        u16 short_limit, long_limit, lifetime;
@@ -1461,7 +1260,7 @@ static int orinoco_ioctl_reset(struct net_device *dev,
                               void *wrqu,
                               char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
 
        if (!capable(CAP_NET_ADMIN))
                return -EPERM;
@@ -1486,14 +1285,14 @@ static int orinoco_ioctl_setibssport(struct net_device *dev,
                                     char *extra)
 
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int val = *((int *) extra);
        unsigned long flags;
 
        if (orinoco_lock(priv, &flags) != 0)
                return -EBUSY;
 
-       priv->ibss_port = val ;
+       priv->ibss_port = val;
 
        /* Actually update the mode we are using */
        set_port_type(priv);
@@ -1507,7 +1306,7 @@ static int orinoco_ioctl_getibssport(struct net_device *dev,
                                     void *wrqu,
                                     char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int *val = (int *) extra;
 
        *val = priv->ibss_port;
@@ -1519,7 +1318,7 @@ static int orinoco_ioctl_setport3(struct net_device *dev,
                                  void *wrqu,
                                  char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int val = *((int *) extra);
        int err = 0;
        unsigned long flags;
@@ -1565,7 +1364,7 @@ static int orinoco_ioctl_getport3(struct net_device *dev,
                                  void *wrqu,
                                  char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int *val = (int *) extra;
 
        *val = priv->prefer_port3;
@@ -1577,7 +1376,7 @@ static int orinoco_ioctl_setpreamble(struct net_device *dev,
                                     void *wrqu,
                                     char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        unsigned long flags;
        int val;
 
@@ -1609,7 +1408,7 @@ static int orinoco_ioctl_getpreamble(struct net_device *dev,
                                     void *wrqu,
                                     char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        int *val = (int *) extra;
 
        if (!priv->has_preamble)
@@ -1629,7 +1428,7 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
                                struct iw_point *data,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
+       struct orinoco_private *priv = ndev_priv(dev);
        hermes_t *hw = &priv->hw;
        int rid = data->flags;
        u16 length;
@@ -1660,519 +1459,6 @@ static int orinoco_ioctl_getrid(struct net_device *dev,
        return err;
 }
 
-/* Trigger a scan (look for other cells in the vicinity) */
-static int orinoco_ioctl_setscan(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_point *srq,
-                                char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       hermes_t *hw = &priv->hw;
-       struct iw_scan_req *si = (struct iw_scan_req *) extra;
-       int err = 0;
-       unsigned long flags;
-
-       /* Note : you may have realised that, as this is a SET operation,
-        * this is privileged and therefore a normal user can't
-        * perform scanning.
-        * This is not an error, while the device perform scanning,
-        * traffic doesn't flow, so it's a perfect DoS...
-        * Jean II */
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       /* Scanning with port 0 disabled would fail */
-       if (!netif_running(dev)) {
-               err = -ENETDOWN;
-               goto out;
-       }
-
-       /* In monitor mode, the scan results are always empty.
-        * Probe responses are passed to the driver as received
-        * frames and could be processed in software. */
-       if (priv->iw_mode == IW_MODE_MONITOR) {
-               err = -EOPNOTSUPP;
-               goto out;
-       }
-
-       /* Note : because we don't lock out the irq handler, the way
-        * we access scan variables in priv is critical.
-        *      o scan_inprogress : not touched by irq handler
-        *      o scan_mode : not touched by irq handler
-        * Before modifying anything on those variables, please think hard !
-        * Jean II */
-
-       /* Save flags */
-       priv->scan_mode = srq->flags;
-
-       /* Always trigger scanning, even if it's in progress.
-        * This way, if the info frame get lost, we will recover somewhat
-        * gracefully  - Jean II */
-
-       if (priv->has_hostscan) {
-               switch (priv->firmware_type) {
-               case FIRMWARE_TYPE_SYMBOL:
-                       err = hermes_write_wordrec(hw, USER_BAP,
-                                               HERMES_RID_CNFHOSTSCAN_SYMBOL,
-                                               HERMES_HOSTSCAN_SYMBOL_ONCE |
-                                               HERMES_HOSTSCAN_SYMBOL_BCAST);
-                       break;
-               case FIRMWARE_TYPE_INTERSIL: {
-                       __le16 req[3];
-
-                       req[0] = cpu_to_le16(0x3fff);   /* All channels */
-                       req[1] = cpu_to_le16(0x0001);   /* rate 1 Mbps */
-                       req[2] = 0;                     /* Any ESSID */
-                       err = HERMES_WRITE_RECORD(hw, USER_BAP,
-                                                 HERMES_RID_CNFHOSTSCAN, &req);
-               }
-               break;
-               case FIRMWARE_TYPE_AGERE:
-                       if (priv->scan_mode & IW_SCAN_THIS_ESSID) {
-                               struct hermes_idstring idbuf;
-                               size_t len = min(sizeof(idbuf.val),
-                                                (size_t) si->essid_len);
-                               idbuf.len = cpu_to_le16(len);
-                               memcpy(idbuf.val, si->essid, len);
-
-                               err = hermes_write_ltv(hw, USER_BAP,
-                                              HERMES_RID_CNFSCANSSID_AGERE,
-                                              HERMES_BYTES_TO_RECLEN(len + 2),
-                                              &idbuf);
-                       } else
-                               err = hermes_write_wordrec(hw, USER_BAP,
-                                                  HERMES_RID_CNFSCANSSID_AGERE,
-                                                  0);  /* Any ESSID */
-                       if (err)
-                               break;
-
-                       if (priv->has_ext_scan) {
-                               /* Clear scan results at the start of
-                                * an extended scan */
-                               orinoco_clear_scan_results(priv,
-                                               msecs_to_jiffies(15000));
-
-                               /* TODO: Is this available on older firmware?
-                                *   Can we use it to scan specific channels
-                                *   for IW_SCAN_THIS_FREQ? */
-                               err = hermes_write_wordrec(hw, USER_BAP,
-                                               HERMES_RID_CNFSCANCHANNELS2GHZ,
-                                               0x7FFF);
-                               if (err)
-                                       goto out;
-
-                               err = hermes_inquire(hw,
-                                                    HERMES_INQ_CHANNELINFO);
-                       } else
-                               err = hermes_inquire(hw, HERMES_INQ_SCAN);
-                       break;
-               }
-       } else
-               err = hermes_inquire(hw, HERMES_INQ_SCAN);
-
-       /* One more client */
-       if (!err)
-               priv->scan_inprogress = 1;
-
- out:
-       orinoco_unlock(priv, &flags);
-       return err;
-}
-
-#define MAX_CUSTOM_LEN 64
-
-/* Translate scan data returned from the card to a card independant
- * format that the Wireless Tools will understand - Jean II */
-static inline char *orinoco_translate_scan(struct net_device *dev,
-                                          struct iw_request_info *info,
-                                          char *current_ev,
-                                          char *end_buf,
-                                          union hermes_scan_info *bss,
-                                          unsigned long last_scanned)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       u16                     capabilities;
-       u16                     channel;
-       struct iw_event         iwe;            /* Temporary buffer */
-       char custom[MAX_CUSTOM_LEN];
-
-       memset(&iwe, 0, sizeof(iwe));
-
-       /* First entry *MUST* be the AP MAC address */
-       iwe.cmd = SIOCGIWAP;
-       iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-       memcpy(iwe.u.ap_addr.sa_data, bss->a.bssid, ETH_ALEN);
-       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                         &iwe, IW_EV_ADDR_LEN);
-
-       /* Other entries will be displayed in the order we give them */
-
-       /* Add the ESSID */
-       iwe.u.data.length = le16_to_cpu(bss->a.essid_len);
-       if (iwe.u.data.length > 32)
-               iwe.u.data.length = 32;
-       iwe.cmd = SIOCGIWESSID;
-       iwe.u.data.flags = 1;
-       current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                         &iwe, bss->a.essid);
-
-       /* Add mode */
-       iwe.cmd = SIOCGIWMODE;
-       capabilities = le16_to_cpu(bss->a.capabilities);
-       if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
-               if (capabilities & WLAN_CAPABILITY_ESS)
-                       iwe.u.mode = IW_MODE_MASTER;
-               else
-                       iwe.u.mode = IW_MODE_ADHOC;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_UINT_LEN);
-       }
-
-       channel = bss->s.channel;
-       if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
-               /* Add channel and frequency */
-               iwe.cmd = SIOCGIWFREQ;
-               iwe.u.freq.m = channel;
-               iwe.u.freq.e = 0;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_FREQ_LEN);
-
-               iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
-               iwe.u.freq.e = 1;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_FREQ_LEN);
-       }
-
-       /* Add quality statistics. level and noise in dB. No link quality */
-       iwe.cmd = IWEVQUAL;
-       iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
-       iwe.u.qual.level = (__u8) le16_to_cpu(bss->a.level) - 0x95;
-       iwe.u.qual.noise = (__u8) le16_to_cpu(bss->a.noise) - 0x95;
-       /* Wireless tools prior to 27.pre22 will show link quality
-        * anyway, so we provide a reasonable value. */
-       if (iwe.u.qual.level > iwe.u.qual.noise)
-               iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
-       else
-               iwe.u.qual.qual = 0;
-       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                         &iwe, IW_EV_QUAL_LEN);
-
-       /* Add encryption capability */
-       iwe.cmd = SIOCGIWENCODE;
-       if (capabilities & WLAN_CAPABILITY_PRIVACY)
-               iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-       else
-               iwe.u.data.flags = IW_ENCODE_DISABLED;
-       iwe.u.data.length = 0;
-       current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                         &iwe, NULL);
-
-       /* Bit rate is not available in Lucent/Agere firmwares */
-       if (priv->firmware_type != FIRMWARE_TYPE_AGERE) {
-               char *current_val = current_ev + iwe_stream_lcp_len(info);
-               int i;
-               int step;
-
-               if (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)
-                       step = 2;
-               else
-                       step = 1;
-
-               iwe.cmd = SIOCGIWRATE;
-               /* Those two flags are ignored... */
-               iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-               /* Max 10 values */
-               for (i = 0; i < 10; i += step) {
-                       /* NULL terminated */
-                       if (bss->p.rates[i] == 0x0)
-                               break;
-                       /* Bit rate given in 500 kb/s units (+ 0x80) */
-                       iwe.u.bitrate.value =
-                               ((bss->p.rates[i] & 0x7f) * 500000);
-                       current_val = iwe_stream_add_value(info, current_ev,
-                                                          current_val,
-                                                          end_buf, &iwe,
-                                                          IW_EV_PARAM_LEN);
-               }
-               /* Check if we added any event */
-               if ((current_val - current_ev) > iwe_stream_lcp_len(info))
-                       current_ev = current_val;
-       }
-
-       /* Beacon interval */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    "bcn_int=%d",
-                                    le16_to_cpu(bss->a.beacon_interv));
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       /* Capabilites */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    "capab=0x%04x",
-                                    capabilities);
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       /* Add EXTRA: Age to display seconds since last beacon/probe response
-        * for given network. */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    " Last beacon: %dms ago",
-                                    jiffies_to_msecs(jiffies - last_scanned));
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       return current_ev;
-}
-
-static inline char *orinoco_translate_ext_scan(struct net_device *dev,
-                                              struct iw_request_info *info,
-                                              char *current_ev,
-                                              char *end_buf,
-                                              struct agere_ext_scan_info *bss,
-                                              unsigned long last_scanned)
-{
-       u16                     capabilities;
-       u16                     channel;
-       struct iw_event         iwe;            /* Temporary buffer */
-       char custom[MAX_CUSTOM_LEN];
-       u8 *ie;
-
-       memset(&iwe, 0, sizeof(iwe));
-
-       /* First entry *MUST* be the AP MAC address */
-       iwe.cmd = SIOCGIWAP;
-       iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-       memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN);
-       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                         &iwe, IW_EV_ADDR_LEN);
-
-       /* Other entries will be displayed in the order we give them */
-
-       /* Add the ESSID */
-       ie = bss->data;
-       iwe.u.data.length = ie[1];
-       if (iwe.u.data.length) {
-               if (iwe.u.data.length > 32)
-                       iwe.u.data.length = 32;
-               iwe.cmd = SIOCGIWESSID;
-               iwe.u.data.flags = 1;
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, &ie[2]);
-       }
-
-       /* Add mode */
-       capabilities = le16_to_cpu(bss->capabilities);
-       if (capabilities & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
-               iwe.cmd = SIOCGIWMODE;
-               if (capabilities & WLAN_CAPABILITY_ESS)
-                       iwe.u.mode = IW_MODE_MASTER;
-               else
-                       iwe.u.mode = IW_MODE_ADHOC;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_UINT_LEN);
-       }
-
-       ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_DS_PARAMS);
-       channel = ie ? ie[2] : 0;
-       if ((channel >= 1) && (channel <= NUM_CHANNELS)) {
-               /* Add channel and frequency */
-               iwe.cmd = SIOCGIWFREQ;
-               iwe.u.freq.m = channel;
-               iwe.u.freq.e = 0;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_FREQ_LEN);
-
-               iwe.u.freq.m = ieee80211_dsss_chan_to_freq(channel) * 100000;
-               iwe.u.freq.e = 1;
-               current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                                 &iwe, IW_EV_FREQ_LEN);
-       }
-
-       /* Add quality statistics. level and noise in dB. No link quality */
-       iwe.cmd = IWEVQUAL;
-       iwe.u.qual.updated = IW_QUAL_DBM | IW_QUAL_QUAL_INVALID;
-       iwe.u.qual.level = bss->level - 0x95;
-       iwe.u.qual.noise = bss->noise - 0x95;
-       /* Wireless tools prior to 27.pre22 will show link quality
-        * anyway, so we provide a reasonable value. */
-       if (iwe.u.qual.level > iwe.u.qual.noise)
-               iwe.u.qual.qual = iwe.u.qual.level - iwe.u.qual.noise;
-       else
-               iwe.u.qual.qual = 0;
-       current_ev = iwe_stream_add_event(info, current_ev, end_buf,
-                                         &iwe, IW_EV_QUAL_LEN);
-
-       /* Add encryption capability */
-       iwe.cmd = SIOCGIWENCODE;
-       if (capabilities & WLAN_CAPABILITY_PRIVACY)
-               iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
-       else
-               iwe.u.data.flags = IW_ENCODE_DISABLED;
-       iwe.u.data.length = 0;
-       current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                         &iwe, NULL);
-
-       /* WPA IE */
-       ie = orinoco_get_wpa_ie(bss->data, sizeof(bss->data));
-       if (ie) {
-               iwe.cmd = IWEVGENIE;
-               iwe.u.data.length = ie[1] + 2;
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, ie);
-       }
-
-       /* RSN IE */
-       ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_RSN);
-       if (ie) {
-               iwe.cmd = IWEVGENIE;
-               iwe.u.data.length = ie[1] + 2;
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, ie);
-       }
-
-       ie = orinoco_get_ie(bss->data, sizeof(bss->data), WLAN_EID_SUPP_RATES);
-       if (ie) {
-               char *p = current_ev + iwe_stream_lcp_len(info);
-               int i;
-
-               iwe.cmd = SIOCGIWRATE;
-               /* Those two flags are ignored... */
-               iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
-
-               for (i = 2; i < (ie[1] + 2); i++) {
-                       iwe.u.bitrate.value = ((ie[i] & 0x7F) * 500000);
-                       p = iwe_stream_add_value(info, current_ev, p, end_buf,
-                                                &iwe, IW_EV_PARAM_LEN);
-               }
-               /* Check if we added any event */
-               if (p > (current_ev + iwe_stream_lcp_len(info)))
-                       current_ev = p;
-       }
-
-       /* Timestamp */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length =
-               snprintf(custom, MAX_CUSTOM_LEN, "tsf=%016llx",
-                        (unsigned long long) le64_to_cpu(bss->timestamp));
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       /* Beacon interval */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    "bcn_int=%d",
-                                    le16_to_cpu(bss->beacon_interval));
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       /* Capabilites */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    "capab=0x%04x",
-                                    capabilities);
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       /* Add EXTRA: Age to display seconds since last beacon/probe response
-        * for given network. */
-       iwe.cmd = IWEVCUSTOM;
-       iwe.u.data.length = snprintf(custom, MAX_CUSTOM_LEN,
-                                    " Last beacon: %dms ago",
-                                    jiffies_to_msecs(jiffies - last_scanned));
-       if (iwe.u.data.length)
-               current_ev = iwe_stream_add_point(info, current_ev, end_buf,
-                                                 &iwe, custom);
-
-       return current_ev;
-}
-
-/* Return results of a scan */
-static int orinoco_ioctl_getscan(struct net_device *dev,
-                                struct iw_request_info *info,
-                                struct iw_point *srq,
-                                char *extra)
-{
-       struct orinoco_private *priv = netdev_priv(dev);
-       int err = 0;
-       unsigned long flags;
-       char *current_ev = extra;
-
-       if (orinoco_lock(priv, &flags) != 0)
-               return -EBUSY;
-
-       if (priv->scan_inprogress) {
-               /* Important note : we don't want to block the caller
-                * until results are ready for various reasons.
-                * First, managing wait queues is complex and racy.
-                * Second, we grab some rtnetlink lock before comming
-                * here (in dev_ioctl()).
-                * Third, we generate an Wireless Event, so the
-                * caller can wait itself on that - Jean II */
-               err = -EAGAIN;
-               goto out;
-       }
-
-       if (priv->has_ext_scan) {
-               struct xbss_element *bss;
-
-               list_for_each_entry(bss, &priv->bss_list, list) {
-                       /* Translate this entry to WE format */
-                       current_ev =
-                               orinoco_translate_ext_scan(dev, info,
-                                                          current_ev,
-                                                          extra + srq->length,
-                                                          &bss->bss,
-                                                          bss->last_scanned);
-
-                       /* Check if there is space for one more entry */
-                       if ((extra + srq->length - current_ev)
-                           <= IW_EV_ADDR_LEN) {
-                               /* Ask user space to try again with a
-                                * bigger buffer */
-                               err = -E2BIG;
-                               goto out;
-                       }
-               }
-
-       } else {
-               struct bss_element *bss;
-
-               list_for_each_entry(bss, &priv->bss_list, list) {
-                       /* Translate this entry to WE format */
-                       current_ev = orinoco_translate_scan(dev, info,
-                                                           current_ev,
-                                                           extra + srq->length,
-                                                           &bss->bss,
-                                                           bss->last_scanned);
-
-                       /* Check if there is space for one more entry */
-                       if ((extra + srq->length - current_ev)
-                           <= IW_EV_ADDR_LEN) {
-                               /* Ask user space to try again with a
-                                * bigger buffer */
-                               err = -E2BIG;
-                               goto out;
-                       }
-               }
-       }
-
-       srq->length = (current_ev - extra);
-       srq->flags = (__u16) priv->scan_mode;
-
-out:
-       orinoco_unlock(priv, &flags);
-       return err;
-}
 
 /* Commit handler, called after set operations */
 static int orinoco_ioctl_commit(struct net_device *dev,
@@ -2180,50 +1466,17 @@ static int orinoco_ioctl_commit(struct net_device *dev,
                                void *wrqu,
                                char *extra)
 {
-       struct orinoco_private *priv = netdev_priv(dev);
-       struct hermes *hw = &priv->hw;
+       struct orinoco_private *priv = ndev_priv(dev);
        unsigned long flags;
        int err = 0;
 
        if (!priv->open)
                return 0;
 
-       if (priv->broken_disableport) {
-               orinoco_reset(&priv->reset_work);
-               return 0;
-       }
-
        if (orinoco_lock(priv, &flags) != 0)
                return err;
 
-       err = hermes_disable_port(hw, 0);
-       if (err) {
-               printk(KERN_WARNING "%s: Unable to disable port "
-                      "while reconfiguring card\n", dev->name);
-               priv->broken_disableport = 1;
-               goto out;
-       }
-
-       err = __orinoco_program_rids(dev);
-       if (err) {
-               printk(KERN_WARNING "%s: Unable to reconfigure card\n",
-                      dev->name);
-               goto out;
-       }
-
-       err = hermes_enable_port(hw, 0);
-       if (err) {
-               printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n",
-                      dev->name);
-               goto out;
-       }
-
- out:
-       if (err) {
-               printk(KERN_WARNING "%s: Resetting instead...\n", dev->name);
-               schedule_work(&priv->reset_work);
-               err = 0;
-       }
+       err = orinoco_commit(priv);
 
        orinoco_unlock(priv, &flags);
        return err;
@@ -2257,26 +1510,24 @@ static const struct iw_priv_args orinoco_privtab[] = {
        [IW_IOCTL_IDX(id)] = (iw_handler) func
 static const iw_handler        orinoco_handler[] = {
        STD_IW_HANDLER(SIOCSIWCOMMIT,   orinoco_ioctl_commit),
-       STD_IW_HANDLER(SIOCGIWNAME,     orinoco_ioctl_getname),
+       STD_IW_HANDLER(SIOCGIWNAME,     cfg80211_wext_giwname),
        STD_IW_HANDLER(SIOCSIWFREQ,     orinoco_ioctl_setfreq),
        STD_IW_HANDLER(SIOCGIWFREQ,     orinoco_ioctl_getfreq),
-       STD_IW_HANDLER(SIOCSIWMODE,     orinoco_ioctl_setmode),
-       STD_IW_HANDLER(SIOCGIWMODE,     orinoco_ioctl_getmode),
+       STD_IW_HANDLER(SIOCSIWMODE,     cfg80211_wext_siwmode),
+       STD_IW_HANDLER(SIOCGIWMODE,     cfg80211_wext_giwmode),
        STD_IW_HANDLER(SIOCSIWSENS,     orinoco_ioctl_setsens),
        STD_IW_HANDLER(SIOCGIWSENS,     orinoco_ioctl_getsens),
-       STD_IW_HANDLER(SIOCGIWRANGE,    orinoco_ioctl_getiwrange),
+       STD_IW_HANDLER(SIOCGIWRANGE,    cfg80211_wext_giwrange),
        STD_IW_HANDLER(SIOCSIWSPY,      iw_handler_set_spy),
        STD_IW_HANDLER(SIOCGIWSPY,      iw_handler_get_spy),
        STD_IW_HANDLER(SIOCSIWTHRSPY,   iw_handler_set_thrspy),
        STD_IW_HANDLER(SIOCGIWTHRSPY,   iw_handler_get_thrspy),
        STD_IW_HANDLER(SIOCSIWAP,       orinoco_ioctl_setwap),
        STD_IW_HANDLER(SIOCGIWAP,       orinoco_ioctl_getwap),
-       STD_IW_HANDLER(SIOCSIWSCAN,     orinoco_ioctl_setscan),
-       STD_IW_HANDLER(SIOCGIWSCAN,     orinoco_ioctl_getscan),
+       STD_IW_HANDLER(SIOCSIWSCAN,     cfg80211_wext_siwscan),
+       STD_IW_HANDLER(SIOCGIWSCAN,     cfg80211_wext_giwscan),
        STD_IW_HANDLER(SIOCSIWESSID,    orinoco_ioctl_setessid),
        STD_IW_HANDLER(SIOCGIWESSID,    orinoco_ioctl_getessid),
-       STD_IW_HANDLER(SIOCSIWNICKN,    orinoco_ioctl_setnick),
-       STD_IW_HANDLER(SIOCGIWNICKN,    orinoco_ioctl_getnick),
        STD_IW_HANDLER(SIOCSIWRATE,     orinoco_ioctl_setrate),
        STD_IW_HANDLER(SIOCGIWRATE,     orinoco_ioctl_getrate),
        STD_IW_HANDLER(SIOCSIWRTS,      orinoco_ioctl_setrts),