diff -u -p linux/include/linux/wireless.25.h linux/include/linux/wireless.h --- linux/include/linux/wireless.25.h Wed Mar 28 10:33:47 2001 +++ linux/include/linux/wireless.h Wed Mar 28 17:31:42 2001 @@ -1,7 +1,7 @@ /* * This file define a set of standard wireless extensions * - * Version : 9 16.10.99 + * Version : 11 28.3.01 * * Authors : Jean Tourrilhes - HPL - */ @@ -63,7 +63,7 @@ * (there is some stuff that will be added in the future...) * I just plan to increment with each new version. */ -#define WIRELESS_EXT 10 +#define WIRELESS_EXT 11 /* * Changes : @@ -111,6 +111,11 @@ * - Add PM modifier : MAX/MIN/RELATIVE * - Add encoding option : IW_ENCODE_NOKEY * - Add TxPower ioctls (work like TxRate) + * + * V10 to V11 + * ---------- + * - Add WE version in range (help backward/forward compatibility) + * - Add retry ioctls (work like PM) */ /* -------------------------- IOCTL LIST -------------------------- */ @@ -162,6 +167,8 @@ #define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ #define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ #define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ +#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ +#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ /* Encoding stuff (scrambling, hardware security, WEP...) */ #define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ @@ -272,6 +279,16 @@ #define IW_TXPOW_DBM 0x0000 /* Value is in dBm */ #define IW_TXPOW_MWATT 0x0001 /* Value is in mW */ +/* Retry limits and lifetime flags available */ +#define IW_RETRY_ON 0x0000 /* No details... */ +#define IW_RETRY_TYPE 0xF000 /* Type of parameter */ +#define IW_RETRY_LIMIT 0x1000 /* Maximum number of retries*/ +#define IW_RETRY_LIFETIME 0x2000 /* Maximum duration of retries in us */ +#define IW_RETRY_MODIFIER 0x000F /* Modify a parameter */ +#define IW_RETRY_MIN 0x0001 /* Value is a minimum */ +#define IW_RETRY_MAX 0x0002 /* Value is a maximum */ +#define IW_RETRY_RELATIVE 0x0004 /* Value is not in seconds/ms/us */ + /****************************** TYPES ******************************/ /* --------------------------- SUBTYPES --------------------------- */ @@ -385,6 +402,7 @@ struct iwreq struct iw_param rts; /* RTS threshold threshold */ struct iw_param frag; /* Fragmentation threshold */ __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ struct iw_point encoding; /* Encoding stuff : tokens */ struct iw_param power; /* PM duration/timeout */ @@ -462,6 +480,19 @@ struct iw_range __u16 txpower_capa; /* What options are supported */ __u8 num_txpower; /* Number of entries in the list */ __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ + + /* Wireless Extension version info */ + __u8 we_version_compiled; /* Must be WIRELESS_EXT */ + __u8 we_version_source; /* Last update of source */ + + /* Retry limits and lifetime */ + __u16 retry_capa; /* What retry options are supported */ + __u16 retry_flags; /* How to decode max/min retry limit */ + __u16 r_time_flags; /* How to decode max/min retry life */ + __s32 min_retry; /* Minimal number of retries */ + __s32 max_retry; /* Maximal number of retries */ + __s32 min_r_time; /* Minimal retry lifetime */ + __s32 max_r_time; /* Maximal retry lifetime */ }; /* diff -u -p linux/drivers/net/wireless.25/wavelan.c linux/drivers/net/wavelan.c --- linux/drivers/net/wireless.25/wavelan.c Wed Mar 28 17:27:27 2001 +++ linux/drivers/net/wavelan.c Wed Mar 28 17:28:34 2001 @@ -2028,8 +2028,17 @@ static int wavelan_ioctl(struct net_devi if (wrq->u.data.pointer != (caddr_t) 0) { struct iw_range range; - /* Set the length (useless: it's constant). */ + /* Set the length (very important for backward + * compatibility) */ wrq->u.data.length = sizeof(struct iw_range); + + /* Set all the info we don't care or don't know + * about to zero */ + memset(&range, 0, sizeof(range)); + + /* Set the Wireless Extension versions */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 9; /* Set information in the range struct. */ range.throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */ diff -u -p linux/drivers/net/pcmcia/wireless.25/wavelan_cs.c linux/drivers/net/pcmcia/wavelan_cs.c --- linux/drivers/net/pcmcia/wireless.25/wavelan_cs.c Wed Mar 28 17:21:02 2001 +++ linux/drivers/net/pcmcia/wavelan_cs.c Wed Mar 28 17:23:19 2001 @@ -2233,8 +2233,15 @@ wavelan_ioctl(struct net_device * dev, / { struct iw_range range; - /* Set the length (useless : its constant...) */ + /* Set the length (very important for backward compatibility) */ wrq->u.data.length = sizeof(struct iw_range); + + /* Set all the info we don't care or don't know about to zero */ + memset(&range, 0, sizeof(range)); + + /* Set the Wireless Extension versions */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 9; /* Nothing for us in v10 and v11 */ /* Set information in the range struct */ range.throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */ diff -u -p linux/drivers/net/pcmcia/wireless.25/netwave_cs.c linux/drivers/net/pcmcia/netwave_cs.c --- linux/drivers/net/pcmcia/wireless.25/netwave_cs.c Wed Mar 28 17:24:40 2001 +++ linux/drivers/net/pcmcia/netwave_cs.c Wed Mar 28 17:29:39 2001 @@ -710,8 +710,17 @@ static int netwave_ioctl(struct net_devi if(wrq->u.data.pointer != (caddr_t) 0) { struct iw_range range; - /* Set the length (useless : its constant...) */ + /* Set the length (very important for backward compatibility) */ wrq->u.data.length = sizeof(struct iw_range); + + /* Set all the info we don't care or don't know about to zero */ + memset(&range, 0, sizeof(range)); + +#if WIRELESS_EXT > 10 + /* Set the Wireless Extension versions */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 9; /* Nothing for us in v10 and v11 */ +#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct */ range.throughput = 450 * 1000; /* don't argue on this ! */ diff -u -p linux/drivers/net/pcmcia/wireless.25/ray_cs.c linux/drivers/net/pcmcia/ray_cs.c --- linux/drivers/net/pcmcia/wireless.25/ray_cs.c Wed Mar 28 17:21:57 2001 +++ linux/drivers/net/pcmcia/ray_cs.c Wed Mar 28 17:30:16 2001 @@ -1332,8 +1332,14 @@ static int ray_dev_ioctl(struct net_devi struct iw_range range; memset((char *) &range, 0, sizeof(struct iw_range)); - /* Set the length (useless : its constant...) */ + /* Set the length (very important for backward compatibility) */ wrq->u.data.length = sizeof(struct iw_range); + +#if WIRELESS_EXT > 10 + /* Set the Wireless Extension versions */ + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 9; +#endif /* WIRELESS_EXT > 10 */ /* Set information in the range struct */ range.throughput = 1.1 * 1000 * 1000; /* Put the right number here */ diff -u -p linux/drivers/net/pcmcia/wireless.25/hermes.h linux/drivers/net/pcmcia/hermes.h --- linux/drivers/net/pcmcia/wireless.25/hermes.h Wed Mar 28 10:31:35 2001 +++ linux/drivers/net/pcmcia/hermes.h Wed Mar 28 10:43:20 2001 @@ -196,6 +196,9 @@ #define HERMES_RID_CURRENT_BSSID ((uint16_t)0xfd42) #define HERMES_RID_COMMSQUALITY ((uint16_t)0xfd43) #define HERMES_RID_CURRENT_TX_RATE ((uint16_t)0xfd44) +#define HERMES_RID_SHORT_RETRY_LIMIT ((uint16_t)0xfd48) +#define HERMES_RID_LONG_RETRY_LIMIT ((uint16_t)0xfd49) +#define HERMES_RID_MAX_TX_LIFETIME ((uint16_t)0xfd4A) #define HERMES_RID_WEP_AVAIL ((uint16_t)0xfd4f) #define HERMES_RID_CURRENT_CHANNEL ((uint16_t)0xfdc1) #define HERMES_RID_DATARATES ((uint16_t)0xfdc6) diff -u -p linux/drivers/net/pcmcia/wireless.25/orinoco_cs.c linux/drivers/net/pcmcia/orinoco_cs.c --- linux/drivers/net/pcmcia/wireless.25/orinoco_cs.c Wed Mar 28 10:31:35 2001 +++ linux/drivers/net/pcmcia/orinoco_cs.c Wed Mar 28 17:16:36 2001 @@ -239,6 +239,7 @@ typedef struct dldwd_priv { int has_wep, has_big_wep; int has_mwo; int has_pm; + int has_retry; int broken_reset, broken_allocate; uint16_t channel_mask; @@ -254,6 +255,7 @@ typedef struct dldwd_priv { uint16_t ap_density, rts_thresh; uint16_t tx_rate_ctrl; uint16_t pm_on, pm_mcast, pm_period, pm_timeout; + uint16_t retry_short, retry_long, retry_time; int promiscuous, allmulti, mc_count; @@ -645,6 +647,24 @@ ESSID in IBSS-Ad-Hoc mode.\n", dev->name goto out; } + /* Set retry settings - will fail on lot's of firmwares */ + if (priv->has_retry) { + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, + priv->retry_short); + if (err) { + printk(KERN_WARNING "%s: Can't set retry limit!\n", dev->name); + goto out; + } + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, + priv->retry_long); + if (err) + goto out; + err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, + priv->retry_time); + if (err) + goto out; + } + /* Set promiscuity / multicast*/ priv->promiscuous = 0; priv->allmulti = 0; @@ -1267,6 +1287,7 @@ static int dldwd_init(struct net_device Gold cards from the others? */ priv->has_mwo = (firmver >= 0x60000); priv->has_pm = (firmver >= 0x40020); + priv->has_retry = 0; /* Tested with Lucent firmware : * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 => Jean II * Tested CableTron firmware : 4.32 => Anton */ @@ -1285,6 +1306,7 @@ static int dldwd_init(struct net_device priv->has_big_wep = 1; priv->has_mwo = 0; priv->has_pm = (firmver >= 0x20000); + priv->has_retry = 0; /* Tested with Intel firmware : 1.01 => Jean II */ /* Note : firmware 1.01 is *seriously* broken */ break; @@ -1301,6 +1323,7 @@ static int dldwd_init(struct net_device priv->has_big_wep = 0; /* FIXME */ priv->has_mwo = 0; priv->has_pm = (firmver >= 0x20000); /* FIXME */ + priv->has_retry = 0; break; case 0x6: vendor_str = "LinkSys/D-Link"; @@ -1315,6 +1338,7 @@ static int dldwd_init(struct net_device priv->has_big_wep = 0; priv->has_mwo = 0; priv->has_pm = (firmver >= 0x20000); /* FIXME */ + priv->has_retry = 0; break; #if 0 case 0x???: /* Could someone help here ??? */ @@ -1330,6 +1354,7 @@ static int dldwd_init(struct net_device priv->has_big_wep = 1; /* Probably RID_SYMBOL_KEY_LENGTH */ priv->has_mwo = 0; priv->has_pm = (firmver >= 0x20000); + priv->has_retry = 0; break; #endif default: @@ -1344,6 +1369,7 @@ static int dldwd_init(struct net_device priv->has_big_wep = 0; priv->has_mwo = 0; priv->has_pm = 0; + priv->has_retry = 0; } printk(KERN_INFO "%s: Firmware ID %02X vendor 0x%x (%s) version %d.%02d\n", @@ -1453,6 +1479,21 @@ static int dldwd_init(struct net_device } } + /* Retry setup */ + if (priv->has_retry) { + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &priv->retry_short); + if (err) + goto out; + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, &priv->retry_long); + if (err) + goto out; + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, &priv->retry_time); + if (err) + goto out; + } + /* Set up the default configuration */ priv->iw_mode = IW_MODE_INFRA; /* By default use IEEE/IBSS ad-hoc mode if we have it */ @@ -1802,6 +1843,11 @@ static int dldwd_ioctl_getiwrange(struct /* Much of this shamelessly taken from wvlan_cs.c. No idea * what it all means -dgibson */ +#if WIRELESS_EXT > 10 + range.we_version_compiled = WIRELESS_EXT; + range.we_version_source = 11; +#endif /* WIRELESS_EXT > 10 */ + range.min_nwid = range.max_nwid = 0; /* We don't use nwids */ /* Set available channels/frequencies */ @@ -1881,6 +1927,16 @@ static int dldwd_ioctl_getiwrange(struct range.txpower[0] = 15; /* 15dBm */ range.txpower_capa = IW_TXPOW_DBM; +#if WIRELESS_EXT > 10 + 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; /* ??? */ +#endif /* WIRELESS_EXT > 10 */ + if (copy_to_user(rrq->pointer, &range, sizeof(range))) return -EFAULT; @@ -2520,6 +2576,92 @@ static int dldwd_ioctl_getpower(struct n return err; } +#if WIRELESS_EXT > 10 +static int dldwd_ioctl_setretry(struct net_device *dev, struct iw_param *rrq) +{ + dldwd_priv_t *priv = dev->priv; + int err = 0; + + + dldwd_lock(priv); + + if ((rrq->disabled) || (!priv->has_retry)){ + err = -EOPNOTSUPP; + goto out; + } else { + if (rrq->flags & IW_RETRY_LIMIT) { + if (rrq->flags & IW_RETRY_MAX) + priv->retry_long = rrq->value; + else if (rrq->flags & IW_RETRY_MIN) + priv->retry_short = rrq->value; + else { + /* No modifier : set both */ + priv->retry_long = rrq->value; + priv->retry_short = rrq->value; + } + } + if (rrq->flags & IW_RETRY_LIFETIME) { + priv->retry_time = rrq->value / 1000; + } + if ((rrq->flags & IW_RETRY_TYPE) == 0) { + err = -EINVAL; + goto out; + } + } + + out: + dldwd_unlock(priv); + + return err; +} + +static int dldwd_ioctl_getretry(struct net_device *dev, struct iw_param *rrq) +{ + dldwd_priv_t *priv = dev->priv; + hermes_t *hw = &priv->hw; + int err = 0; + uint16_t short_limit, long_limit, lifetime; + + dldwd_lock(priv); + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORT_RETRY_LIMIT, &short_limit); + if (err) + goto out; + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONG_RETRY_LIMIT, &long_limit); + if (err) + goto out; + + err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAX_TX_LIFETIME, &lifetime); + if (err) + goto out; + + rrq->disabled = 0; /* Can't be disabled */ + + /* Note : by default, display the retry number */ + if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { + rrq->flags = IW_RETRY_LIFETIME; + rrq->value = lifetime * 1000; /* ??? */ + } else { + /* By default, display the min number */ + if ((rrq->flags & IW_RETRY_MAX)) { + rrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; + rrq->value = long_limit; + } else { + rrq->flags = IW_RETRY_LIMIT; + rrq->value = short_limit; + if(short_limit != long_limit) + rrq->flags |= IW_RETRY_MIN; + } + } + + out: + dldwd_unlock(priv); + + return err; +} +#endif /* WIRELESS_EXT > 10 */ + static int dldwd_ioctl_setport3(struct net_device *dev, struct iwreq *wrq) { dldwd_priv_t *priv = dev->priv; @@ -2857,6 +2999,20 @@ static int dldwd_ioctl(struct net_device wrq->u.txpower.disabled = 0; wrq->u.txpower.flags = IW_TXPOW_DBM; break; + +#if WIRELESS_EXT > 10 + case SIOCSIWRETRY: + DEBUG(1, "%s: SIOCSIWRETRY\n", dev->name); + err = dldwd_ioctl_setretry(dev, &wrq->u.retry); + if (! err) + changed = 1; + break; + + case SIOCGIWRETRY: + DEBUG(1, "%s: SIOCGIWRETRY\n", dev->name); + err = dldwd_ioctl_getretry(dev, &wrq->u.retry); + break; +#endif /* WIRELESS_EXT > 10 */ case SIOCSIWSPY: DEBUG(1, "%s: SIOCSIWSPY\n", dev->name);