diff options
author | David Kilroy <kilroyd@googlemail.com> | 2009-02-04 23:05:56 +0000 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-02-13 13:44:33 -0500 |
commit | cb1576a829826d56fab59e22aa3af8c5a7db9936 (patch) | |
tree | 9d5fcd385dc1e28e7ddb89412bbdfc433d23c769 | |
parent | 712a4342a0d89e855a03ba06fb11f7eb29456d45 (diff) |
orinoco: Move WEXT handlers into a separate file
No functional change.
Signed-off-by: David Kilroy <kilroyd@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/orinoco/Makefile | 2 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/main.c | 2355 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/main.h | 63 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/wext.c | 2325 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco/wext.h | 13 |
5 files changed, 2408 insertions, 2350 deletions
diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile index f40f54d31e5..431ba399a9f 100644 --- a/drivers/net/wireless/orinoco/Makefile +++ b/drivers/net/wireless/orinoco/Makefile @@ -1,7 +1,7 @@ # # Makefile for the orinoco wireless device drivers. # -orinoco-objs := main.o fw.o hw.o mic.o scan.o +orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o obj-$(CONFIG_HERMES) += orinoco.o hermes.o hermes_dld.o obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c index a340c7d75dd..54dfc4540b8 100644 --- a/drivers/net/wireless/orinoco/main.c +++ b/drivers/net/wireless/orinoco/main.c @@ -95,6 +95,8 @@ #include "scan.h" #include "mic.h" #include "fw.h" +#include "wext.h" +#include "main.h" #include "orinoco.h" @@ -125,22 +127,11 @@ module_param(ignore_disconnect, int, 0644); MODULE_PARM_DESC(ignore_disconnect, "Don't report lost link to the network layer"); -static int force_monitor; /* = 0 */ +int force_monitor; /* = 0 */ module_param(force_monitor, int, 0644); MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); /********************************************************************/ -/* Compile time configuration and compatibility stuff */ -/********************************************************************/ - -/* We do this this way to avoid ifdefs in the actual code */ -#ifdef WIRELESS_SPY -#define SPY_NUMBER(priv) (priv->spy_data.spy_number) -#else -#define SPY_NUMBER(priv) 0 -#endif /* WIRELESS_SPY */ - -/********************************************************************/ /* Internal constants */ /********************************************************************/ @@ -170,9 +161,6 @@ static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; | HERMES_EV_WTERR | HERMES_EV_INFO \ | HERMES_EV_INFDROP) -#define MAX_RID_LEN 1024 - -static const struct iw_handler_def orinoco_handler_def; static const struct ethtool_ops orinoco_ethtool_ops; /********************************************************************/ @@ -221,14 +209,13 @@ struct orinoco_rx_data { /* Function prototypes */ /********************************************************************/ -static int __orinoco_program_rids(struct net_device *dev); static void __orinoco_set_multicast_list(struct net_device *dev); /********************************************************************/ /* Internal helper functions */ /********************************************************************/ -static inline void set_port_type(struct orinoco_private *priv) +void set_port_type(struct orinoco_private *priv) { switch (priv->iw_mode) { case IW_MODE_INFRA: @@ -254,33 +241,6 @@ static inline void set_port_type(struct orinoco_private *priv) } } -static inline u8 *orinoco_get_ie(u8 *data, size_t len, - enum ieee80211_eid eid) -{ - u8 *p = data; - while ((p + 2) < (data + len)) { - if (p[0] == eid) - return p; - p += p[1] + 2; - } - return NULL; -} - -#define WPA_OUI_TYPE "\x00\x50\xF2\x01" -#define WPA_SELECTOR_LEN 4 -static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len) -{ - u8 *p = data; - while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) { - if ((p[0] == WLAN_EID_GENERIC) && - (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0)) - return p; - p += p[1] + 2; - } - return NULL; -} - - /********************************************************************/ /* Device methods */ /********************************************************************/ @@ -330,68 +290,6 @@ static struct net_device_stats *orinoco_get_stats(struct net_device *dev) return &priv->stats; } -static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - struct iw_statistics *wstats = &priv->wstats; - int err; - unsigned long flags; - - if (!netif_device_present(dev)) { - printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n", - dev->name); - return NULL; /* FIXME: Can we do better than this? */ - } - - /* If busy, return the old stats. Returning NULL may cause - * the interface to disappear from /proc/net/wireless */ - if (orinoco_lock(priv, &flags) != 0) - return wstats; - - /* We can't really wait for the tallies inquiry command to - * complete, so we just use the previous results and trigger - * a new tallies inquiry command for next time - Jean II */ - /* FIXME: Really we should wait for the inquiry to come back - - * as it is the stats we give don't make a whole lot of sense. - * Unfortunately, it's not clear how to do that within the - * wireless extensions framework: I think we're in user - * context, but a lock seems to be held by the time we get in - * here so we're not safe to sleep here. */ - hermes_inquire(hw, HERMES_INQ_TALLIES); - - if (priv->iw_mode == IW_MODE_ADHOC) { - memset(&wstats->qual, 0, sizeof(wstats->qual)); - /* If a spy address is defined, we report stats of the - * first spy address - Jean II */ - if (SPY_NUMBER(priv)) { - wstats->qual.qual = priv->spy_data.spy_stat[0].qual; - wstats->qual.level = priv->spy_data.spy_stat[0].level; - wstats->qual.noise = priv->spy_data.spy_stat[0].noise; - wstats->qual.updated = - priv->spy_data.spy_stat[0].updated; - } - } else { - struct { - __le16 qual, signal, noise, unused; - } __attribute__ ((packed)) cq; - - err = HERMES_READ_RECORD(hw, USER_BAP, - HERMES_RID_COMMSQUALITY, &cq); - - if (!err) { - wstats->qual.qual = (int)le16_to_cpu(cq.qual); - wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; - wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; - wstats->qual.updated = - IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - } - } - - orinoco_unlock(priv, &flags); - return wstats; -} - static void orinoco_set_multicast_list(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); @@ -1716,7 +1614,7 @@ int orinoco_reinit_firmware(struct net_device *dev) } EXPORT_SYMBOL(orinoco_reinit_firmware); -static int __orinoco_program_rids(struct net_device *dev) +int __orinoco_program_rids(struct net_device *dev) { struct orinoco_private *priv = netdev_priv(dev); hermes_t *hw = &priv->hw; @@ -1970,7 +1868,7 @@ __orinoco_set_multicast_list(struct net_device *dev) /* This must be called from user context, without locks held - use * schedule_work() */ -static void orinoco_reset(struct work_struct *work) +void orinoco_reset(struct work_struct *work) { struct orinoco_private *priv = container_of(work, struct orinoco_private, reset_work); @@ -2711,2247 +2609,6 @@ void free_orinocodev(struct net_device *dev) } EXPORT_SYMBOL(free_orinocodev); -/********************************************************************/ -/* 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); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Enable automatic roaming - no sanity checks are needed */ - if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || - memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { - priv->bssid_fixed = 0; - memset(priv->desired_bssid, 0, ETH_ALEN); - - /* "off" means keep existing connection */ - if (ap_addr->sa_data[0] == 0) { - __orinoco_hw_set_wap(priv); - err = 0; - } - goto out; - } - - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { - printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " - "support manual roaming\n", - dev->name); - err = -EOPNOTSUPP; - goto out; - } - - if (priv->iw_mode != IW_MODE_INFRA) { - printk(KERN_WARNING "%s: Manual roaming supported only in " - "managed mode\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Intersil firmware hangs without Desired ESSID */ - if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && - strlen(priv->desired_essid) == 0) { - printk(KERN_WARNING "%s: Desired ESSID must be set for " - "manual roaming\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Finally, enable manual roaming */ - priv->bssid_fixed = 1; - memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); - - out: - orinoco_unlock(priv, &flags); - return err; -} - -static int orinoco_ioctl_getwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - hermes_t *hw = &priv->hw; - int err = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - 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); - - 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); - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - int setindex = priv->tx_key; - int encode_alg = priv->encode_alg; - int restricted = priv->wep_restrict; - u16 xlen = 0; - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (!priv->has_wep) - return -EOPNOTSUPP; - - if (erq->pointer) { - /* We actually have a key to set - check its length */ - if (erq->length > LARGE_KEY_SIZE) - return -E2BIG; - - if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep) - return -E2BIG; - } - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Clear any TKIP key we have */ - if ((priv->has_wpa) && (priv->encode_alg == IW_ENCODE_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)) { - setindex = index; - encode_alg = IW_ENCODE_ALG_WEP; - } - } else { - /* Important note : if the user do "iwconfig eth0 enc off", - * we will arrive there with an index of -1. This is valid - * but need to be taken care off... Jean II */ - if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) { - if ((index != -1) || (erq->flags == 0)) { - err = -EINVAL; - goto out; - } - } else { - /* Set the index : Check that the key is valid */ - if (priv->keys[index].len == 0) { - err = -EINVAL; - goto out; - } - setindex = index; - } - } - - if (erq->flags & IW_ENCODE_DISABLED) - encode_alg = IW_ENCODE_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); - } - priv->tx_key = setindex; - - /* Try fast key change if connected and only keys are changed */ - if ((priv->encode_alg == encode_alg) && - (priv->wep_restrict == restricted) && - netif_carrier_ok(dev)) { - err = __orinoco_hw_setup_wepkeys(priv); - /* No need to commit if successful */ - goto out; - } - - priv->encode_alg = encode_alg; - priv->wep_restrict = restricted; - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getiwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *keybuf) -{ - struct orinoco_private *priv = netdev_priv(dev); - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - u16 xlen = 0; - unsigned long flags; - - if (!priv->has_wep) - return -EOPNOTSUPP; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) - index = priv->tx_key; - - erq->flags = 0; - if (!priv->encode_alg) - erq->flags |= IW_ENCODE_DISABLED; - erq->flags |= index + 1; - - if (priv->wep_restrict) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - xlen = le16_to_cpu(priv->keys[index].len); - - erq->length = xlen; - - memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE); - - orinoco_unlock(priv, &flags); - return 0; -} - -static int orinoco_ioctl_setessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) -{ - struct orinoco_private *priv = netdev_priv(dev); - unsigned long flags; - - /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it - * anyway... - Jean II */ - - /* Hum... Should not use Wireless Extension constant (may change), - * should use our own... - Jean II */ - if (erq->length > IW_ESSID_MAX_SIZE) - return -E2BIG; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ - memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); - - /* If not ANY, get the new ESSID */ - if (erq->flags) - memcpy(priv->desired_essid, essidbuf, erq->length); - - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) -{ - struct orinoco_private *priv = netdev_priv(dev); - int active; - int err = 0; - unsigned long flags; - - if (netif_running(dev)) { - err = orinoco_hw_get_essid(priv, &active, essidbuf); - if (err < 0) - return err; - erq->length = err; - } else { - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE); - erq->length = strlen(priv->desired_essid); - orinoco_unlock(priv, &flags); - } - - erq->flags = 1; - - 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); - 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) - return -EBUSY; - - if ((frq->e == 0) && (frq->m <= 1000)) { - /* Setting by channel number */ - chan = frq->m; - } else { - /* Setting by frequency */ - int denom = 1; - int i; - - /* Calculate denominator to rescale to MHz */ - for (i = 0; i < (6 - frq->e); i++) - denom *= 10; - - chan = ieee80211_freq_to_dsss_chan(frq->m / denom); - } - - if ((chan < 1) || (chan > NUM_CHANNELS) || - !(priv->channel_mask & (1 << (chan-1)))) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->channel = chan; - if (priv->iw_mode == IW_MODE_MONITOR) { - /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_SET_CHANNEL, - chan, NULL); - } - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *frq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int tmp; - - /* Locking done in there */ - tmp = orinoco_hw_get_freq(priv); - if (tmp < 0) - return tmp; - - frq->m = tmp * 100000; - frq->e = 1; - - return 0; -} - -static int orinoco_ioctl_getsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - u16 val; - int err; - unsigned long flags; - - if (!priv->has_sensitivity) - return -EOPNOTSUPP; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFSYSTEMSCALE, &val); - orinoco_unlock(priv, &flags); - - if (err) - return err; - - srq->value = val; - srq->fixed = 0; /* auto */ - - return 0; -} - -static int orinoco_ioctl_setsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int val = srq->value; - unsigned long flags; - - if (!priv->has_sensitivity) - return -EOPNOTSUPP; - - if ((val < 1) || (val > 3)) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - priv->ap_density = val; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_setrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int val = rrq->value; - unsigned long flags; - - if (rrq->disabled) - val = 2347; - - if ((val < 0) || (val > 2347)) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->rts_thresh = val; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - - rrq->value = priv->rts_thresh; - rrq->disabled = (rrq->value == 2347); - rrq->fixed = 1; - - return 0; -} - -static int orinoco_ioctl_setfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - if (frq->disabled) - priv->mwo_robust = 0; - else { - if (frq->fixed) - printk(KERN_WARNING "%s: Fixed fragmentation " - "is not supported on this firmware. " - "Using MWO robust instead.\n", - dev->name); - priv->mwo_robust = 1; - } - } else { - if (frq->disabled) - priv->frag_thresh = 2346; - else { - if ((frq->value < 256) || (frq->value > 2346)) - err = -EINVAL; - else - /* must be even */ - priv->frag_thresh = frq->value & ~0x1; - } - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - int err; - u16 val; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - &val); - if (err) - val = 0; - - frq->value = val ? 2347 : 0; - frq->disabled = !val; - frq->fixed = 0; - } else { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - &val); - if (err) - val = 0; - - frq->value = val; - frq->disabled = (val >= 2346); - frq->fixed = 1; - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_setrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int ratemode; - int bitrate; /* 100s of kilobits */ - unsigned long flags; - - /* As the user space doesn't know our highest rate, it uses -1 - * to ask us to set the highest rate. Test it using "iwconfig - * ethX rate auto" - Jean II */ - if (rrq->value == -1) - bitrate = 110; - else { - if (rrq->value % 100000) - return -EINVAL; - bitrate = rrq->value / 100000; - } - - ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed); - - if (ratemode == -1) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - priv->bitratemode = ratemode; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; -} - -static int orinoco_ioctl_getrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = 0; - int bitrate, automatic; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic); - - /* If the interface is running we try to find more about the - current mode */ - if (netif_running(dev)) - err = orinoco_hw_get_act_bitrate(priv, &bitrate); - - orinoco_unlock(priv, &flags); - - rrq->value = bitrate; - rrq->fixed = !automatic; - rrq->disabled = 0; - - return err; -} - -static int orinoco_ioctl_setpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (prq->disabled) { - priv->pm_on = 0; - } else { - switch (prq->flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - priv->pm_mcast = 0; - priv->pm_on = 1; - break; - case IW_POWER_ALL_R: - priv->pm_mcast = 1; - priv->pm_on = 1; - break; - case IW_POWER_ON: - /* No flags : but we may have a value - Jean II */ - break; - default: - err = -EINVAL; - goto out; - } - - if (prq->flags & IW_POWER_TIMEOUT) { - priv->pm_on = 1; - priv->pm_timeout = prq->value / 1000; - } - if (prq->flags & IW_POWER_PERIOD) { - priv->pm_on = 1; - priv->pm_period = prq->value / 1000; - } - /* It's valid to not have a value if we are just toggling - * the flags... Jean II */ - if (!priv->pm_on) { - err = -EINVAL; - goto out; - } - } - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) -{ - struct orinoco_private *priv = netdev_priv(dev); - hermes_t *hw = &priv->hw; - int err = 0; - u16 enable, period, timeout, mcast; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMENABLED, &enable); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMAXSLEEPDURATION, &period); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMHOLDOVERDURATION, &timeout); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMULTICASTRECEIVE, &mcast); - if (err) - goto out; - - prq->disabled = !enable; - /* Note : by default, display the period */ - if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - prq->flags = IW_POWER_TIMEOUT; - prq->value = timeout * 1000; - } else { - prq->flags = IW_POWER_PERIOD; - prq->value = period * 1000; - } - if (mcast) - prq->flags |= IW_POWER_ALL_R; - else - prq->flags |= IW_POWER_UNICAST_R; - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct orinoco_private *priv = netdev_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; - - /* Determine and validate the key index */ - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if ((idx < 1) || (idx > 4)) - goto out; - idx--; - } else - idx = priv->tx_key; - - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) { - /* Clear any TKIP TX key we had */ - (void) orinoco_clear_tkip_key(priv, priv->tx_key); - } - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - priv->tx_key = idx; - set_key = ((alg == IW_ENCODE_ALG_TKIP) || - (ext->key_len > 0)) ? 1 : 0; - } - - if ( |