Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJean Tourrilhes <jt@hpl.hp.com>2002-02-20 21:53:35 -0500
committerJeff Garzik <jgarzik@mandrakesoft.com>2002-02-20 21:53:35 -0500
commita5220ff4a3485216fe2736fc3de00878baf62651 (patch)
treebacd0d12ebeb4405a3d0f5f93048eabf9e8a5963
parent74a4e27a139636ee49de5529ba00c513c74634f8 (diff)
Update (ancient) wireless net drivers netwave_cs, wavelan,
and wavelan_cs to new wireless API.
-rw-r--r--drivers/net/wireless/netwave_cs.c474
-rw-r--r--drivers/net/wireless/wavelan.c1104
-rw-r--r--drivers/net/wireless/wavelan.p.h15
-rw-r--r--drivers/net/wireless/wavelan_cs.c1646
-rw-r--r--drivers/net/wireless/wavelan_cs.p.h25
5 files changed, 2189 insertions, 1075 deletions
diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c
index 9823adc71276..d5f52f16ed8e 100644
--- a/drivers/net/wireless/netwave_cs.c
+++ b/drivers/net/wireless/netwave_cs.c
@@ -63,6 +63,9 @@
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h>
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif /* WIRELESS_EXT > 12 */
#endif
#include <pcmcia/version.h>
@@ -269,6 +272,16 @@ static dev_link_t *dev_list;
because they generally can't be allocated dynamically.
*/
+#if WIRELESS_EXT <= 12
+/* Wireless extensions backward compatibility */
+
+/* Part of iw_handler prototype we need */
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+
/* Wireless Extension Backward compatibility - Jean II
* If the new wireless device private ioctl range is not defined,
* default to standard device private ioctl range */
@@ -276,8 +289,11 @@ static dev_link_t *dev_list;
#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE
#endif /* SIOCIWFIRSTPRIV */
-#define SIOCGIPSNAP SIOCIWFIRSTPRIV /* Site Survey Snapshot */
-/*#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1*/
+#else /* WIRELESS_EXT <= 12 */
+static const struct iw_handler_def netwave_handler_def;
+#endif /* WIRELESS_EXT <= 12 */
+
+#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */
#define MAX_ESA 10
@@ -483,7 +499,10 @@ static dev_link_t *netwave_attach(void)
/* wireless extensions */
#ifdef WIRELESS_EXT
dev->get_wireless_stats = &netwave_get_wireless_stats;
-#endif
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = (struct iw_handler_def *)&netwave_handler_def;
+#endif /* WIRELESS_EXT > 12 */
+#endif /* WIRELESS_EXT */
dev->do_ioctl = &netwave_ioctl;
dev->tx_timeout = &netwave_watchdog;
@@ -596,6 +615,303 @@ static void netwave_flush_stale_links(void)
} /* netwave_flush_stale_links */
/*
+ * Wireless Handler : get protocol name
+ */
+static int netwave_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ strcpy(wrqu->name, "Netwave");
+ return 0;
+}
+
+/*
+ * Wireless Handler : set Network ID
+ */
+static int netwave_set_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long flags;
+ ioaddr_t iobase = dev->base_addr;
+ netwave_private *priv = (netwave_private *) dev->priv;
+ u_char *ramBase = priv->ramBase;
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+#if WIRELESS_EXT > 8
+ if(!wrqu->nwid.disabled) {
+ domain = wrqu->nwid.value;
+#else /* WIRELESS_EXT > 8 */
+ if(wrqu->nwid.on) {
+ domain = wrqu->nwid.nwid;
+#endif /* WIRELESS_EXT > 8 */
+ printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
+ (domain >> 8) & 0x01, domain & 0xff);
+ wait_WOC(iobase);
+ writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0);
+ writeb( domain & 0xff, ramBase + NETWAVE_EREG_CB + 1);
+ writeb((domain >>8 ) & 0x01,ramBase + NETWAVE_EREG_CB+2);
+ writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+ }
+
+ /* ReEnable interrupts & restore flags */
+ restore_flags(flags);
+
+ return 0;
+}
+
+/*
+ * Wireless Handler : get Network ID
+ */
+static int netwave_get_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+#if WIRELESS_EXT > 8
+ wrqu->nwid.value = domain;
+ wrqu->nwid.disabled = 0;
+ wrqu->nwid.fixed = 1;
+#else /* WIRELESS_EXT > 8 */
+ wrqu->nwid.nwid = domain;
+ wrqu->nwid.on = 1;
+#endif /* WIRELESS_EXT > 8 */
+
+ return 0;
+}
+
+/*
+ * Wireless Handler : set scramble key
+ */
+static int netwave_set_scramble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *key)
+{
+ unsigned long flags;
+ ioaddr_t iobase = dev->base_addr;
+ netwave_private *priv = (netwave_private *) dev->priv;
+ u_char *ramBase = priv->ramBase;
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+ scramble_key = (key[0] << 8) | key[1];
+ wait_WOC(iobase);
+ writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
+ writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
+ writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
+ writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+
+ /* ReEnable interrupts & restore flags */
+ restore_flags(flags);
+
+ return 0;
+}
+
+/*
+ * Wireless Handler : get scramble key
+ */
+static int netwave_get_scramble(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *key)
+{
+ key[1] = scramble_key & 0xff;
+ key[0] = (scramble_key>>8) & 0xff;
+#if WIRELESS_EXT > 8
+ wrqu->encoding.flags = IW_ENCODE_ENABLED;
+ wrqu->encoding.length = 2;
+#else /* WIRELESS_EXT > 8 */
+ wrqu->encoding.method = 1;
+#endif /* WIRELESS_EXT > 8 */
+
+ return 0;
+}
+
+#if WIRELESS_EXT > 8
+/*
+ * Wireless Handler : get mode
+ */
+static int netwave_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ if(domain & 0x100)
+ wrqu->mode = IW_MODE_INFRA;
+ else
+ wrqu->mode = IW_MODE_ADHOC;
+
+ return 0;
+}
+#endif /* WIRELESS_EXT > 8 */
+
+/*
+ * Wireless Handler : get range info
+ */
+static int netwave_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ struct iw_range *range = (struct iw_range *) extra;
+ int ret = 0;
+
+ /* Set the length (very important for backward compatibility) */
+ wrqu->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(struct iw_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 ! */
+ range->min_nwid = 0x0000;
+ range->max_nwid = 0x01FF;
+
+ range->num_channels = range->num_frequency = 0;
+
+ range->sensitivity = 0x3F;
+ range->max_qual.qual = 255;
+ range->max_qual.level = 255;
+ range->max_qual.noise = 0;
+
+#if WIRELESS_EXT > 7
+ range->num_bitrates = 1;
+ range->bitrate[0] = 1000000; /* 1 Mb/s */
+#endif /* WIRELESS_EXT > 7 */
+
+#if WIRELESS_EXT > 8
+ range->encoding_size[0] = 2; /* 16 bits scrambling */
+ range->num_encoding_sizes = 1;
+ range->max_encoding_tokens = 1; /* Only one key possible */
+#endif /* WIRELESS_EXT > 8 */
+
+ return ret;
+}
+
+/*
+ * Wireless Private Handler : get snapshot
+ */
+static int netwave_get_snap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long flags;
+ ioaddr_t iobase = dev->base_addr;
+ netwave_private *priv = (netwave_private *) dev->priv;
+ u_char *ramBase = priv->ramBase;
+
+ /* Disable interrupts & save flags */
+ save_flags(flags);
+ cli();
+
+ /* Take snapshot of environment */
+ netwave_snapshot( priv, ramBase, iobase);
+ wrqu->data.length = priv->nss.length;
+ memcpy(extra, (u_char *) &priv->nss, sizeof( struct site_survey));
+
+ priv->lastExec = jiffies;
+
+ /* ReEnable interrupts & restore flags */
+ restore_flags(flags);
+
+ return(0);
+}
+
+/*
+ * Structures to export the Wireless Handlers
+ * This is the stuff that are treated the wireless extensions (iwconfig)
+ */
+
+static const struct iw_priv_args netwave_private_args[] = {
+/*{ cmd, set_args, get_args, name } */
+ { SIOCGIPSNAP, 0,
+ IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(struct site_survey),
+ "getsitesurvey" },
+};
+
+#if WIRELESS_EXT > 12
+
+static const iw_handler netwave_handler[] =
+{
+ NULL, /* SIOCSIWNAME */
+ netwave_get_name, /* SIOCGIWNAME */
+ netwave_set_nwid, /* SIOCSIWNWID */
+ netwave_get_nwid, /* SIOCGIWNWID */
+ NULL, /* SIOCSIWFREQ */
+ NULL, /* SIOCGIWFREQ */
+ NULL, /* SIOCSIWMODE */
+ netwave_get_mode, /* SIOCGIWMODE */
+ NULL, /* SIOCSIWSENS */
+ NULL, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ netwave_get_range, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+ NULL, /* SIOCSIWSPY */
+ NULL, /* SIOCGIWSPY */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWAP */
+ NULL, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWESSID */
+ NULL, /* SIOCGIWESSID */
+ NULL, /* SIOCSIWNICKN */
+ NULL, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWRATE */
+ NULL, /* SIOCGIWRATE */
+ NULL, /* SIOCSIWRTS */
+ NULL, /* SIOCGIWRTS */
+ NULL, /* SIOCSIWFRAG */
+ NULL, /* SIOCGIWFRAG */
+ NULL, /* SIOCSIWTXPOW */
+ NULL, /* SIOCGIWTXPOW */
+ NULL, /* SIOCSIWRETRY */
+ NULL, /* SIOCGIWRETRY */
+ netwave_set_scramble, /* SIOCSIWENCODE */
+ netwave_get_scramble, /* SIOCGIWENCODE */
+};
+
+static const iw_handler netwave_private_handler[] =
+{
+ NULL, /* SIOCIWFIRSTPRIV */
+ netwave_get_snap, /* SIOCIWFIRSTPRIV + 1 */
+};
+
+static const struct iw_handler_def netwave_handler_def =
+{
+ num_standard: sizeof(netwave_handler)/sizeof(iw_handler),
+ num_private: sizeof(netwave_private_handler)/sizeof(iw_handler),
+ num_private_args: sizeof(netwave_private_args)/sizeof(struct iw_priv_args),
+ standard: (iw_handler *) netwave_handler,
+ private: (iw_handler *) netwave_private_handler,
+ private_args: (struct iw_priv_args *) netwave_private_args,
+};
+#endif /* WIRELESS_EXT > 12 */
+
+/*
* Function netwave_ioctl (dev, rq, cmd)
*
* Perform ioctl : config & info stuff
@@ -606,56 +922,28 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
struct ifreq *rq, /* Data passed */
int cmd) /* Ioctl number */
{
- unsigned long flags;
int ret = 0;
#ifdef WIRELESS_EXT
- ioaddr_t iobase = dev->base_addr;
- netwave_private *priv = (netwave_private *) dev->priv;
- u_char *ramBase = priv->ramBase;
+#if WIRELESS_EXT <= 12
struct iwreq *wrq = (struct iwreq *) rq;
#endif
+#endif
DEBUG(0, "%s: ->netwave_ioctl(cmd=0x%X)\n", dev->name, cmd);
- /* Disable interrupts & save flags */
- save_flags(flags);
- cli();
-
/* Look what is the request */
switch(cmd) {
/* --------------- WIRELESS EXTENSIONS --------------- */
#ifdef WIRELESS_EXT
+#if WIRELESS_EXT <= 12
case SIOCGIWNAME:
- /* Get name */
- strcpy(wrq->u.name, "Netwave");
+ netwave_get_name(dev, NULL, &(wrq->u), NULL);
break;
case SIOCSIWNWID:
- /* Set domain */
-#if WIRELESS_EXT > 8
- if(!wrq->u.nwid.disabled) {
- domain = wrq->u.nwid.value;
-#else /* WIRELESS_EXT > 8 */
- if(wrq->u.nwid.on) {
- domain = wrq->u.nwid.nwid;
-#endif /* WIRELESS_EXT > 8 */
- printk( KERN_DEBUG "Setting domain to 0x%x%02x\n",
- (domain >> 8) & 0x01, domain & 0xff);
- wait_WOC(iobase);
- writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0);
- writeb( domain & 0xff, ramBase + NETWAVE_EREG_CB + 1);
- writeb((domain >>8 ) & 0x01,ramBase + NETWAVE_EREG_CB+2);
- writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
- } break;
+ ret = netwave_set_nwid(dev, NULL, &(wrq->u), NULL);
+ break;
case SIOCGIWNWID:
- /* Read domain*/
-#if WIRELESS_EXT > 8
- wrq->u.nwid.value = domain;
- wrq->u.nwid.disabled = 0;
- wrq->u.nwid.fixed = 1;
-#else /* WIRELESS_EXT > 8 */
- wrq->u.nwid.nwid = domain;
- wrq->u.nwid.on = 1;
-#endif /* WIRELESS_EXT > 8 */
+ ret = netwave_get_nwid(dev, NULL, &(wrq->u), NULL);
break;
#if WIRELESS_EXT > 8 /* Note : The API did change... */
case SIOCGIWENCODE:
@@ -663,10 +951,7 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
if(wrq->u.encoding.pointer != (caddr_t) 0)
{
char key[2];
- key[1] = scramble_key & 0xff;
- key[0] = (scramble_key>>8) & 0xff;
- wrq->u.encoding.flags = IW_ENCODE_ENABLED;
- wrq->u.encoding.length = 2;
+ ret = netwave_get_scramble(dev, NULL, &(wrq->u), key);
if(copy_to_user(wrq->u.encoding.pointer, key, 2))
ret = -EFAULT;
}
@@ -681,127 +966,68 @@ static int netwave_ioctl(struct net_device *dev, /* ioctl device */
ret = -EFAULT;
break;
}
- scramble_key = (key[0] << 8) | key[1];
- wait_WOC(iobase);
- writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
- writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
- writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
- writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+ ret = netwave_set_scramble(dev, NULL, &(wrq->u), key);
}
break;
case SIOCGIWMODE:
- /* Mode of operation */
- if(domain & 0x100)
- wrq->u.mode = IW_MODE_INFRA;
- else
- wrq->u.mode = IW_MODE_ADHOC;
- break;
+ /* Mode of operation */
+ ret = netwave_get_mode(dev, NULL, &(wrq->u), NULL);
+ break;
#else /* WIRELESS_EXT > 8 */
case SIOCGIWENCODE:
/* Get scramble key */
- wrq->u.encoding.code = scramble_key;
- wrq->u.encoding.method = 1;
+ ret = netwave_get_scramble(dev, NULL, &(wrq->u),
+ (char *) &wrq->u.encoding.code);
break;
case SIOCSIWENCODE:
/* Set scramble key */
- scramble_key = wrq->u.encoding.code;
- wait_WOC(iobase);
- writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0);
- writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1);
- writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2);
- writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3);
+ ret = netwave_set_scramble(dev, NULL, &(wrq->u),
+ (char *) &wrq->u.encoding.code);
break;
#endif /* WIRELESS_EXT > 8 */
case SIOCGIWRANGE:
/* Basic checking... */
if(wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_range range;
-
- /* 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 ! */
- range.min_nwid = 0x0000;
- range.max_nwid = 0x01FF;
-
- range.num_channels = range.num_frequency = 0;
-
- range.sensitivity = 0x3F;
- range.max_qual.qual = 255;
- range.max_qual.level = 255;
- range.max_qual.noise = 0;
-
-#if WIRELESS_EXT > 7
- range.num_bitrates = 1;
- range.bitrate[0] = 1000000; /* 1 Mb/s */
-#endif /* WIRELESS_EXT > 7 */
-
-#if WIRELESS_EXT > 8
- range.encoding_size[0] = 2; /* 16 bits scrambling */
- range.num_encoding_sizes = 1;
- range.max_encoding_tokens = 1; /* Only one key possible */
-#endif /* WIRELESS_EXT > 8 */
-
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- ret = -EFAULT;
+ struct iw_range range;
+ ret = netwave_get_range(dev, NULL, &(wrq->u), (char *) &range);
+ if (copy_to_user(wrq->u.data.pointer, &range,
+ sizeof(struct iw_range)))
+ ret = -EFAULT;
}
break;
case SIOCGIWPRIV:
/* Basic checking... */
if(wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_priv_args priv[] =
- { /* cmd, set_args, get_args, name */
- { SIOCGIPSNAP, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 0,
- sizeof(struct site_survey),
- "getsitesurvey" },
- };
-
/* Set the number of ioctl available */
- wrq->u.data.length = 1;
+ wrq->u.data.length = sizeof(netwave_private_args) / sizeof(netwave_private_args[0]);
/* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
- sizeof(priv)))
+ if(copy_to_user(wrq->u.data.pointer,
+ (u_char *) netwave_private_args,
+ sizeof(netwave_private_args)))
ret = -EFAULT;
}
break;
case SIOCGIPSNAP:
if(wrq->u.data.pointer != (caddr_t) 0) {
- /* Take snapshot of environment */
- netwave_snapshot( priv, ramBase, iobase);
- wrq->u.data.length = priv->nss.length;
+ char buffer[sizeof( struct site_survey)];
+ ret = netwave_get_snap(dev, NULL, &(wrq->u), buffer);
/* Copy structure to the user buffer */
if(copy_to_user(wrq->u.data.pointer,
- (u_char *) &priv->nss,
- sizeof( struct site_survey)))
+ buffer,
+ sizeof( struct site_survey)))
{
printk(KERN_DEBUG "Bad buffer!\n");
break;
}
-
- priv->lastExec = jiffies;
}
break;
-#endif
+#endif /* WIRELESS_EXT <= 12 */
+#endif /* WIRELESS_EXT */
default:
ret = -EOPNOTSUPP;
}
- /* ReEnable interrupts & restore flags */
- restore_flags(flags);
-
return ret;
}
diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c
index 10805eff7113..b35567e8c577 100644
--- a/drivers/net/wireless/wavelan.c
+++ b/drivers/net/wireless/wavelan.c
@@ -1786,170 +1786,287 @@ static inline void wl_his_gather(device * dev, u8 * stats)
/*------------------------------------------------------------------*/
/*
- * Perform ioctl for configuration and information.
- * It is here that the wireless extensions are treated (iwconfig).
+ * Wireless Handler : get protocol name
*/
-static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is applied */
- struct ifreq *rq, /* data passed */
- int cmd)
-{ /* ioctl number */
+static int wavelan_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ strcpy(wrqu->name, "WaveLAN");
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set NWID
+ */
+static int wavelan_set_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
unsigned long ioaddr = dev->base_addr;
net_local *lp = (net_local *) dev->priv; /* lp is not unused */
- struct iwreq *wrq = (struct iwreq *) rq;
psa_t psa;
mm_t m;
unsigned long flags;
int ret = 0;
- int err = 0;
-#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name,
- cmd);
-#endif
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Set NWID in WaveLAN. */
+ if (!wrqu->nwid.disabled) {
+ /* Set NWID in psa */
+ psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;
+ psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;
+ psa.psa_nwid_select = 0x01;
+ psa_write(ioaddr, lp->hacr,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
+
+ /* Set NWID in mmc. */
+ m.w.mmw_netw_id_l = psa.psa_nwid[1];
+ m.w.mmw_netw_id_h = psa.psa_nwid[0];
+ mmc_write(ioaddr,
+ (char *) &m.w.mmw_netw_id_l -
+ (char *) &m,
+ (unsigned char *) &m.w.mmw_netw_id_l, 2);
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
+ } else {
+ /* Disable NWID in the psa. */
+ psa.psa_nwid_select = 0x00;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_nwid_select -
+ (char *) &psa,
+ (unsigned char *) &psa.psa_nwid_select,
+ 1);
+
+ /* Disable NWID in the mmc (no filtering). */
+ mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
+ MMW_LOOPT_SEL_DIS_NWID);
+ }
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get NWID
+ */
+static int wavelan_get_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
/* Disable interrupts and save flags. */
wv_splhi(lp, &flags);
- /* Look what is the request */
- switch (cmd) {
- /* --------------- WIRELESS EXTENSIONS --------------- */
-
- case SIOCGIWNAME:
- strcpy(wrq->u.name, "WaveLAN");
- break;
-
- case SIOCSIWNWID:
- /* Set NWID in WaveLAN. */
- if (!wrq->u.nwid.disabled) {
- /* Set NWID in psa */
- psa.psa_nwid[0] =
- (wrq->u.nwid.value & 0xFF00) >> 8;
- psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
- psa.psa_nwid_select = 0x01;
- psa_write(ioaddr, lp->hacr,
- (char *) psa.psa_nwid - (char *) &psa,
- (unsigned char *) psa.psa_nwid, 3);
-
- /* Set NWID in mmc. */
- m.w.mmw_netw_id_l = psa.psa_nwid[1];
- m.w.mmw_netw_id_h = psa.psa_nwid[0];
- mmc_write(ioaddr,
- (char *) &m.w.mmw_netw_id_l -
- (char *) &m,
- (unsigned char *) &m.w.mmw_netw_id_l, 2);
- mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00);
- } else {
- /* Disable NWID in the psa. */
- psa.psa_nwid_select = 0x00;
- psa_write(ioaddr, lp->hacr,
- (char *) &psa.psa_nwid_select -
- (char *) &psa,
- (unsigned char *) &psa.psa_nwid_select,
- 1);
+ /* Read the NWID. */
+ psa_read(ioaddr, lp->hacr,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
+ wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+ wrqu->nwid.disabled = !(psa.psa_nwid_select);
+ wrqu->nwid.fixed = 1; /* Superfluous */
- /* Disable NWID in the mmc (no filtering). */
- mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel),
- MMW_LOOPT_SEL_DIS_NWID);
- }
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- case SIOCGIWNWID:
- /* Read the NWID. */
- psa_read(ioaddr, lp->hacr,
- (char *) psa.psa_nwid - (char *) &psa,
- (unsigned char *) psa.psa_nwid, 3);
- wrq->u.nwid.value =
- (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
- wrq->u.nwid.disabled = !(psa.psa_nwid_select);
- wrq->u.nwid.fixed = 1; /* Superfluous */
- break;
-
- case SIOCSIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
- if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- ret = wv_set_frequency(ioaddr, &(wrq->u.freq));
- else
- ret = -EOPNOTSUPP;
- break;
-
- case SIOCGIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
- * Does it work for everybody, especially old cards? */
- if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
- unsigned short freq;
-
- /* Ask the EEPROM to read the frequency from the first area. */
- fee_read(ioaddr, 0x00, &freq, 1);
- wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
- wrq->u.freq.e = 1;
- } else {
- psa_read(ioaddr, lp->hacr,
- (char *) &psa.psa_subband - (char *) &psa,
- (unsigned char *) &psa.psa_subband, 1);
-
- if (psa.psa_subband <= 4) {
- wrq->u.freq.m =
- fixed_bands[psa.psa_subband];
- wrq->u.freq.e = (psa.psa_subband != 0);
- } else
- ret = -EOPNOTSUPP;
- }
- break;
+ return ret;
+}
- case SIOCSIWSENS:
- /* Set the level threshold. */
- /* We should complain loudly if wrq->u.sens.fixed = 0, because we
- * can't set auto mode... */
- psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
- psa_write(ioaddr, lp->hacr,
- (char *) &psa.psa_thr_pre_set - (char *) &psa,
- (unsigned char *) &psa.psa_thr_pre_set, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
- psa.psa_thr_pre_set);
- break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int wavelan_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ int ret;
- case SIOCGIWSENS:
- /* Read the level threshold. */
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+ ret = wv_set_frequency(ioaddr, &(wrqu->freq));
+ else
+ ret = -EOPNOTSUPP;
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int wavelan_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+ * Does it work for everybody, especially old cards? */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ unsigned short freq;
+
+ /* Ask the EEPROM to read the frequency from the first area. */
+ fee_read(ioaddr, 0x00, &freq, 1);
+ wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+ wrqu->freq.e = 1;
+ } else {
psa_read(ioaddr, lp->hacr,
- (char *) &psa.psa_thr_pre_set - (char *) &psa,
- (unsigned char *) &psa.psa_thr_pre_set, 1);
- wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
- wrq->u.sens.fixed = 1;
- break;
-
- case SIOCSIWENCODE:
- /* Set encryption key */
- if (!mmc_encr(ioaddr)) {
+ (char *) &psa.psa_subband - (char *) &psa,
+ (unsigned char *) &psa.psa_subband, 1);
+
+ if (psa.psa_subband <= 4) {
+ wrqu->freq.m = fixed_bands[psa.psa_subband];
+ wrqu->freq.e = (psa.psa_subband != 0);
+ } else
ret = -EOPNOTSUPP;
- break;
- }
+ }
- /* Basic checking... */
- if (wrq->u.encoding.pointer != (caddr_t) 0) {
- /* Check the size of the key */
- if (wrq->u.encoding.length != 8) {
- ret = -EINVAL;
- break;
- }
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- /* Copy the key in the driver */
- wv_splx(lp, &flags);
- err = copy_from_user(psa.psa_encryption_key,
- wrq->u.encoding.pointer,
- wrq->u.encoding.length);
- wv_splhi(lp, &flags);
- if (err) {
- ret = -EFAULT;
- break;
- }
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set level threshold
+ */
+static int wavelan_set_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Set the level threshold. */
+ /* We should complain loudly if wrqu->sens.fixed = 0, because we
+ * can't set auto mode... */
+ psa.psa_thr_pre_set = wrqu->sens.value & 0x3F;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set),
+ psa.psa_thr_pre_set);
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get level threshold
+ */
+static int wavelan_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Read the level threshold. */
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ wrqu->sens.value = psa.psa_thr_pre_set & 0x3F;
+ wrqu->sens.fixed = 1;
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set encryption key
+ */
+static int wavelan_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ psa_t psa;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check if capable of encryption */
+ if (!mmc_encr(ioaddr)) {
+ ret = -EOPNOTSUPP;
+ }
+
+ /* Check the size of the key */
+ if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) {
+ ret = -EINVAL;
+ }
+
+ if(!ret) {
+ /* Basic checking... */
+ if (wrqu->encoding.length == 8) {
+ /* Copy the key in the driver */
+ memcpy(psa.psa_encryption_key, extra,
+ wrqu->encoding.length);
psa.psa_encryption_select = 1;
+
psa_write(ioaddr, lp->hacr,
(char *) &psa.psa_encryption_select -
(char *) &psa,
@@ -1963,7 +2080,8 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
psa_encryption_key, 8);
}
- if (wrq->u.encoding.flags & IW_ENCODE_DISABLED) { /* disable encryption */
+ /* disable encryption */
+ if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
psa.psa_encryption_select = 0;
psa_write(ioaddr, lp->hacr,
(char *) &psa.psa_encryption_select -
@@ -1975,350 +2093,430 @@ static int wavelan_ioctl(struct net_device *dev, /* device on which the ioctl is
}
/* update the Wavelan checksum */
update_psa_checksum(dev, ioaddr, lp->hacr);
- break;
+ }
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get encryption key
+ */
+static int wavelan_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
- case SIOCGIWENCODE:
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check if encryption is available */
+ if (!mmc_encr(ioaddr)) {
+ ret = -EOPNOTSUPP;
+ } else {
/* Read the encryption key */
- if (!mmc_encr(ioaddr)) {
- ret = -EOPNOTSUPP;
- break;
- }
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 1 + 8);
+
+ /* encryption is enabled ? */
+ if (psa.psa_encryption_select)
+ wrqu->encoding.flags = IW_ENCODE_ENABLED;
+ else
+ wrqu->encoding.flags = IW_ENCODE_DISABLED;
+ wrqu->encoding.flags |= mmc_encr(ioaddr);
- /* only super-user can see encryption key */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- break;
- }
+ /* Copy the key to the user buffer */
+ wrqu->encoding.length = 8;
+ memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length);
+ }
- /* Basic checking... */
- if (wrq->u.encoding.pointer != (caddr_t) 0) {
- /* Verify the user buffer */
- ret =
- verify_area(VERIFY_WRITE,
- wrq->u.encoding.pointer, 8);
- if (ret)
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- psa_read(ioaddr, lp->hacr,
- (char *) &psa.psa_encryption_select -
- (char *) &psa,
- (unsigned char *) &psa.
- psa_encryption_select, 1 + 8);
+ return ret;
+}
- /* encryption is enabled ? */
- if (psa.psa_encryption_select)
- wrq->u.encoding.flags = IW_ENCODE_ENABLED;
- else
- wrq->u.encoding.flags = IW_ENCODE_DISABLED;
- wrq->u.encoding.flags |= mmc_encr(ioaddr);
-
- /* Copy the key to the user buffer */
- wrq->u.encoding.length = 8;
- wv_splx(lp, &flags);
- if (copy_to_user(wrq->u.encoding.pointer,
- psa.psa_encryption_key, 8))
- ret = -EFAULT;
- wv_splhi(lp, &flags);
- }
- break;
-
- case SIOCGIWRANGE:
- /* basic checking */
- if (wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_range range;
-
- /* 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 ! */
- range.min_nwid = 0x0000;
- range.max_nwid = 0xFFFF;
-
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
- if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
- range.num_channels = 10;
- range.num_frequency =
- wv_frequency_list(ioaddr, range.freq,
- IW_MAX_FREQUENCIES);
- } else
- range.num_channels = range.num_frequency =
- 0;
-
- range.sensitivity = 0x3F;
- range.max_qual.qual = MMR_SGNL_QUAL;
- range.max_qual.level = MMR_SIGNAL_LVL;
- range.max_qual.noise = MMR_SILENCE_LVL;
- range.avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
- /* Need to get better values for those two */
- range.avg_qual.level = 30;
- range.avg_qual.noise = 8;
-
- range.num_bitrates = 1;
- range.bitrate[0] = 2000000; /* 2 Mb/s */
-
- /* Encryption supported ? */
- if (mmc_encr(ioaddr)) {
- range.encoding_size[0] = 8; /* DES = 64 bits key */
- range.num_encoding_sizes = 1;
- range.max_encoding_tokens = 1; /* Only one key possible */
- } else {
- range.num_encoding_sizes = 0;
- range.max_encoding_tokens = 0;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int wavelan_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct iw_range *range = (struct iw_range *) extra;
+ unsigned long flags;
+ int ret = 0;
- /* Copy structure to the user buffer. */
- wv_splx(lp, &flags);
- if (copy_to_user(wrq->u.data.pointer,
- &range,
- sizeof(struct iw_range)))
- ret = -EFAULT;
- wv_splhi(lp, &flags);
- }
- break;
-
- case SIOCGIWPRIV:
- /* Basic checking */
- if (wrq->u.data.pointer != (caddr_t) 0) {
- struct iw_priv_args priv[] = {
- /* { cmd,
- set_args,
- get_args,
- name } */
- { SIOCSIPQTHR,
- IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- 0,
- "setqualthr" },
- { SIOCGIPQTHR,
- 0,
- IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1,
- "getqualthr" },
- { SIOCSIPHISTO,
- IW_PRIV_TYPE_BYTE | 16,
- 0,
- "sethisto" },
- { SIOCGIPHISTO,
- 0,
- IW_PRIV_TYPE_INT | 16,
- "gethisto" },
- };
-
- /* Set the number of available ioctls. */
- wrq->u.data.length = 4;
-
- /* Copy structure to the user buffer. */
- wv_splx(lp, &flags);
- if (copy_to_user(wrq->u.data.pointer,
- (u8 *) priv,
- sizeof(priv)))
- ret = -EFAULT;
- wv_splhi(lp, &flags);
- }
- break;
+ /* Set the length (very important for backward compatibility) */
+ wrqu->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(struct iw_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 ! */
+ range->min_nwid = 0x0000;
+ range->max_nwid = 0xFFFF;
+
+ range->sensitivity = 0x3F;
+ range->max_qual.qual = MMR_SGNL_QUAL;
+ range->max_qual.level = MMR_SIGNAL_LVL;
+ range->max_qual.noise = MMR_SILENCE_LVL;
+ range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
+ /* Need to get better values for those two */
+ range->avg_qual.level = 30;
+ range->avg_qual.noise = 8;
+
+ range->num_bitrates = 1;
+ range->bitrate[0] = 2000000; /* 2 Mb/s */
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ range->num_channels = 10;
+ range->num_frequency = wv_frequency_list(ioaddr, range->freq,
+ IW_MAX_FREQUENCIES);
+ } else
+ range->num_channels = range->num_frequency = 0;
+
+ /* Encryption supported ? */
+ if (mmc_encr(ioaddr)) {
+ range->encoding_size[0] = 8; /* DES = 64 bits key */
+ range->num_encoding_sizes = 1;
+ range->max_encoding_tokens = 1; /* Only one key possible */
+ } else {
+ range->num_encoding_sizes = 0;
+ range->max_encoding_tokens = 0;
+ }
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
#ifdef WIRELESS_SPY
- case SIOCSIWSPY:
- /* Set the spy list */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set spy list
+ */
+static int wavelan_set_spy(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int i;
+ int ret = 0;
- /* Check the number of addresses. */
- if (wrq->u.data.length > IW_MAX_SPY) {
- ret = -E2BIG;
- break;
- }
- lp->spy_number = wrq->u.data.length;
-
- /* Are there are addresses to copy? */
- if (lp->spy_number > 0) {
- struct sockaddr address[IW_MAX_SPY];
- int i;
-
- /* Copy addresses to the driver. */
- wv_splx(lp, &flags);
- err = copy_from_user(address,
- wrq->u.data.pointer,
- sizeof(struct sockaddr)
- * lp->spy_number);
- wv_splhi(lp, &flags);
- if (err) {
- ret = -EFAULT;
- break;
- }
+ /* Disable spy while we copy the addresses.
+ * As we don't disable interrupts, we need to do this */
+ lp->spy_number = 0;
- /* Copy addresses to the lp structure. */
- for (i = 0; i < lp->spy_number; i++) {
- memcpy(lp->spy_address[i],
- address[i].sa_data,
- WAVELAN_ADDR_SIZE);
- }
+ /* Are there are addresses to copy? */
+ if (wrqu->data.length > 0) {
+ /* Copy addresses to the lp structure. */
+ for (i = 0; i < wrqu->data.length; i++) {
+ memcpy(lp->spy_address[i], address[i].sa_data,
+ WAVELAN_ADDR_SIZE);
+ }
- /* Reset structure. */
- memset(lp->spy_stat, 0x00,
- sizeof(iw_qual) * IW_MAX_SPY);
+ /* Reset structure. */
+ memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
#ifdef DEBUG_IOCTL_INFO
+ printk(KERN_DEBUG
+ "SetSpy: set of new addresses is: \n");
+ for (i = 0; i < wrqu->data.length; i++)
printk(KERN_DEBUG
- "SetSpy: set of new addresses is: \n");
- for (i = 0; i < wrq->u.data.length; i++)
- printk(KERN_DEBUG
- "%02X:%02X:%02X:%02X:%02X:%02X \n",
- lp->spy_address[i][0],
- lp->spy_address[i][1],
- lp->spy_address[i][2],
- lp->spy_address[i][3],
- lp->spy_address[i][4],
- lp->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
- }
+ "%02X:%02X:%02X:%02X:%02X:%02X \n",
+ lp->spy_address[i][0],
+ lp->spy_address[i][1],
+ lp->spy_address[i][2],
+ lp->spy_address[i][3],
+ lp->spy_address[i][4],
+ lp->spy_address[i][5]);
+#endif /* DEBUG_IOCTL_INFO */
+ }
- break;
+ /* Now we can set the number of addresses */
+ lp->spy_number = wrqu->data.length;
- case SIOCGIWSPY:
- /* Get the spy list and spy stats. */
+ return ret;
+}
- /* Set the number of addresses */
- wrq->u.data.length = lp->spy_number;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get spy list
+ */
+static int wavelan_get_spy(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int i;
- /* Does the user want to have the addresses back? */
- if ((lp->spy_number > 0)
- && (wrq->u.data.pointer != (caddr_t) 0)) {
- struct sockaddr address[IW_MAX_SPY];
- int i;
+ /* Set the number of addresses */
+ wrqu->data.length = lp->spy_number;
- /* Copy addresses from the lp structure. */
- for (i = 0; i < lp->spy_number; i++) {
- memcpy(address[i].sa_data,
- lp->spy_address[i],
- WAVELAN_ADDR_SIZE);
- address[i].sa_family = AF_UNIX;
- }
+ /* Copy addresses from the lp structure. */
+ for (i = 0; i < lp->spy_number; i++) {
+ memcpy(address[i].sa_data,
+ lp->spy_address[i],
+ WAVELAN_ADDR_SIZE);
+ address[i].sa_family = AF_UNIX;
+ }
+ /* Copy stats to the user buffer (just after). */
+ if(lp->spy_number > 0)
+ memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number),
+ lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
- /* Copy addresses to the user buffer. */
- wv_splx(lp, &flags);
- err = copy_to_user(wrq->u.data.pointer,
- address,
- sizeof(struct sockaddr)
- * lp->spy_number);
-
- /* Copy stats to the user buffer (just after). */
- err |= copy_to_user(wrq->u.data.pointer
- + (sizeof(struct sockaddr)
- * lp->spy_number),
- lp->spy_stat,
- sizeof(iw_qual) * lp->spy_number);
- wv_splhi(lp, &flags);
- if (err) {
- ret = -EFAULT;
- break;
- }
+ /* Reset updated flags. */
+ for (i = 0; i < lp->spy_number; i++)
+ lp->spy_stat[i].updated = 0x0;
- /* Reset updated flags. */
- for (i = 0; i < lp->spy_number; i++)
- lp->spy_stat[i].updated = 0x0;
- }
- /* if(pointer != NULL) */
- break;
-#endif /* WIRELESS_SPY */
+ return(0);
+}
+#endif /* WIRELESS_SPY */
- /* ------------------ PRIVATE IOCTL ------------------ */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set quality threshold
+ */
+static int wavelan_set_qthr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
- case SIOCSIPQTHR:
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- break;
- }
- psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
- psa_write(ioaddr, lp->hacr,
- (char *) &psa.psa_quality_thr - (char *) &psa,
- (unsigned char *) &psa.psa_quality_thr, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev, ioaddr, lp->hacr);
- mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
- psa.psa_quality_thr);
- break;
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ psa.psa_quality_thr = *(extra) & 0x0F;
+ psa_write(ioaddr, lp->hacr,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev, ioaddr, lp->hacr);
+ mmc_out(ioaddr, mmwoff(0, mmw_quality_thr),
+ psa.psa_quality_thr);
- case SIOCGIPQTHR:
- psa_read(ioaddr, lp->hacr,
- (char *) &psa.psa_quality_thr - (char *) &psa,
- (unsigned char *) &psa.psa_quality_thr, 1);
- *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_qthr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ unsigned long ioaddr = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ psa_read(ioaddr, lp->hacr,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ *(extra) = psa.psa_quality_thr & 0x0F;
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return 0;
+}
#ifdef HISTOGRAM
- case SIOCSIPHISTO:
- /* Verify that the user is root. */
- if (!capable(CAP_NET_ADMIN)) {
- ret = -EPERM;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set histogram
+ */
+static int wavelan_set_histo(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
- /* Check the number of intervals. */
- if (wrq->u.data.length > 16) {
- ret = -E2BIG;
- break;
- }
- lp->his_number = wrq->u.data.length;
-
- /* Are there addresses to copy? */
- if (lp->his_number > 0) {
- /* Copy interval ranges to the driver */
- wv_splx(lp, &flags);
- err = copy_from_user(lp->his_range,
- wrq->u.data.pointer,
- sizeof(char) * lp->his_number);
- wv_splhi(lp, &flags);
- if (err) {
- ret = -EFAULT;
- break;
- }
+ /* Check the number of intervals. */
+ if (wrqu->data.length > 16) {
+ return(-E2BIG);
+ }
- /* Reset structure. */
- memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ /* Disable histo while we copy the addresses.
+ * As we don't disable interrupts, we need to do this */
+ lp->his_number = 0;
+
+ /* Are there ranges to copy? */
+ if (wrqu->data.length > 0) {
+ /* Copy interval ranges to the driver */
+ memcpy(lp->his_range, extra, wrqu->data.length);
+
+ {
+ int i;
+ printk(KERN_DEBUG "Histo :");
+ for(i = 0; i < wrqu->data.length; i++)
+ printk(" %d", lp->his_range[i]);
+ printk("\n");
}
- break;
-
- case SIOCGIPHISTO:
- /* Set the number of intervals. */
- wrq->u.data.length = lp->his_number;
-
- /* Give back the distribution statistics */
- if ((lp->his_number > 0)
- && (wrq->u.data.pointer != (caddr_t) 0)) {
- /* Copy data to the user buffer. */
- wv_splx(lp, &flags);
- if (copy_to_user(wrq->u.data.pointer,
- lp->his_sum,
- sizeof(long) * lp->his_number);
- ret = -EFAULT;
- wv_splhi(lp, &flags);
-
- } /* if(pointer != NULL) */
- break;
-#endif /* HISTOGRAM */
- /* ------------------- OTHER IOCTL ------------------- */
+ /* Reset result structure. */
+ memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ }
- default:
- ret = -EOPNOTSUPP;
- } /* switch (cmd) */
+ /* Now we can set the number of ranges */
+ lp->his_number = wrqu->data.length;
- /* Enable interrupts and restore flags. */
- wv_splx(lp, &flags);
+ return(0);
+}
-#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
-#endif
- return ret;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get histogram
+ */
+static int wavelan_get_histo(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+
+ /* Set the number of intervals. */
+ wrqu->data.length = lp->his_number;
+
+ /* Give back the distribution statistics */
+ if(lp->his_number > 0)
+ memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number);
+
+ return(0);
}
+#endif /* HISTOGRAM */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const iw_handler wavelan_handler[] =
+{
+ NULL, /* SIOCSIWNAME */
+ wavelan_get_name, /* SIOCGIWNAME */
+ wavelan_set_nwid, /* SIOCSIWNWID */
+ wavelan_get_nwid, /* SIOCGIWNWID */
+ wavelan_set_freq, /* SIOCSIWFREQ */
+ wavelan_get_freq, /* SIOCGIWFREQ */
+ NULL, /* SIOCSIWMODE */
+ NULL, /* SIOCGIWMODE */
+ wavelan_set_sens, /* SIOCSIWSENS */
+ wavelan_get_sens, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ wavelan_get_range, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+#ifdef WIRELESS_SPY
+ wavelan_set_spy, /* SIOCSIWSPY */
+ wavelan_get_spy, /* SIOCGIWSPY */
+#else /* WIRELESS_SPY */
+ NULL, /* SIOCSIWSPY */
+ NULL, /* SIOCGIWSPY */
+#endif /* WIRELESS_SPY */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWAP */
+ NULL, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWESSID */
+ NULL, /* SIOCGIWESSID */
+ NULL, /* SIOCSIWNICKN */
+ NULL, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWRATE */
+ NULL, /* SIOCGIWRATE */
+ NULL, /* SIOCSIWRTS */
+ NULL, /* SIOCGIWRTS */
+ NULL, /* SIOCSIWFRAG */
+ NULL, /* SIOCGIWFRAG */
+ NULL, /* SIOCSIWTXPOW */
+ NULL, /* SIOCGIWTXPOW */
+ NULL, /* SIOCSIWRETRY */
+ NULL, /* SIOCGIWRETRY */
+ /* Bummer ! Why those are only at the end ??? */
+ wavelan_set_encode, /* SIOCSIWENCODE */
+ wavelan_get_encode, /* SIOCGIWENCODE */
+};
+
+static const iw_handler wavelan_private_handler[] =
+{
+ wavelan_set_qthr, /* SIOCIWFIRSTPRIV */
+ wavelan_get_qthr, /* SIOCIWFIRSTPRIV + 1 */
+#ifdef HISTOGRAM
+ wavelan_set_histo, /* SIOCIWFIRSTPRIV + 2 */
+ wavelan_get_histo, /* SIOCIWFIRSTPRIV + 3 */
+#endif /* HISTOGRAM */
+};
+
+static const struct iw_priv_args wavelan_private_args[] = {
+/*{ cmd, set_args, get_args, name } */
+ { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
+ { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
+ { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" },
+ { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
+};
+
+static const struct iw_handler_def wavelan_handler_def =
+{
+ num_standard: sizeof(wavelan_handler)/sizeof(iw_handler),
+ num_private: sizeof(wavelan_private_handler)/sizeof(iw_handler),
+ num_private_args: sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
+ standard: (iw_handler *) wavelan_handler,
+ private: (iw_handler *) wavelan_private_handler,
+ private_args: (struct iw_priv_args *) wavelan_private_args,
+};
/*------------------------------------------------------------------*/
/*
@@ -4069,8 +4267,8 @@ static int __init wavelan_config(device * dev)
#endif /* SET_MAC_ADDRESS */
#ifdef WIRELESS_EXT /* if wireless extension exists in the kernel */
- dev->do_ioctl = wavelan_ioctl;
dev->get_wireless_stats = wavelan_get_wireless_stats;
+ dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
#endif
dev->mtu = WAVELAN_MTU;
diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h
index 6bc145acc525..afda9f61371b 100644
--- a/drivers/net/wireless/wavelan.p.h
+++ b/drivers/net/wireless/wavelan.p.h
@@ -345,6 +345,12 @@
* - Fix spinlock stupid bugs that I left in. The driver is now SMP
* compliant and doesn't lockup at startup.
*
+ * Changes made for release in 2.5.2 :
+ * ---------------------------------
+ * - Use new driver API for Wireless Extensions :
+ * o got rid of wavelan_ioctl()
+ * o use a bunch of iw_handler instead
+ *
* Wishes & dreams:
* ----------------
* - roaming (see Pcmcia driver)
@@ -379,6 +385,7 @@
#include <linux/init.h>
#include <linux/wireless.h> /* Wireless extensions */
+#include <net/iw_handler.h> /* Wireless handlers */
/* WaveLAN declarations */
#include "i82586.h"
@@ -436,7 +443,7 @@
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan.c : v23 (SMP + wireless extensions) 05/10/00\n";
+static const char *version = "wavelan.c : v24 (SMP + wireless extensions) 11/12/01\n";
#endif
/* Watchdog temporisation */
@@ -449,11 +456,9 @@ static const char *version = "wavelan.c : v23 (SMP + wireless extensions) 05/10/
#define SIOCSIPQTHR SIOCIWFIRSTPRIV /* Set quality threshold */
#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1 /* Get quality threshold */
-#define SIOCSIPLTHR SIOCIWFIRSTPRIV + 2 /* Set level threshold */
-#define SIOCGIPLTHR SIOCIWFIRSTPRIV + 3 /* Get level threshold */
-#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 6 /* Set histogram ranges */
-#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 7 /* Get histogram values */
+#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 2 /* Set histogram ranges */
+#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 3 /* Get histogram values */
/****************************** TYPES ******************************/
diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c
index 173f937c309e..05688ca68114 100644
--- a/drivers/net/wireless/wavelan_cs.c
+++ b/drivers/net/wireless/wavelan_cs.c
@@ -1884,557 +1884,1234 @@ wl_his_gather(device * dev,
/*------------------------------------------------------------------*/
/*
- * Perform ioctl : config & info stuff
- * This is here that are treated the wireless extensions (iwconfig)
+ * Wireless Handler : get protocol name
*/
-static int
-wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
- struct ifreq * rq, /* Data passed */
- int cmd) /* Ioctl number */
+static int wavelan_get_name(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
{
- ioaddr_t base = dev->base_addr;
- net_local * lp = (net_local *)dev->priv; /* lp is not unused */
- struct iwreq * wrq = (struct iwreq *) rq;
- psa_t psa;
- mm_t m;
- unsigned long flags;
- int ret = 0;
-
-#ifdef DEBUG_IOCTL_TRACE
- printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
-#endif
-
- /* Disable interrupts & save flags */
- wv_splhi(lp, &flags);
-
- /* Look what is the request */
- switch(cmd)
- {
- /* --------------- WIRELESS EXTENSIONS --------------- */
-
- case SIOCGIWNAME:
- strcpy(wrq->u.name, "Wavelan");
- break;
+ strcpy(wrqu->name, "WaveLAN");
+ return 0;
+}
- case SIOCSIWNWID:
- /* Set NWID in wavelan */
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set NWID
+ */
+static int wavelan_set_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ mm_t m;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Set NWID in WaveLAN. */
#if WIRELESS_EXT > 8
- if(!wrq->u.nwid.disabled)
- {
- /* Set NWID in psa */
- psa.psa_nwid[0] = (wrq->u.nwid.value & 0xFF00) >> 8;
- psa.psa_nwid[1] = wrq->u.nwid.value & 0xFF;
+ if (!wrqu->nwid.disabled) {
+ /* Set NWID in psa */
+ psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8;
+ psa.psa_nwid[1] = wrqu->nwid.value & 0xFF;
#else /* WIRELESS_EXT > 8 */
- if(wrq->u.nwid.on)
- {
- /* Set NWID in psa */
- psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
- psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
+ if(wrq->u.nwid.on) {
+ /* Set NWID in psa */
+ psa.psa_nwid[0] = (wrq->u.nwid.nwid & 0xFF00) >> 8;
+ psa.psa_nwid[1] = wrq->u.nwid.nwid & 0xFF;
#endif /* WIRELESS_EXT > 8 */
- psa.psa_nwid_select = 0x01;
- psa_write(dev, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
-
- /* Set NWID in mmc */
- m.w.mmw_netw_id_l = psa.psa_nwid[1];
- m.w.mmw_netw_id_h = psa.psa_nwid[0];
- mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m,
- (unsigned char *)&m.w.mmw_netw_id_l, 2);
- mmc_out(base, mmwoff(0, mmw_loopt_sel), 0x00);
+ psa.psa_nwid_select = 0x01;
+ psa_write(dev,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
+
+ /* Set NWID in mmc. */
+ m.w.mmw_netw_id_l = psa.psa_nwid[1];
+ m.w.mmw_netw_id_h = psa.psa_nwid[0];
+ mmc_write(base,
+ (char *) &m.w.mmw_netw_id_l -
+ (char *) &m,
+ (unsigned char *) &m.w.mmw_netw_id_l, 2);
+ mmc_out(base, mmwoff(0, mmw_loopt_sel), 0x00);
+ } else {
+ /* Disable NWID in the psa. */
+ psa.psa_nwid_select = 0x00;
+ psa_write(dev,
+ (char *) &psa.psa_nwid_select -
+ (char *) &psa,
+ (unsigned char *) &psa.psa_nwid_select,
+ 1);
+
+ /* Disable NWID in the mmc (no filtering). */
+ mmc_out(base, mmwoff(0, mmw_loopt_sel),
+ MMW_LOOPT_SEL_DIS_NWID);
}
- else
- {
- /* Disable nwid in the psa */
- psa.psa_nwid_select = 0x00;
- psa_write(dev, (char *)&psa.psa_nwid_select - (char *)&psa,
- (unsigned char *)&psa.psa_nwid_select, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev);
- /* Disable nwid in the mmc (no filtering) */
- mmc_out(base, mmwoff(0, mmw_loopt_sel), MMW_LOOPT_SEL_DIS_NWID);
- }
- /* update the Wavelan checksum */
- update_psa_checksum(dev);
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- case SIOCGIWNWID:
- /* Read the NWID */
- psa_read(dev, (char *)psa.psa_nwid - (char *)&psa,
- (unsigned char *)psa.psa_nwid, 3);
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get NWID
+ */
+static int wavelan_get_nwid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Read the NWID. */
+ psa_read(dev,
+ (char *) psa.psa_nwid - (char *) &psa,
+ (unsigned char *) psa.psa_nwid, 3);
#if WIRELESS_EXT > 8
- wrq->u.nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
- wrq->u.nwid.disabled = !(psa.psa_nwid_select);
- wrq->u.nwid.fixed = 1; /* Superfluous */
+ wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+ wrqu->nwid.disabled = !(psa.psa_nwid_select);
+ wrqu->nwid.fixed = 1; /* Superfluous */
#else /* WIRELESS_EXT > 8 */
- wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
- wrq->u.nwid.on = psa.psa_nwid_select;
+ wrq->u.nwid.nwid = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1];
+ wrq->u.nwid.on = psa.psa_nwid_select;
#endif /* WIRELESS_EXT > 8 */
- break;
- case SIOCSIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
- if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- ret = wv_set_frequency(base, &(wrq->u.freq));
- else
- ret = -EOPNOTSUPP;
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- case SIOCGIWFREQ:
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable)
- * (does it work for everybody ? - especially old cards...) */
- if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- unsigned short freq;
+ return ret;
+}
- /* Ask the EEprom to read the frequency from the first area */
- fee_read(base, 0x00 /* 1st area - frequency... */,
- &freq, 1);
- wrq->u.freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
- wrq->u.freq.e = 1;
- }
- else
- {
- psa_read(dev, (char *)&psa.psa_subband - (char *)&psa,
- (unsigned char *)&psa.psa_subband, 1);
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set frequency
+ */
+static int wavelan_set_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ int ret;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
+ ret = wv_set_frequency(base, &(wrqu->freq));
+ else
+ ret = -EOPNOTSUPP;
- if(psa.psa_subband <= 4)
- {
- wrq->u.freq.m = fixed_bands[psa.psa_subband];
- wrq->u.freq.e = (psa.psa_subband != 0);
- }
- else
- ret = -EOPNOTSUPP;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get frequency
+ */
+static int wavelan_get_freq(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable).
+ * Does it work for everybody, especially old cards? */
+ if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ unsigned short freq;
+
+ /* Ask the EEPROM to read the frequency from the first area. */
+ fee_read(base, 0x00, &freq, 1);
+ wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000;
+ wrqu->freq.e = 1;
+ } else {
+ psa_read(dev,
+ (char *) &psa.psa_subband - (char *) &psa,
+ (unsigned char *) &psa.psa_subband, 1);
+
+ if (psa.psa_subband <= 4) {
+ wrqu->freq.m = fixed_bands[psa.psa_subband];
+ wrqu->freq.e = (psa.psa_subband != 0);
+ } else
+ ret = -EOPNOTSUPP;
}
- break;
- case SIOCSIWSENS:
- /* Set the level threshold */
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set level threshold
+ */
+static int wavelan_set_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Set the level threshold. */
#if WIRELESS_EXT > 7
- /* We should complain loudly if wrq->u.sens.fixed = 0, because we
- * can't set auto mode... */
- psa.psa_thr_pre_set = wrq->u.sens.value & 0x3F;
+ /* We should complain loudly if wrqu->sens.fixed = 0, because we
+ * can't set auto mode... */
+ psa.psa_thr_pre_set = wrqu->sens.value & 0x3F;
#else /* WIRELESS_EXT > 7 */
- psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
+ psa.psa_thr_pre_set = wrq->u.sensitivity & 0x3F;
#endif /* WIRELESS_EXT > 7 */
- psa_write(dev, (char *)&psa.psa_thr_pre_set - (char *)&psa,
- (unsigned char *)&psa.psa_thr_pre_set, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev);
- mmc_out(base, mmwoff(0, mmw_thr_pre_set), psa.psa_thr_pre_set);
- break;
+ psa_write(dev,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev);
+ mmc_out(base, mmwoff(0, mmw_thr_pre_set),
+ psa.psa_thr_pre_set);
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
- case SIOCGIWSENS:
- /* Read the level threshold */
- psa_read(dev, (char *)&psa.psa_thr_pre_set - (char *)&psa,
- (unsigned char *)&psa.psa_thr_pre_set, 1);
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get level threshold
+ */
+static int wavelan_get_sens(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Read the level threshold. */
+ psa_read(dev,
+ (char *) &psa.psa_thr_pre_set - (char *) &psa,
+ (unsigned char *) &psa.psa_thr_pre_set, 1);
#if WIRELESS_EXT > 7
- wrq->u.sens.value = psa.psa_thr_pre_set & 0x3F;
- wrq->u.sens.fixed = 1;
+ wrqu->sens.value = psa.psa_thr_pre_set & 0x3F;
+ wrqu->sens.fixed = 1;
#else /* WIRELESS_EXT > 7 */
- wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
+ wrq->u.sensitivity = psa.psa_thr_pre_set & 0x3F;
#endif /* WIRELESS_EXT > 7 */
- break;
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
#if WIRELESS_EXT > 8
- case SIOCSIWENCODE:
- /* Set encryption key */
- if(!mmc_encr(base))
- {
- ret = -EOPNOTSUPP;
- break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set encryption key
+ */
+static int wavelan_set_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ psa_t psa;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check if capable of encryption */
+ if (!mmc_encr(base)) {
+ ret = -EOPNOTSUPP;
}
- /* Basic checking... */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- /* Check the size of the key */
- if(wrq->u.encoding.length != 8)
- {
- ret = -EINVAL;
- break;
- }
+ /* Check the size of the key */
+ if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) {
+ ret = -EINVAL;
+ }
- /* Copy the key in the driver */
- if(copy_from_user(psa.psa_encryption_key, wrq->u.encoding.pointer,
- wrq->u.encoding.length))
- {
- ret = -EFAULT;
- break;
- }
+ if(!ret) {
+ /* Basic checking... */
+ if (wrqu->encoding.length == 8) {
+ /* Copy the key in the driver */
+ memcpy(psa.psa_encryption_key, extra,
+ wrqu->encoding.length);
+ psa.psa_encryption_select = 1;
+
+ psa_write(dev,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 8 + 1);
+
+ mmc_out(base, mmwoff(0, mmw_encr_enable),
+ MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
+ mmc_write(base, mmwoff(0, mmw_encr_key),
+ (unsigned char *) &psa.
+ psa_encryption_key, 8);
+ }
- psa.psa_encryption_select = 1;
- psa_write(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 8+1);
+ /* disable encryption */
+ if (wrqu->encoding.flags & IW_ENCODE_DISABLED) {
+ psa.psa_encryption_select = 0;
+ psa_write(dev,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 1);
- mmc_out(base, mmwoff(0, mmw_encr_enable),
- MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE);
- mmc_write(base, mmwoff(0, mmw_encr_key),
- (unsigned char *) &psa.psa_encryption_key, 8);
+ mmc_out(base, mmwoff(0, mmw_encr_enable), 0);
+ }
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev);
}
- if(wrq->u.encoding.flags & IW_ENCODE_DISABLED)
- { /* disable encryption */
- psa.psa_encryption_select = 0;
- psa_write(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 1);
-
- mmc_out(base, mmwoff(0, mmw_encr_enable), 0);
- }
- /* update the Wavelan checksum */
- update_psa_checksum(dev);
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- case SIOCGIWENCODE:
- /* Read the encryption key */
- if(!mmc_encr(base))
- {
- ret = -EOPNOTSUPP;
- break;
- }
+ return ret;
+}
- /* only super-user can see encryption key */
- if(!capable(CAP_NET_ADMIN))
- {
- ret = -EPERM;
- break;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get encryption key
+ */
+static int wavelan_get_encode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check if encryption is available */
+ if (!mmc_encr(base)) {
+ ret = -EOPNOTSUPP;
+ } else {
+ /* Read the encryption key */
+ psa_read(dev,
+ (char *) &psa.psa_encryption_select -
+ (char *) &psa,
+ (unsigned char *) &psa.
+ psa_encryption_select, 1 + 8);
+
+ /* encryption is enabled ? */
+ if (psa.psa_encryption_select)
+ wrqu->encoding.flags = IW_ENCODE_ENABLED;
+ else
+ wrqu->encoding.flags = IW_ENCODE_DISABLED;
+ wrqu->encoding.flags |= mmc_encr(base);
+
+ /* Copy the key to the user buffer */
+ wrqu->encoding.length = 8;
+ memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length);
}
- /* Basic checking... */
- if(wrq->u.encoding.pointer != (caddr_t) 0)
- {
- psa_read(dev, (char *) &psa.psa_encryption_select - (char *) &psa,
- (unsigned char *) &psa.psa_encryption_select, 1+8);
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- /* encryption is enabled ? */
- if(psa.psa_encryption_select)
- wrq->u.encoding.flags = IW_ENCODE_ENABLED;
- else
- wrq->u.encoding.flags = IW_ENCODE_DISABLED;
- wrq->u.encoding.flags |= mmc_encr(base);
-
- /* Copy the key to the user buffer */
- wrq->u.encoding.length = 8;
- if(copy_to_user(wrq->u.encoding.pointer, psa.psa_encryption_key, 8))
- ret = -EFAULT;
- }
- break;
+ return ret;
+}
#endif /* WIRELESS_EXT > 8 */
#ifdef WAVELAN_ROAMING_EXT
#if WIRELESS_EXT > 5
- case SIOCSIWESSID:
- /* Check if disable */
- if(wrq->u.data.flags == 0)
- lp->filter_domains = 0;
- else
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
- char * endp;
-
- /* Check the size of the string */
- if(wrq->u.data.length > IW_ESSID_MAX_SIZE + 1)
- {
- ret = -E2BIG;
- break;
- }
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set ESSID (domain)
+ */
+static int wavelan_set_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check if disable */
+ if(wrqu->data.flags == 0)
+ lp->filter_domains = 0;
+ else {
+ char essid[IW_ESSID_MAX_SIZE + 1];
+ char * endp;
- /* Copy the string in the driver */
- if(copy_from_user(essid, wrq->u.data.pointer, wrq->u.data.length))
- {
- ret = -EFAULT;
- break;
- }
- essid[IW_ESSID_MAX_SIZE] = '\0';
+ /* Terminate the string */
+ memcpy(essid, extra, wrqu->data.length);
+ essid[IW_ESSID_MAX_SIZE] = '\0';
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "SetEssid : ``%s''\n", essid);
+ printk(KERN_DEBUG "SetEssid : ``%s''\n", essid);
#endif /* DEBUG_IOCTL_INFO */
- /* Convert to a number (note : Wavelan specific) */
- lp->domain_id = simple_strtoul(essid, &endp, 16);
- /* Has it worked ? */
- if(endp > essid)
- lp->filter_domains = 1;
- else
- {
- lp->filter_domains = 0;
- ret = -EINVAL;
- }
- }
- break;
+ /* Convert to a number (note : Wavelan specific) */
+ lp->domain_id = simple_strtoul(essid, &endp, 16);
+ /* Has it worked ? */
+ if(endp > essid)
+ lp->filter_domains = 1;
+ else {
+ lp->filter_domains = 0;
+ ret = -EINVAL;
+ }
+ }
- case SIOCGIWESSID:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- char essid[IW_ESSID_MAX_SIZE + 1];
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
- /* Is the domain ID active ? */
- wrq->u.data.flags = lp->filter_domains;
+ return ret;
+}
- /* Copy Domain ID into a string (Wavelan specific) */
- /* Sound crazy, be we can't have a snprintf in the kernel !!! */
- sprintf(essid, "%lX", lp->domain_id);
- essid[IW_ESSID_MAX_SIZE] = '\0';
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get ESSID (domain)
+ */
+static int wavelan_get_essid(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
- /* Set the length */
- wrq->u.data.length = strlen(essid) + 1;
+ /* Is the domain ID active ? */
+ wrqu->data.flags = lp->filter_domains;
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, essid, wrq->u.data.length))
- ret = -EFAULT;
- }
- break;
+ /* Copy Domain ID into a string (Wavelan specific) */
+ /* Sound crazy, be we can't have a snprintf in the kernel !!! */
+ sprintf(extra, "%lX", lp->domain_id);
+ extra[IW_ESSID_MAX_SIZE] = '\0';
- case SIOCSIWAP:
+ /* Set the length */
+ wrqu->data.length = strlen(extra) + 1;
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set AP address
+ */
+static int wavelan_set_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
- wrq->u.ap_addr.sa_data[0],
- wrq->u.ap_addr.sa_data[1],
- wrq->u.ap_addr.sa_data[2],
- wrq->u.ap_addr.sa_data[3],
- wrq->u.ap_addr.sa_data[4],
- wrq->u.ap_addr.sa_data[5]);
+ printk(KERN_DEBUG "Set AP to : %02X:%02X:%02X:%02X:%02X:%02X\n",
+ wrqu->ap_addr.sa_data[0],
+ wrqu->ap_addr.sa_data[1],
+ wrqu->ap_addr.sa_data[2],
+ wrqu->ap_addr.sa_data[3],
+ wrqu->ap_addr.sa_data[4],
+ wrqu->ap_addr.sa_data[5]);
#endif /* DEBUG_IOCTL_INFO */
- ret = -EOPNOTSUPP; /* Not supported yet */
- break;
+ return -EOPNOTSUPP;
+}
- case SIOCGIWAP:
- /* Should get the real McCoy instead of own Ethernet address */
- memcpy(wrq->u.ap_addr.sa_data, dev->dev_addr, WAVELAN_ADDR_SIZE);
- wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get AP address
+ */
+static int wavelan_get_wap(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ /* Should get the real McCoy instead of own Ethernet address */
+ memcpy(wrqu->ap_addr.sa_data, dev->dev_addr, WAVELAN_ADDR_SIZE);
+ wrqu->ap_addr.sa_family = ARPHRD_ETHER;
- ret = -EOPNOTSUPP; /* Not supported yet */
- break;
+ return -EOPNOTSUPP;
+}
#endif /* WIRELESS_EXT > 5 */
#endif /* WAVELAN_ROAMING_EXT */
#if WIRELESS_EXT > 8
#ifdef WAVELAN_ROAMING
- case SIOCSIWMODE:
- switch(wrq->u.mode)
- {
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set mode
+ */
+static int wavelan_set_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+ int ret = 0;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Check mode */
+ switch(wrqu->mode) {
case IW_MODE_ADHOC:
- if(do_roaming)
- {
- wv_roam_cleanup(dev);
- do_roaming = 0;
- }
- break;
+ if(do_roaming) {
+ wv_roam_cleanup(dev);
+ do_roaming = 0;
+ }
+ break;
case IW_MODE_INFRA:
- if(!do_roaming)
- {
- wv_roam_init(dev);
- do_roaming = 1;
- }
- break;
+ if(!do_roaming) {
+ wv_roam_init(dev);
+ do_roaming = 1;
+ }
+ break;
default:
- ret = -EINVAL;
+ ret = -EINVAL;
}
- break;
- case SIOCGIWMODE:
- if(do_roaming)
- wrq->u.mode = IW_MODE_INFRA;
- else
- wrq->u.mode = IW_MODE_ADHOC;
- break;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get mode
+ */
+static int wavelan_get_mode(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ if(do_roaming)
+ wrqu->mode = IW_MODE_INFRA;
+ else
+ wrqu->mode = IW_MODE_ADHOC;
+
+ return 0;
+}
#endif /* WAVELAN_ROAMING */
#endif /* WIRELESS_EXT > 8 */
- case SIOCGIWRANGE:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_range range;
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get range info
+ */
+static int wavelan_get_range(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct iw_range *range = (struct iw_range *) extra;
+ unsigned long flags;
+ int ret = 0;
- /* Set the length (very important for backward compatibility) */
- wrq->u.data.length = sizeof(struct iw_range);
+ /* Set the length (very important for backward compatibility) */
+ wrqu->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 all the info we don't care or don't know about to zero */
+ memset(range, 0, sizeof(struct iw_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 */
+ /* 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.4 * 1000 * 1000; /* don't argue on this ! */
- range.min_nwid = 0x0000;
- range.max_nwid = 0xFFFF;
-
- /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) */
- if(!(mmc_in(base, mmroff(0, mmr_fee_status)) &
- (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY)))
- {
- range.num_channels = 10;
- range.num_frequency = wv_frequency_list(base, range.freq,
- IW_MAX_FREQUENCIES);
- }
- else
- range.num_channels = range.num_frequency = 0;
+ /* Set information in the range struct. */
+ range->throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */
+ range->min_nwid = 0x0000;
+ range->max_nwid = 0xFFFF;
- range.sensitivity = 0x3F;
- range.max_qual.qual = MMR_SGNL_QUAL;
- range.max_qual.level = MMR_SIGNAL_LVL;
- range.max_qual.noise = MMR_SILENCE_LVL;
+ range->sensitivity = 0x3F;
+ range->max_qual.qual = MMR_SGNL_QUAL;
+ range->max_qual.level = MMR_SIGNAL_LVL;
+ range->max_qual.noise = MMR_SILENCE_LVL;
#if WIRELESS_EXT > 11
- range.avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
- /* Need to get better values for those two */
- range.avg_qual.level = 30;
- range.avg_qual.noise = 8;
+ range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */
+ /* Need to get better values for those two */
+ range->avg_qual.level = 30;
+ range->avg_qual.noise = 8;
#endif /* WIRELESS_EXT > 11 */
#if WIRELESS_EXT > 7
- range.num_bitrates = 1;
- range.bitrate[0] = 2000000; /* 2 Mb/s */
+ range->num_bitrates = 1;
+ range->bitrate[0] = 2000000; /* 2 Mb/s */
#endif /* WIRELESS_EXT > 7 */
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */
+ if (!(mmc_in(base, mmroff(0, mmr_fee_status)) &
+ (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) {
+ range->num_channels = 10;
+ range->num_frequency = wv_frequency_list(base, range->freq,
+ IW_MAX_FREQUENCIES);
+ } else
+ range->num_channels = range->num_frequency = 0;
+
#if WIRELESS_EXT > 8
- /* Encryption supported ? */
- if(mmc_encr(base))
- {
- range.encoding_size[0] = 8; /* DES = 64 bits key */
- range.num_encoding_sizes = 1;
- range.max_encoding_tokens = 1; /* Only one key possible */
- }
- else
- {
- range.num_encoding_sizes = 0;
- range.max_encoding_tokens = 0;
- }
+ /* Encryption supported ? */
+ if (mmc_encr(base)) {
+ range->encoding_size[0] = 8; /* DES = 64 bits key */
+ range->num_encoding_sizes = 1;
+ range->max_encoding_tokens = 1; /* Only one key possible */
+ } else {
+ range->num_encoding_sizes = 0;
+ range->max_encoding_tokens = 0;
+ }
#endif /* WIRELESS_EXT > 8 */
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, &range,
- sizeof(struct iw_range)))
- ret = -EFAULT;
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return ret;
+}
+
+#ifdef WIRELESS_SPY
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : set spy list
+ */
+static int wavelan_set_spy(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int i;
+ int ret = 0;
+
+ /* Disable spy while we copy the addresses.
+ * As we don't disable interrupts, we need to do this */
+ lp->spy_number = 0;
+
+ /* Are there are addresses to copy? */
+ if (wrqu->data.length > 0) {
+ /* Copy addresses to the lp structure. */
+ for (i = 0; i < wrqu->data.length; i++) {
+ memcpy(lp->spy_address[i], address[i].sa_data,
+ WAVELAN_ADDR_SIZE);
+ }
+
+ /* Reset structure. */
+ memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+
+#ifdef DEBUG_IOCTL_INFO
+ printk(KERN_DEBUG
+ "SetSpy: set of new addresses is: \n");
+ for (i = 0; i < wrqu->data.length; i++)
+ printk(KERN_DEBUG
+ "%02X:%02X:%02X:%02X:%02X:%02X \n",
+ lp->spy_address[i][0],
+ lp->spy_address[i][1],
+ lp->spy_address[i][2],
+ lp->spy_address[i][3],
+ lp->spy_address[i][4],
+ lp->spy_address[i][5]);
+#endif /* DEBUG_IOCTL_INFO */
+ }
+
+ /* Now we can set the number of addresses */
+ lp->spy_number = wrqu->data.length;
+
+ return ret;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Handler : get spy list
+ */
+static int wavelan_get_spy(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ struct sockaddr *address = (struct sockaddr *) extra;
+ int i;
+
+ /* Set the number of addresses */
+ wrqu->data.length = lp->spy_number;
+
+ /* Copy addresses from the lp structure. */
+ for (i = 0; i < lp->spy_number; i++) {
+ memcpy(address[i].sa_data,
+ lp->spy_address[i],
+ WAVELAN_ADDR_SIZE);
+ address[i].sa_family = AF_UNIX;
+ }
+ /* Copy stats to the user buffer (just after). */
+ if(lp->spy_number > 0)
+ memcpy(extra + (sizeof(struct sockaddr) * lp->spy_number),
+ lp->spy_stat, sizeof(iw_qual) * lp->spy_number);
+
+ /* Reset updated flags. */
+ for (i = 0; i < lp->spy_number; i++)
+ lp->spy_stat[i].updated = 0x0;
+
+ return(0);
+}
+#endif /* WIRELESS_SPY */
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set quality threshold
+ */
+static int wavelan_set_qthr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ ioaddr_t base = dev->base_addr;
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ psa.psa_quality_thr = *(extra) & 0x0F;
+ psa_write(dev,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ /* update the Wavelan checksum */
+ update_psa_checksum(dev);
+ mmc_out(base, mmwoff(0, mmw_quality_thr),
+ psa.psa_quality_thr);
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_qthr(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ psa_t psa;
+ unsigned long flags;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ psa_read(dev,
+ (char *) &psa.psa_quality_thr - (char *) &psa,
+ (unsigned char *) &psa.psa_quality_thr, 1);
+ *(extra) = psa.psa_quality_thr & 0x0F;
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return 0;
+}
+
+#ifdef WAVELAN_ROAMING
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set roaming
+ */
+static int wavelan_set_roam(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+ unsigned long flags;
+
+ /* Disable interrupts and save flags. */
+ wv_splhi(lp, &flags);
+
+ /* Note : should check if user == root */
+ if(do_roaming && (*extra)==0)
+ wv_roam_cleanup(dev);
+ else if(do_roaming==0 && (*extra)!=0)
+ wv_roam_init(dev);
+
+ do_roaming = (*extra);
+
+ /* Enable interrupts and restore flags. */
+ wv_splx(lp, &flags);
+
+ return 0;
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get quality threshold
+ */
+static int wavelan_get_roam(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ *(extra) = do_roaming;
+
+ return 0;
+}
+#endif /* WAVELAN_ROAMING */
+
+#ifdef HISTOGRAM
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : set histogram
+ */
+static int wavelan_set_histo(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+
+ /* Check the number of intervals. */
+ if (wrqu->data.length > 16) {
+ return(-E2BIG);
}
+
+ /* Disable histo while we copy the addresses.
+ * As we don't disable interrupts, we need to do this */
+ lp->his_number = 0;
+
+ /* Are there ranges to copy? */
+ if (wrqu->data.length > 0) {
+ /* Copy interval ranges to the driver */
+ memcpy(lp->his_range, extra, wrqu->data.length);
+
+ {
+ int i;
+ printk(KERN_DEBUG "Histo :");
+ for(i = 0; i < wrqu->data.length; i++)
+ printk(" %d", lp->his_range[i]);
+ printk("\n");
+ }
+
+ /* Reset result structure. */
+ memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ }
+
+ /* Now we can set the number of ranges */
+ lp->his_number = wrqu->data.length;
+
+ return(0);
+}
+
+/*------------------------------------------------------------------*/
+/*
+ * Wireless Private Handler : get histogram
+ */
+static int wavelan_get_histo(struct net_device *dev,
+ struct iw_request_info *info,
+ union iwreq_data *wrqu,
+ char *extra)
+{
+ net_local *lp = (net_local *) dev->priv; /* lp is not unused */
+
+ /* Set the number of intervals. */
+ wrqu->data.length = lp->his_number;
+
+ /* Give back the distribution statistics */
+ if(lp->his_number > 0)
+ memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number);
+
+ return(0);
+}
+#endif /* HISTOGRAM */
+
+/*------------------------------------------------------------------*/
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const struct iw_priv_args wavelan_private_args[] = {
+/*{ cmd, set_args, get_args, name } */
+ { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
+ { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
+ { SIOCSIPROAM, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setroam" },
+ { SIOCGIPROAM, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getroam" },
+ { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" },
+ { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
+};
+
+#if WIRELESS_EXT > 12
+
+static const iw_handler wavelan_handler[] =
+{
+ NULL, /* SIOCSIWNAME */
+ wavelan_get_name, /* SIOCGIWNAME */
+ wavelan_set_nwid, /* SIOCSIWNWID */
+ wavelan_get_nwid, /* SIOCGIWNWID */
+ wavelan_set_freq, /* SIOCSIWFREQ */
+ wavelan_get_freq, /* SIOCGIWFREQ */
+#ifdef WAVELAN_ROAMING
+ wavelan_set_mode, /* SIOCSIWMODE */
+ wavelan_get_mode, /* SIOCGIWMODE */
+#else /* WAVELAN_ROAMING */
+ NULL, /* SIOCSIWMODE */
+ NULL, /* SIOCGIWMODE */
+#endif /* WAVELAN_ROAMING */
+ wavelan_set_sens, /* SIOCSIWSENS */
+ wavelan_get_sens, /* SIOCGIWSENS */
+ NULL, /* SIOCSIWRANGE */
+ wavelan_get_range, /* SIOCGIWRANGE */
+ NULL, /* SIOCSIWPRIV */
+ NULL, /* SIOCGIWPRIV */
+ NULL, /* SIOCSIWSTATS */
+ NULL, /* SIOCGIWSTATS */
+#ifdef WIRELESS_SPY
+ wavelan_set_spy, /* SIOCSIWSPY */
+ wavelan_get_spy, /* SIOCGIWSPY */
+#else /* WIRELESS_SPY */
+ NULL, /* SIOCSIWSPY */
+ NULL, /* SIOCGIWSPY */
+#endif /* WIRELESS_SPY */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+#ifdef WAVELAN_ROAMING_EXT
+ wavelan_set_wap, /* SIOCSIWAP */
+ wavelan_get_wap, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ wavelan_set_essid, /* SIOCSIWESSID */
+ wavelan_get_essid, /* SIOCGIWESSID */
+#else /* WAVELAN_ROAMING_EXT */
+ NULL, /* SIOCSIWAP */
+ NULL, /* SIOCGIWAP */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCGIWAPLIST */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWESSID */
+ NULL, /* SIOCGIWESSID */
+#endif /* WAVELAN_ROAMING_EXT */
+#if WIRELESS_EXT > 8
+ NULL, /* SIOCSIWNICKN */
+ NULL, /* SIOCGIWNICKN */
+ NULL, /* -- hole -- */
+ NULL, /* -- hole -- */
+ NULL, /* SIOCSIWRATE */
+ NULL, /* SIOCGIWRATE */
+ NULL, /* SIOCSIWRTS */
+ NULL, /* SIOCGIWRTS */
+ NULL, /* SIOCSIWFRAG */
+ NULL, /* SIOCGIWFRAG */
+ NULL, /* SIOCSIWTXPOW */
+ NULL, /* SIOCGIWTXPOW */
+ NULL, /* SIOCSIWRETRY */
+ NULL, /* SIOCGIWRETRY */
+ wavelan_set_encode, /* SIOCSIWENCODE */
+ wavelan_get_encode, /* SIOCGIWENCODE */
+#endif /* WIRELESS_EXT > 8 */
+};
+
+static const iw_handler wavelan_private_handler[] =
+{
+ wavelan_set_qthr, /* SIOCIWFIRSTPRIV */
+ wavelan_get_qthr, /* SIOCIWFIRSTPRIV + 1 */
+#ifdef WAVELAN_ROAMING
+ wavelan_set_roam, /* SIOCIWFIRSTPRIV + 2 */
+ wavelan_get_roam, /* SIOCIWFIRSTPRIV + 3 */
+#else /* WAVELAN_ROAMING */
+ NULL, /* SIOCIWFIRSTPRIV + 2 */
+ NULL, /* SIOCIWFIRSTPRIV + 3 */
+#endif /* WAVELAN_ROAMING */
+#ifdef HISTOGRAM
+ wavelan_set_histo, /* SIOCIWFIRSTPRIV + 4 */
+ wavelan_get_histo, /* SIOCIWFIRSTPRIV + 5 */
+#endif /* HISTOGRAM */
+};
+
+static const struct iw_handler_def wavelan_handler_def =
+{
+ num_standard: sizeof(wavelan_handler)/sizeof(iw_handler),
+ num_private: sizeof(wavelan_private_handler)/sizeof(iw_handler),
+ num_private_args: sizeof(wavelan_private_args)/sizeof(struct iw_priv_args),
+ standard: (iw_handler *) wavelan_handler,
+ private: (iw_handler *) wavelan_private_handler,
+ private_args: (struct iw_priv_args *) wavelan_private_args,
+};
+
+#else /* WIRELESS_EXT > 12 */
+/*------------------------------------------------------------------*/
+/*
+ * Perform ioctl : config & info stuff
+ * This is here that are treated the wireless extensions (iwconfig)
+ */
+static int
+wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
+ struct ifreq * rq, /* Data passed */
+ int cmd) /* Ioctl number */
+{
+ struct iwreq * wrq = (struct iwreq *) rq;
+ int ret = 0;
+
+#ifdef DEBUG_IOCTL_TRACE
+ printk(KERN_DEBUG "%s: ->wavelan_ioctl(cmd=0x%X)\n", dev->name, cmd);
+#endif
+
+ /* Look what is the request */
+ switch(cmd)
+ {
+ /* --------------- WIRELESS EXTENSIONS --------------- */
+
+ case SIOCGIWNAME:
+ wavelan_get_name(dev, NULL, &(wrq->u), NULL);
break;
- case SIOCGIWPRIV:
- /* Basic checking... */
- if(wrq->u.data.pointer != (caddr_t) 0)
- {
- struct iw_priv_args priv[] =
- { /* cmd, set_args, get_args, name */
- { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" },
- { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" },
- { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" },
- { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" },
- { SIOCSIPROAM, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1 , 0, "setroam" },
- { SIOCGIPROAM, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getroam" },
- };
+ case SIOCSIWNWID:
+ ret = wavelan_set_nwid(dev, NULL, &(wrq->u), NULL);
+ break;
- /* Set the number of ioctl available */
- wrq->u.data.length = 6;
+ case SIOCGIWNWID:
+ ret = wavelan_get_nwid(dev, NULL, &(wrq->u), NULL);
+ break;
- /* Copy structure to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, (u_char *) priv,
- sizeof(priv)))
+ case SIOCSIWFREQ:
+ ret = wavelan_set_freq(dev, NULL, &(wrq->u), NULL);
+ break;
+
+ case SIOCGIWFREQ:
+ ret = wavelan_get_freq(dev, NULL, &(wrq->u), NULL);
+ break;
+
+ case SIOCSIWSENS:
+ ret = wavelan_set_sens(dev, NULL, &(wrq->u), NULL);
+ break;
+
+ case SIOCGIWSENS:
+ ret = wavelan_get_sens(dev, NULL, &(wrq->u), NULL);
+ break;
+
+#if WIRELESS_EXT > 8
+ case SIOCSIWENCODE:
+ {
+ char keybuf[8];
+ if (wrq->u.encoding.pointer) {
+ /* We actually have a key to set */
+ if (wrq->u.encoding.length != 8) {
+ ret = -EINVAL;
+ break;
+ }
+ if (copy_from_user(keybuf,
+ wrq->u.encoding.pointer,
+ wrq->u.encoding.length)) {
ret = -EFAULT;
+ break;
+ }
+ } else if (wrq->u.encoding.length != 0) {
+ ret = -EINVAL;
+ break;
}
+ ret = wavelan_set_encode(dev, NULL, &(wrq->u), keybuf);
+ }
break;
-#ifdef WIRELESS_SPY
- case SIOCSIWSPY:
- /* Set the spy list */
+ case SIOCGIWENCODE:
+ if (! capable(CAP_NET_ADMIN)) {
+ ret = -EPERM;
+ break;
+ }
+ {
+ char keybuf[8];
+ ret = wavelan_get_encode(dev, NULL,
+ &(wrq->u),
+ keybuf);
+ if (wrq->u.encoding.pointer) {
+ if (copy_to_user(wrq->u.encoding.pointer,
+ keybuf,
+ wrq->u.encoding.length))
+ ret = -EFAULT;
+ }
+ }
+ break;
+#endif /* WIRELESS_EXT > 8 */
- /* Check the number of addresses */
- if(wrq->u.data.length > IW_MAX_SPY)
- {
+#ifdef WAVELAN_ROAMING_EXT
+#if WIRELESS_EXT > 5
+ case SIOCSIWESSID:
+ {
+ char essidbuf[IW_ESSID_MAX_SIZE+1];
+ if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
ret = -E2BIG;
break;
}
- lp->spy_number = wrq->u.data.length;
-
- /* If there is some addresses to copy */
- if(lp->spy_number > 0)
- {
- struct sockaddr address[IW_MAX_SPY];
- int i;
-
- /* Copy addresses to the driver */
- if(copy_from_user(address, wrq->u.data.pointer,
- sizeof(struct sockaddr) * lp->spy_number))
- {
- ret = -EFAULT;
- break;
- }
+ if (copy_from_user(essidbuf, wrq->u.essid.pointer,
+ wrq->u.essid.length)) {
+ ret = -EFAULT;
+ break;
+ }
+ ret = wavelan_set_essid(dev, NULL,
+ &(wrq->u),
+ essidbuf);
+ }
+ break;
- /* Copy addresses to the lp structure */
- for(i = 0; i < lp->spy_number; i++)
- {
- memcpy(lp->spy_address[i], address[i].sa_data,
- WAVELAN_ADDR_SIZE);
- }
+ case SIOCGIWESSID:
+ {
+ char essidbuf[IW_ESSID_MAX_SIZE+1];
+ ret = wavelan_get_essid(dev, NULL,
+ &(wrq->u),
+ essidbuf);
+ if (wrq->u.essid.pointer)
+ if ( copy_to_user(wrq->u.essid.pointer,
+ essidbuf,
+ wrq->u.essid.length) )
+ ret = -EFAULT;
+ }
+ break;
- /* Reset structure... */
- memset(lp->spy_stat, 0x00, sizeof(iw_qual) * IW_MAX_SPY);
+ case SIOCSIWAP:
+ ret = wavelan_set_wap(dev, NULL, &(wrq->u), NULL);
+ break;
-#ifdef DEBUG_IOCTL_INFO
- printk(KERN_DEBUG "SetSpy - Set of new addresses is :\n");
- for(i = 0; i < wrq->u.data.length; i++)
- printk(KERN_DEBUG "%02X:%02X:%02X:%02X:%02X:%02X\n",
- lp->spy_address[i][0],
- lp->spy_address[i][1],
- lp->spy_address[i][2],
- lp->spy_address[i][3],
- lp->spy_address[i][4],
- lp->spy_address[i][5]);
-#endif /* DEBUG_IOCTL_INFO */
- }
+ case SIOCGIWAP:
+ ret = wavelan_get_wap(dev, NULL, &(wrq->u), NULL);
+ break;
+#endif /* WIRELESS_EXT > 5 */
+#endif /* WAVELAN_ROAMING_EXT */
+#if WIRELESS_EXT > 8
+#ifdef WAVELAN_ROAMING
+ case SIOCSIWMODE:
+ ret = wavelan_set_mode(dev, NULL, &(wrq->u), NULL);
break;
- case SIOCGIWSPY:
- /* Get the spy list and spy stats */
+ case SIOCGIWMODE:
+ ret = wavelan_get_mode(dev, NULL, &(wrq->u), NULL);
+ break;
+#endif /* WAVELAN_ROAMING */
+#endif /* WIRELESS_EXT > 8 */
- /* Set the number of addresses */
- wrq->u.data.length = lp->spy_number;
+ case SIOCGIWRANGE:
+ {
+ struct iw_range range;
+ ret = wavelan_get_range(dev, NULL,
+ &(wrq->u),
+ (char *) &range);
+ if (copy_to_user(wrq->u.data.pointer, &range,
+ sizeof(struct iw_range)))
+ ret = -EFAULT;
+ }
+ break;
- /* If the user want to have the addresses back... */
- if((lp->spy_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
+ case SIOCGIWPRIV:
+ /* Basic checking... */
+ if(wrq->u.data.pointer != (caddr_t) 0)
{
- struct sockaddr address[IW_MAX_SPY];
- int i;
-
- /* Copy addresses from the lp structure */
- for(i = 0; i < lp->spy_number; i++)
- {
- memcpy(address[i].sa_data, lp->spy_address[i],
- WAVELAN_ADDR_SIZE);
- address[i].sa_family = ARPHRD_ETHER;
- }
-
- /* Copy addresses to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, address,
- sizeof(struct sockaddr) * lp->spy_number))
- {
- ret = -EFAULT;
- break;
- }
+ /* Set the number of ioctl available */
+ wrq->u.data.length = sizeof(wavelan_private_args) / sizeof(wavelan_private_args[0]);
- /* Copy stats to the user buffer (just after) */
- if(copy_to_user(wrq->u.data.pointer +
- (sizeof(struct sockaddr) * lp->spy_number),
- lp->spy_stat, sizeof(iw_qual) * lp->spy_number))
- {
- ret = -EFAULT;
- break;
- }
+ /* Copy structure to the user buffer */
+ if(copy_to_user(wrq->u.data.pointer, (u_char *) wavelan_private_args,
+ sizeof(wavelan_private_args)))
+ ret = -EFAULT;
+ }
+ break;
- /* Reset updated flags */
- for(i = 0; i < lp->spy_number; i++)
- lp->spy_stat[i].updated = 0x0;
- } /* if(pointer != NULL) */
+#ifdef WIRELESS_SPY
+ case SIOCSIWSPY:
+ {
+ struct sockaddr address[IW_MAX_SPY];
+ /* Check the number of addresses */
+ if (wrq->u.data.length > IW_MAX_SPY) {
+ ret = -E2BIG;
+ break;
+ }
+ /* Get the data in the driver */
+ if (wrq->u.data.pointer) {
+ if (copy_from_user((char *) address,
+ wrq->u.data.pointer,
+ sizeof(struct sockaddr) *
+ wrq->u.data.length)) {
+ ret = -EFAULT;
+ break;
+ }
+ } else if (wrq->u.data.length != 0) {
+ ret = -EINVAL;
+ break;
+ }
+ ret = wavelan_set_spy(dev, NULL, &(wrq->u),
+ (char *) address);
+ }
+ break;
+ case SIOCGIWSPY:
+ {
+ char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
+ sizeof(struct iw_quality))];
+ ret = wavelan_get_spy(dev, NULL, &(wrq->u),
+ buffer);
+ if (wrq->u.data.pointer) {
+ if (copy_to_user(wrq->u.data.pointer,
+ buffer,
+ (wrq->u.data.length *
+ (sizeof(struct sockaddr) +
+ sizeof(struct iw_quality)))
+ ))
+ ret = -EFAULT;
+ }
+ }
break;
#endif /* WIRELESS_SPY */
@@ -2446,34 +3123,21 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
ret = -EPERM;
break;
}
- psa.psa_quality_thr = *(wrq->u.name) & 0x0F;
- psa_write(dev, (char *)&psa.psa_quality_thr - (char *)&psa,
- (unsigned char *)&psa.psa_quality_thr, 1);
- /* update the Wavelan checksum */
- update_psa_checksum(dev);
- mmc_out(base, mmwoff(0, mmw_quality_thr), psa.psa_quality_thr);
+ ret = wavelan_set_qthr(dev, NULL, &(wrq->u), NULL);
break;
case SIOCGIPQTHR:
- psa_read(dev, (char *)&psa.psa_quality_thr - (char *)&psa,
- (unsigned char *)&psa.psa_quality_thr, 1);
- *(wrq->u.name) = psa.psa_quality_thr & 0x0F;
+ ret = wavelan_get_qthr(dev, NULL, &(wrq->u), NULL);
break;
#ifdef WAVELAN_ROAMING
case SIOCSIPROAM:
/* Note : should check if user == root */
- if(do_roaming && (*wrq->u.name)==0)
- wv_roam_cleanup(dev);
- else if(do_roaming==0 && (*wrq->u.name)!=0)
- wv_roam_init(dev);
-
- do_roaming = (*wrq->u.name);
-
+ ret = wavelan_set_roam(dev, NULL, &(wrq->u), NULL);
break;
case SIOCGIPROAM:
- *(wrq->u.name) = do_roaming;
+ ret = wavelan_get_roam(dev, NULL, &(wrq->u), NULL);
break;
#endif /* WAVELAN_ROAMING */
@@ -2484,44 +3148,44 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
{
ret = -EPERM;
}
-
- /* Check the number of intervals */
- if(wrq->u.data.length > 16)
- {
- ret = -E2BIG;
- break;
+ {
+ char buffer[16];
+ /* Check the number of intervals */
+ if(wrq->u.data.length > 16)
+ {
+ ret = -E2BIG;
+ break;
}
- lp->his_number = wrq->u.data.length;
-
- /* If there is some addresses to copy */
- if(lp->his_number > 0)
- {
- /* Copy interval ranges to the driver */
- if(copy_from_user(lp->his_range, wrq->u.data.pointer,
- sizeof(char) * lp->his_number))
- {
- ret = -EFAULT;
- break;
- }
-
- /* Reset structure... */
- memset(lp->his_sum, 0x00, sizeof(long) * 16);
+ /* Get the data in the driver */
+ if (wrq->u.data.pointer) {
+ if (copy_from_user(buffer,
+ wrq->u.data.pointer,
+ sizeof(struct sockaddr) *
+ wrq->u.data.length)) {
+ ret = -EFAULT;
+ break;
+ }
+ } else if (wrq->u.data.length != 0) {
+ ret = -EINVAL;
+ break;
}
+ ret = wavelan_set_histo(dev, NULL, &(wrq->u),
+ buffer);
+ }
break;
case SIOCGIPHISTO:
- /* Set the number of intervals */
- wrq->u.data.length = lp->his_number;
-
- /* Give back the distribution statistics */
- if((lp->his_number > 0) && (wrq->u.data.pointer != (caddr_t) 0))
- {
- /* Copy data to the user buffer */
- if(copy_to_user(wrq->u.data.pointer, lp->his_sum,
- sizeof(long) * lp->his_number))
+ {
+ long buffer[16];
+ ret = wavelan_get_histo(dev, NULL, &(wrq->u),
+ (char *) buffer);
+ if (wrq->u.data.pointer) {
+ if (copy_to_user(wrq->u.data.pointer,
+ buffer,
+ (wrq->u.data.length * sizeof(long))))
ret = -EFAULT;
-
- } /* if(pointer != NULL) */
+ }
+ }
break;
#endif /* HISTOGRAM */
@@ -2531,14 +3195,12 @@ wavelan_ioctl(struct net_device * dev, /* Device on wich the ioctl apply */
ret = -EOPNOTSUPP;
}
- /* ReEnable interrupts & restore flags */
- wv_splx(lp, &flags);
-
#ifdef DEBUG_IOCTL_TRACE
printk(KERN_DEBUG "%s: <-wavelan_ioctl()\n", dev->name);
#endif
return ret;
}
+#endif /* WIRELESS_EXT > 12 */
/*------------------------------------------------------------------*/
/*
@@ -4530,7 +5192,11 @@ wavelan_attach(void)
dev->watchdog_timeo = WATCHDOG_JIFFIES;
#ifdef WIRELESS_EXT /* If wireless extension exist in the kernel */
+#if WIRELESS_EXT > 12
+ dev->wireless_handlers = (struct iw_handler_def *)&wavelan_handler_def;
+#else /* WIRELESS_EXT > 12 */
dev->do_ioctl = wavelan_ioctl; /* wireless extensions */
+#endif /* WIRELESS_EXT > 12 */
dev->get_wireless_stats = wavelan_get_wireless_stats;
#endif
diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h
index 67b19932aed4..6bdaa7fdc5d0 100644
--- a/drivers/net/wireless/wavelan_cs.p.h
+++ b/drivers/net/wireless/wavelan_cs.p.h
@@ -394,6 +394,12 @@
* o control first busy loop in wv_82593_cmd()
* o Extend spinlock protection in wv_hw_config()
*
+ * Changes made for release in 3.1.33 :
+ * ----------------------------------
+ * - Optional use new driver API for Wireless Extensions :
+ * o got rid of wavelan_ioctl()
+ * o use a bunch of iw_handler instead
+ *
* Wishes & dreams:
* ----------------
* - Cleanup and integrate the roaming code
@@ -430,6 +436,9 @@
#ifdef CONFIG_NET_RADIO
#include <linux/wireless.h> /* Wireless extensions */
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif /* WIRELESS_EXT > 12 */
#endif
/* Pcmcia headers that we need */
@@ -498,7 +507,7 @@
/************************ CONSTANTS & MACROS ************************/
#ifdef DEBUG_VERSION_SHOW
-static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/12/00\n";
+static const char *version = "wavelan_cs.c : v24 (SMP + wireless extensions) 11/1/02\n";
#endif
/* Watchdog temporisation */
@@ -523,8 +532,8 @@ static const char *version = "wavelan_cs.c : v23 (SMP + wireless extensions) 20/
#define SIOCSIPROAM SIOCIWFIRSTPRIV + 2 /* Set roaming state */
#define SIOCGIPROAM SIOCIWFIRSTPRIV + 3 /* Get roaming state */
-#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 6 /* Set histogram ranges */
-#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 7 /* Get histogram values */
+#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 4 /* Set histogram ranges */
+#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 5 /* Get histogram values */
/*************************** WaveLAN Roaming **************************/
#ifdef WAVELAN_ROAMING /* Conditional compile, see above in options */
@@ -589,6 +598,16 @@ typedef struct iw_freq iw_freq;
typedef struct net_local net_local;
typedef struct timer_list timer_list;
+#if WIRELESS_EXT <= 12
+/* Wireless extensions backward compatibility */
+/* Part of iw_handler prototype we need */
+struct iw_request_info
+{
+ __u16 cmd; /* Wireless Extension command */
+ __u16 flags; /* More to come ;-) */
+};
+#endif /* WIRELESS_EXT <= 12 */
+
/* Basic types */
typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */