summaryrefslogtreecommitdiff
path: root/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff
diff options
context:
space:
mode:
Diffstat (limited to 'linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff')
-rw-r--r--linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff1513
1 files changed, 0 insertions, 1513 deletions
diff --git a/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff b/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff
deleted file mode 100644
index a27a7654a9..0000000000
--- a/linux/openzaurus-pxa-2.4.18-rmk7-pxa3-embedix20031107/iw_handlers.w13-5.diff
+++ /dev/null
@@ -1,1513 +0,0 @@
-diff -u -p -r --new-file linux/include/linux-w12/netdevice.h linux/include/linux/netdevice.h
---- linux/include/linux-w12/netdevice.h Thu Nov 22 11:47:09 2001
-+++ linux/include/linux/netdevice.h Thu Jan 17 12:00:39 2002
-@@ -278,6 +278,10 @@ struct net_device
- struct net_device_stats* (*get_stats)(struct net_device *dev);
- struct iw_statistics* (*get_wireless_stats)(struct net_device *dev);
-
-+ /* List of functions to handle Wireless Extensions (instead of ioctl).
-+ * See <net/iw_handler.h> for details. Jean II */
-+ struct iw_handler_def * wireless_handlers;
-+
- /*
- * This marks the end of the "visible" part of the structure. All
- * fields hereafter are internal to the system, and may change at
-diff -u -p -r --new-file linux/include/linux-w12/wireless.h linux/include/linux/wireless.h
---- linux/include/linux-w12/wireless.h Thu Nov 22 11:47:12 2001
-+++ linux/include/linux/wireless.h Thu Jan 17 12:04:08 2002
-@@ -1,9 +1,10 @@
- /*
- * This file define a set of standard wireless extensions
- *
-- * Version : 12 5.10.01
-+ * Version : 13 6.12.01
- *
- * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-+ * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
- */
-
- #ifndef _LINUX_WIRELESS_H
-@@ -11,6 +12,8 @@
-
- /************************** DOCUMENTATION **************************/
- /*
-+ * Initial APIs (1996 -> onward) :
-+ * -----------------------------
- * Basically, the wireless extensions are for now a set of standard ioctl
- * call + /proc/net/wireless
- *
-@@ -27,16 +30,27 @@
- * We have the list of command plus a structure descibing the
- * data exchanged...
- * Note that to add these ioctl, I was obliged to modify :
-- * net/core/dev.c (two place + add include)
-- * net/ipv4/af_inet.c (one place + add include)
-+ * # net/core/dev.c (two place + add include)
-+ * # net/ipv4/af_inet.c (one place + add include)
- *
- * /proc/net/wireless is a copy of /proc/net/dev.
- * We have a structure for data passed from the driver to /proc/net/wireless
- * Too add this, I've modified :
-- * net/core/dev.c (two other places)
-- * include/linux/netdevice.h (one place)
-- * include/linux/proc_fs.h (one place)
-+ * # net/core/dev.c (two other places)
-+ * # include/linux/netdevice.h (one place)
-+ * # include/linux/proc_fs.h (one place)
-+ *
-+ * New driver API (2001 -> onward) :
-+ * -------------------------------
-+ * This file is only concerned with the user space API and common definitions.
-+ * The new driver API is defined and documented in :
-+ * # include/net/iw_handler.h
- *
-+ * Note as well that /proc/net/wireless implementation has now moved in :
-+ * # include/linux/wireless.c
-+ *
-+ * Other comments :
-+ * --------------
- * Do not add here things that are redundant with other mechanisms
- * (drivers init, ifconfig, /proc/net/dev, ...) and with are not
- * wireless specific.
-@@ -54,16 +68,14 @@
- #include <linux/socket.h> /* for "struct sockaddr" et al */
- #include <linux/if.h> /* for IFNAMSIZ and co... */
-
--/**************************** CONSTANTS ****************************/
--
--/* --------------------------- VERSION --------------------------- */
-+/***************************** VERSION *****************************/
- /*
- * This constant is used to know the availability of the wireless
- * extensions and to know which version of wireless extensions it is
- * (there is some stuff that will be added in the future...)
- * I just plan to increment with each new version.
- */
--#define WIRELESS_EXT 12
-+#define WIRELESS_EXT 13
-
- /*
- * Changes :
-@@ -123,12 +135,20 @@
- * - Add DEV PRIVATE IOCTL to avoid collisions in SIOCDEVPRIVATE space
- * - Add new statistics (frag, retry, beacon)
- * - Add average quality (for user space calibration)
-+ *
-+ * V12 to V13
-+ * ----------
-+ * - Document creation of new driver API.
-+ * - Extract union iwreq_data from struct iwreq (for new driver API).
-+ * - Rename SIOCSIWNAME as SIOCSIWCOMMIT
- */
-
-+/**************************** CONSTANTS ****************************/
-+
- /* -------------------------- IOCTL LIST -------------------------- */
-
- /* Basic operations */
--#define SIOCSIWNAME 0x8B00 /* Unused */
-+#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */
- #define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */
- #define SIOCSIWNWID 0x8B02 /* set network id (the cell) */
- #define SIOCGIWNWID 0x8B03 /* get network id */
-@@ -414,13 +434,49 @@ struct iw_statistics
-
- /* ------------------------ IOCTL REQUEST ------------------------ */
- /*
-+ * This structure defines the payload of an ioctl, and is used
-+ * below.
-+ *
-+ * Note that this structure should fit on the memory footprint
-+ * of iwreq (which is the same as ifreq), which mean a max size of
-+ * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
-+ * You should check this when increasing the structures defined
-+ * above in this file...
-+ */
-+union iwreq_data
-+{
-+ /* Config - generic */
-+ char name[IFNAMSIZ];
-+ /* Name : used to verify the presence of wireless extensions.
-+ * Name of the protocol/provider... */
-+
-+ struct iw_point essid; /* Extended network name */
-+ struct iw_param nwid; /* network id (or domain - the cell) */
-+ struct iw_freq freq; /* frequency or channel :
-+ * 0-1000 = channel
-+ * > 1000 = frequency in Hz */
-+
-+ struct iw_param sens; /* signal level threshold */
-+ struct iw_param bitrate; /* default bit rate */
-+ struct iw_param txpower; /* default transmit power */
-+ struct iw_param rts; /* RTS threshold threshold */
-+ struct iw_param frag; /* Fragmentation threshold */
-+ __u32 mode; /* Operation mode */
-+ struct iw_param retry; /* Retry limits & lifetime */
-+
-+ struct iw_point encoding; /* Encoding stuff : tokens */
-+ struct iw_param power; /* PM duration/timeout */
-+
-+ struct sockaddr ap_addr; /* Access point address */
-+
-+ struct iw_point data; /* Other large parameters */
-+};
-+
-+/*
- * The structure to exchange data for ioctl.
- * This structure is the same as 'struct ifreq', but (re)defined for
- * convenience...
-- *
-- * Note that it should fit on the same memory footprint !
-- * You should check this when increasing the above structures (16 octets)
-- * 16 octets = 128 bits. Warning, pointers might be 64 bits wide...
-+ * Do I need to remind you about structure size (32 octets) ?
- */
- struct iwreq
- {
-@@ -429,35 +485,8 @@ struct iwreq
- char ifrn_name[IFNAMSIZ]; /* if name, e.g. "eth0" */
- } ifr_ifrn;
-
-- /* Data part */
-- union
-- {
-- /* Config - generic */
-- char name[IFNAMSIZ];
-- /* Name : used to verify the presence of wireless extensions.
-- * Name of the protocol/provider... */
--
-- struct iw_point essid; /* Extended network name */
-- struct iw_param nwid; /* network id (or domain - the cell) */
-- struct iw_freq freq; /* frequency or channel :
-- * 0-1000 = channel
-- * > 1000 = frequency in Hz */
--
-- struct iw_param sens; /* signal level threshold */
-- struct iw_param bitrate; /* default bit rate */
-- struct iw_param txpower; /* default transmit power */
-- struct iw_param rts; /* RTS threshold threshold */
-- struct iw_param frag; /* Fragmentation threshold */
-- __u32 mode; /* Operation mode */
-- struct iw_param retry; /* Retry limits & lifetime */
--
-- struct iw_point encoding; /* Encoding stuff : tokens */
-- struct iw_param power; /* PM duration/timeout */
--
-- struct sockaddr ap_addr; /* Access point address */
--
-- struct iw_point data; /* Other large parameters */
-- } u;
-+ /* Data part (defined just above) */
-+ union iwreq_data u;
- };
-
- /* -------------------------- IOCTL DATA -------------------------- */
-diff -u -p -r --new-file linux/include/net-w12/iw_handler.h linux/include/net/iw_handler.h
---- linux/include/net-w12/iw_handler.h Wed Dec 31 16:00:00 1969
-+++ linux/include/net/iw_handler.h Thu Jan 17 12:16:46 2002
-@@ -0,0 +1,374 @@
-+/*
-+ * This file define the new driver API for Wireless Extensions
-+ *
-+ * Version : 2 6.12.01
-+ *
-+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-+ * Copyright (c) 2001 Jean Tourrilhes, All Rights Reserved.
-+ */
-+
-+#ifndef _IW_HANDLER_H
-+#define _IW_HANDLER_H
-+
-+/************************** DOCUMENTATION **************************/
-+/*
-+ * Initial driver API (1996 -> onward) :
-+ * -----------------------------------
-+ * The initial API just sends the IOCTL request received from user space
-+ * to the driver (via the driver ioctl handler). The driver has to
-+ * handle all the rest...
-+ *
-+ * The initial API also defines a specific handler in struct net_device
-+ * to handle wireless statistics.
-+ *
-+ * The initial APIs served us well and has proven a reasonably good design.
-+ * However, there is a few shortcommings :
-+ * o No events, everything is a request to the driver.
-+ * o Large ioctl function in driver with gigantic switch statement
-+ * (i.e. spaghetti code).
-+ * o Driver has to mess up with copy_to/from_user, and in many cases
-+ * does it unproperly. Common mistakes are :
-+ * * buffer overflows (no checks or off by one checks)
-+ * * call copy_to/from_user with irq disabled
-+ * o The user space interface is tied to ioctl because of the use
-+ * copy_to/from_user.
-+ *
-+ * New driver API (2001 -> onward) :
-+ * -------------------------------
-+ * The new driver API is just a bunch of standard functions (handlers),
-+ * each handling a specific Wireless Extension. The driver just export
-+ * the list of handler it supports, and those will be called apropriately.
-+ *
-+ * I tried to keep the main advantage of the previous API (simplicity,
-+ * efficiency and light weight), and also I provide a good dose of backward
-+ * compatibility (most structures are the same, driver can use both API
-+ * simultaneously, ...).
-+ * Hopefully, I've also addressed the shortcomming of the initial API.
-+ *
-+ * The advantage of the new API are :
-+ * o Handling of Extensions in driver broken in small contained functions
-+ * o Tighter checks of ioctl before calling the driver
-+ * o Flexible commit strategy (at least, the start of it)
-+ * o Backward compatibility (can be mixed with old API)
-+ * o Driver doesn't have to worry about memory and user-space issues
-+ * The last point is important for the following reasons :
-+ * o You are now able to call the new driver API from any API you
-+ * want (including from within other parts of the kernel).
-+ * o Common mistakes are avoided (buffer overflow, user space copy
-+ * with irq disabled and so on).
-+ *
-+ * The Drawback of the new API are :
-+ * o bloat (especially kernel)
-+ * o need to migrate existing drivers to new API
-+ * My initial testing shows that the new API adds around 3kB to the kernel
-+ * and save between 0 and 5kB from a typical driver.
-+ * Also, as all structures and data types are unchanged, the migration is
-+ * quite straightforward (but tedious).
-+ *
-+ * ---
-+ *
-+ * The new driver API is defined below in this file. User space should
-+ * not be aware of what's happening down there...
-+ *
-+ * A new kernel wrapper is in charge of validating the IOCTLs and calling
-+ * the appropriate driver handler. This is implemented in :
-+ * # net/core/wireless.c
-+ *
-+ * The driver export the list of handlers in :
-+ * # include/linux/netdevice.h (one place)
-+ *
-+ * The new driver API is available for WIRELESS_EXT >= 13.
-+ * Good luck with migration to the new API ;-)
-+ */
-+
-+/* ---------------------- THE IMPLEMENTATION ---------------------- */
-+/*
-+ * Some of the choice I've made are pretty controversials. Defining an
-+ * API is very much weighting compromises. This goes into some of the
-+ * details and the thinking behind the implementation.
-+ *
-+ * Implementation goals :
-+ * --------------------
-+ * The implementation goals were as follow :
-+ * o Obvious : you should not need a PhD to understand what's happening,
-+ * the benefit is easier maintainance.
-+ * o Flexible : it should accomodate a wide variety of driver
-+ * implementations and be as flexible as the old API.
-+ * o Lean : it should be efficient memory wise to minimise the impact
-+ * on kernel footprint.
-+ * o Transparent to user space : the large number of user space
-+ * applications that use Wireless Extensions should not need
-+ * any modifications.
-+ *
-+ * Array of functions versus Struct of functions
-+ * ---------------------------------------------
-+ * 1) Having an array of functions allow the kernel code to access the
-+ * handler in a single lookup, which is much more efficient (think hash
-+ * table here).
-+ * 2) The only drawback is that driver writer may put their handler in
-+ * the wrong slot. This is trivial to test (I set the frequency, the
-+ * bitrate changes). Once the handler is in the proper slot, it will be
-+ * there forever, because the array is only extended at the end.
-+ * 3) Backward/forward compatibility : adding new handler just require
-+ * extending the array, so you can put newer driver in older kernel
-+ * without having to patch the kernel code (and vice versa).
-+ *
-+ * All handler are of the same generic type
-+ * ----------------------------------------
-+ * That's a feature !!!
-+ * 1) Having a generic handler allow to have generic code, which is more
-+ * efficient. If each of the handler was individually typed I would need
-+ * to add a big switch in the kernel (== more bloat). This solution is
-+ * more scalable, adding new Wireless Extensions doesn't add new code.
-+ * 2) You can use the same handler in different slots of the array. For
-+ * hardware, it may be more efficient or logical to handle multiple
-+ * Wireless Extensions with a single function, and the API allow you to
-+ * do that. (An example would be a single record on the card to control
-+ * both bitrate and frequency, the handler would read the old record,
-+ * modify it according to info->cmd and rewrite it).
-+ *
-+ * Functions prototype uses union iwreq_data
-+ * -----------------------------------------
-+ * Some would have prefered functions defined this way :
-+ * static int mydriver_ioctl_setrate(struct net_device *dev,
-+ * long rate, int auto)
-+ * 1) The kernel code doesn't "validate" the content of iwreq_data, and
-+ * can't do it (different hardware may have different notion of what a
-+ * valid frequency is), so we don't pretend that we do it.
-+ * 2) The above form is not extendable. If I want to add a flag (for
-+ * example to distinguish setting max rate and basic rate), I would
-+ * break the prototype. Using iwreq_data is more flexible.
-+ * 3) Also, the above form is not generic (see above).
-+ * 4) I don't expect driver developper using the wrong field of the
-+ * union (Doh !), so static typechecking doesn't add much value.
-+ * 5) Lastly, you can skip the union by doing :
-+ * static int mydriver_ioctl_setrate(struct net_device *dev,
-+ * struct iw_request_info *info,
-+ * struct iw_param *rrq,
-+ * char *extra)
-+ * And then adding the handler in the array like this :
-+ * (iw_handler) mydriver_ioctl_setrate, // SIOCSIWRATE
-+ *
-+ * Using functions and not a registry
-+ * ----------------------------------
-+ * Another implementation option would have been for every instance to
-+ * define a registry (a struct containing all the Wireless Extensions)
-+ * and only have a function to commit the registry to the hardware.
-+ * 1) This approach can be emulated by the current code, but not
-+ * vice versa.
-+ * 2) Some drivers don't keep any configuration in the driver, for them
-+ * adding such a registry would be a significant bloat.
-+ * 3) The code to translate from Wireless Extension to native format is
-+ * needed anyway, so it would not reduce significantely the amount of code.
-+ * 4) The current approach only selectively translate Wireless Extensions
-+ * to native format and only selectively set, whereas the registry approach
-+ * would require to translate all WE and set all parameters for any single
-+ * change.
-+ * 5) For many Wireless Extensions, the GET operation return the current
-+ * dynamic value, not the value that was set.
-+ *
-+ * This header is <net/iw_handler.h>
-+ * ---------------------------------
-+ * 1) This header is kernel space only and should not be exported to
-+ * user space. Headers in "include/linux/" are exported, headers in
-+ * "include/net/" are not.
-+ *
-+ * Mixed 32/64 bit issues
-+ * ----------------------
-+ * The Wireless Extensions are designed to be 64 bit clean, by using only
-+ * datatypes with explicit storage size.
-+ * There are some issues related to kernel and user space using different
-+ * memory model, and in particular 64bit kernel with 32bit user space.
-+ * The problem is related to struct iw_point, that contains a pointer
-+ * that *may* need to be translated.
-+ * This is quite messy. The new API doesn't solve this problem (it can't),
-+ * but is a step in the right direction :
-+ * 1) Meta data about each ioctl is easily available, so we know what type
-+ * of translation is needed.
-+ * 2) The move of data between kernel and user space is only done in a single
-+ * place in the kernel, so adding specific hooks in there is possible.
-+ * 3) In the long term, it allows to move away from using ioctl as the
-+ * user space API.
-+ *
-+ * So many comments and so few code
-+ * --------------------------------
-+ * That's a feature. Comments won't bloat the resulting kernel binary.
-+ */
-+
-+/***************************** INCLUDES *****************************/
-+
-+#include <linux/wireless.h> /* IOCTL user space API */
-+
-+/***************************** VERSION *****************************/
-+/*
-+ * This constant is used to know which version of the driver API is
-+ * available. Hopefully, this will be pretty stable and no changes
-+ * will be needed...
-+ * I just plan to increment with each new version.
-+ */
-+#define IW_HANDLER_VERSION 2
-+
-+/**************************** CONSTANTS ****************************/
-+
-+/* Special error message for the driver to indicate that we
-+ * should do a commit after return from the iw_handler */
-+#define EIWCOMMIT EINPROGRESS
-+
-+/* Flags available in struct iw_request_info */
-+#define IW_REQUEST_FLAG_NONE 0x0000 /* No flag so far */
-+
-+/* Type of headers we know about (basically union iwreq_data) */
-+#define IW_HEADER_TYPE_NULL 0 /* Not available */
-+#define IW_HEADER_TYPE_CHAR 2 /* char [IFNAMSIZ] */
-+#define IW_HEADER_TYPE_UINT 4 /* __u32 */
-+#define IW_HEADER_TYPE_FREQ 5 /* struct iw_freq */
-+#define IW_HEADER_TYPE_POINT 6 /* struct iw_point */
-+#define IW_HEADER_TYPE_PARAM 7 /* struct iw_param */
-+#define IW_HEADER_TYPE_ADDR 8 /* struct sockaddr */
-+
-+/* Handling flags */
-+/* Most are not implemented. I just use them as a reminder of some
-+ * cool features we might need one day ;-) */
-+#define IW_DESCR_FLAG_NONE 0x0000 /* Obvious */
-+/* Wrapper level flags */
-+#define IW_DESCR_FLAG_DUMP 0x0001 /* Not part of the dump command */
-+#define IW_DESCR_FLAG_EVENT 0x0002 /* Generate an event on SET */
-+#define IW_DESCR_FLAG_RESTRICT 0x0004 /* GET request is ROOT only */
-+/* Driver level flags */
-+#define IW_DESCR_FLAG_WAIT 0x0100 /* Wait for driver event */
-+
-+/****************************** TYPES ******************************/
-+
-+/* ----------------------- WIRELESS HANDLER ----------------------- */
-+/*
-+ * A wireless handler is just a standard function, that looks like the
-+ * ioctl handler.
-+ * We also define there how a handler list look like... As the Wireless
-+ * Extension space is quite dense, we use a simple array, which is faster
-+ * (that's the perfect hash table ;-).
-+ */
-+
-+/*
-+ * Meta data about the request passed to the iw_handler.
-+ * Most handlers can safely ignore what's in there.
-+ * The 'cmd' field might come handy if you want to use the same handler
-+ * for multiple command...
-+ * This struct is also my long term insurance. I can add new fields here
-+ * without breaking the prototype of iw_handler...
-+ */
-+struct iw_request_info
-+{
-+ __u16 cmd; /* Wireless Extension command */
-+ __u16 flags; /* More to come ;-) */
-+};
-+
-+/*
-+ * This is how a function handling a Wireless Extension should look
-+ * like (both get and set, standard and private).
-+ */
-+typedef int (*iw_handler)(struct net_device *dev, struct iw_request_info *info,
-+ union iwreq_data *wrqu, char *extra);
-+
-+/*
-+ * This define all the handler that the driver export.
-+ * As you need only one per driver type, please use a static const
-+ * shared by all driver instances... Same for the members...
-+ * This will be linked from net_device in <linux/netdevice.h>
-+ */
-+struct iw_handler_def
-+{
-+ /* Number of handlers defined (more precisely, index of the
-+ * last defined handler + 1) */
-+ __u16 num_standard;
-+ __u16 num_private;
-+ /* Number of private arg description */
-+ __u16 num_private_args;
-+
-+ /* Array of handlers for standard ioctls
-+ * We will call dev->wireless_handlers->standard[ioctl - SIOCSIWNAME]
-+ */
-+ iw_handler * standard;
-+
-+ /* Array of handlers for private ioctls
-+ * Will call dev->wireless_handlers->private[ioctl - SIOCIWFIRSTPRIV]
-+ */
-+ iw_handler * private;
-+
-+ /* Arguments of private handler. This one is just a list, so you
-+ * can put it in any order you want and should not leave holes...
-+ * We will automatically export that to user space... */
-+ struct iw_priv_args * private_args;
-+
-+ /* In the long term, get_wireless_stats will move from
-+ * 'struct net_device' to here, to minimise bloat. */
-+};
-+
-+/* ----------------------- WIRELESS EVENTS ----------------------- */
-+/*
-+ * Currently we don't support events, so let's just plan for the
-+ * future...
-+ */
-+
-+/*
-+ * A Wireless Event.
-+ */
-+// How do we define short header ? We don't want a flag on length.
-+// Probably a flag on event ? Highest bit to zero...
-+struct iw_event
-+{
-+ __u16 length; /* Lenght of this stuff */
-+ __u16 event; /* Wireless IOCTL */
-+ union iwreq_data header; /* IOCTL fixed payload */
-+ char extra[0]; /* Optional IOCTL data */
-+};
-+
-+/* ---------------------- IOCTL DESCRIPTION ---------------------- */
-+/*
-+ * One of the main goal of the new interface is to deal entirely with
-+ * user space/kernel space memory move.
-+ * For that, we need to know :
-+ * o if iwreq is a pointer or contain the full data
-+ * o what is the size of the data to copy
-+ *
-+ * For private IOCTLs, we use the same rules as used by iwpriv and
-+ * defined in struct iw_priv_args.
-+ *
-+ * For standard IOCTLs, things are quite different and we need to
-+ * use the stuctures below. Actually, this struct is also more
-+ * efficient, but that's another story...
-+ */
-+
-+/*
-+ * Describe how a standard IOCTL looks like.
-+ */
-+struct iw_ioctl_description
-+{
-+ __u8 header_type; /* NULL, iw_point or other */
-+ __u8 token_type; /* Future */
-+ __u16 token_size; /* Granularity of payload */
-+ __u16 min_tokens; /* Min acceptable token number */
-+ __u16 max_tokens; /* Max acceptable token number */
-+ __u32 flags; /* Special handling of the request */
-+};
-+
-+/* Need to think of short header translation table. Later. */
-+
-+/**************************** PROTOTYPES ****************************/
-+/*
-+ * Functions part of the Wireless Extensions (defined in net/core/wireless.c).
-+ * Those may be called only within the kernel.
-+ */
-+
-+/* First : function strictly used inside the kernel */
-+
-+/* Handle /proc/net/wireless, called in net/code/dev.c */
-+extern int dev_get_wireless_info(char * buffer, char **start, off_t offset,
-+ int length);
-+
-+/* Handle IOCTLs, called in net/code/dev.c */
-+extern int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd);
-+
-+/* Second : functions that may be called by driver modules */
-+/* None yet */
-+
-+#endif /* _LINUX_WIRELESS_H */
-diff -u -p -r --new-file linux/net/core-w12/Makefile linux/net/core/Makefile
---- linux/net/core-w12/Makefile Tue Oct 30 15:08:12 2001
-+++ linux/net/core/Makefile Thu Jan 17 11:06:07 2002
-@@ -26,5 +26,8 @@ obj-$(CONFIG_NET) += dev.o dev_mcast.o d
- obj-$(CONFIG_NETFILTER) += netfilter.o
- obj-$(CONFIG_NET_DIVERT) += dv.o
- obj-$(CONFIG_NET_PROFILE) += profile.o
-+obj-$(CONFIG_NET_RADIO) += wireless.o
-+# Ugly. I wish all wireless drivers were moved in drivers/net/wireless
-+obj-$(CONFIG_NET_PCMCIA_RADIO) += wireless.o
-
- include $(TOPDIR)/Rules.make
-diff -u -p -r --new-file linux/net/core-w12/dev.c linux/net/core/dev.c
---- linux/net/core-w12/dev.c Wed Nov 7 14:39:36 2001
-+++ linux/net/core/dev.c Thu Jan 17 11:06:07 2002
-@@ -102,6 +102,7 @@
- #include <linux/module.h>
- #if defined(CONFIG_NET_RADIO) || defined(CONFIG_NET_PCMCIA_RADIO)
- #include <linux/wireless.h> /* Note : will define WIRELESS_EXT */
-+#include <net/iw_handler.h>
- #endif /* CONFIG_NET_RADIO || CONFIG_NET_PCMCIA_RADIO */
- #ifdef CONFIG_PLIP
- extern int plip_init(void);
-@@ -1796,122 +1797,6 @@ static int dev_proc_stats(char *buffer,
- #endif /* CONFIG_PROC_FS */
-
-
--#ifdef WIRELESS_EXT
--#ifdef CONFIG_PROC_FS
--
--/*
-- * Print one entry of /proc/net/wireless
-- * This is a clone of /proc/net/dev (just above)
-- */
--static int sprintf_wireless_stats(char *buffer, struct net_device *dev)
--{
-- /* Get stats from the driver */
-- struct iw_statistics *stats = (dev->get_wireless_stats ?
-- dev->get_wireless_stats(dev) :
-- (struct iw_statistics *) NULL);
-- int size;
--
-- if (stats != (struct iw_statistics *) NULL) {
-- size = sprintf(buffer,
-- "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n",
-- dev->name,
-- stats->status,
-- stats->qual.qual,
-- stats->qual.updated & 1 ? '.' : ' ',
-- stats->qual.level,
-- stats->qual.updated & 2 ? '.' : ' ',
-- stats->qual.noise,
-- stats->qual.updated & 4 ? '.' : ' ',
-- stats->discard.nwid,
-- stats->discard.code,
-- stats->discard.fragment,
-- stats->discard.retries,
-- stats->discard.misc,
-- stats->miss.beacon);
-- stats->qual.updated = 0;
-- }
-- else
-- size = 0;
--
-- return size;
--}
--
--/*
-- * Print info for /proc/net/wireless (print all entries)
-- * This is a clone of /proc/net/dev (just above)
-- */
--static int dev_get_wireless_info(char * buffer, char **start, off_t offset,
-- int length)
--{
-- int len = 0;
-- off_t begin = 0;
-- off_t pos = 0;
-- int size;
--
-- struct net_device * dev;
--
-- size = sprintf(buffer,
-- "Inter-| sta-| Quality | Discarded packets | Missed\n"
-- " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
-- );
--
-- pos += size;
-- len += size;
--
-- read_lock(&dev_base_lock);
-- for (dev = dev_base; dev != NULL; dev = dev->next) {
-- size = sprintf_wireless_stats(buffer + len, dev);
-- len += size;
-- pos = begin + len;
--
-- if (pos < offset) {
-- len = 0;
-- begin = pos;
-- }
-- if (pos > offset + length)
-- break;
-- }
-- read_unlock(&dev_base_lock);
--
-- *start = buffer + (offset - begin); /* Start of wanted data */
-- len -= (offset - begin); /* Start slop */
-- if (len > length)
-- len = length; /* Ending slop */
-- if (len < 0)
-- len = 0;
--
-- return len;
--}
--#endif /* CONFIG_PROC_FS */
--
--/*
-- * Allow programatic access to /proc/net/wireless even if /proc
-- * doesn't exist... Also more efficient...
-- */
--static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
--{
-- /* Get stats from the driver */
-- struct iw_statistics *stats = (dev->get_wireless_stats ?
-- dev->get_wireless_stats(dev) :
-- (struct iw_statistics *) NULL);
--
-- if (stats != (struct iw_statistics *) NULL) {
-- struct iwreq * wrq = (struct iwreq *)ifr;
--
-- /* Copy statistics to the user buffer */
-- if(copy_to_user(wrq->u.data.pointer, stats,
-- sizeof(struct iw_statistics)))
-- return -EFAULT;
--
-- /* Check if we need to clear the update flag */
-- if(wrq->u.data.flags != 0)
-- stats->qual.updated = 0;
-- return(0);
-- } else
-- return -EOPNOTSUPP;
--}
--#endif /* WIRELESS_EXT */
--
- /**
- * netdev_set_master - set up master/slave pair
- * @slave: slave device
-@@ -2209,11 +2094,6 @@ static int dev_ifsioc(struct ifreq *ifr,
- notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
- return 0;
-
--#ifdef WIRELESS_EXT
-- case SIOCGIWSTATS:
-- return dev_iwstats(dev, ifr);
--#endif /* WIRELESS_EXT */
--
- /*
- * Unknown or private ioctl
- */
-@@ -2239,17 +2119,6 @@ static int dev_ifsioc(struct ifreq *ifr,
- return -EOPNOTSUPP;
- }
-
--#ifdef WIRELESS_EXT
-- if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) {
-- if (dev->do_ioctl) {
-- if (!netif_device_present(dev))
-- return -ENODEV;
-- return dev->do_ioctl(dev, ifr, cmd);
-- }
-- return -EOPNOTSUPP;
-- }
--#endif /* WIRELESS_EXT */
--
- }
- return -EINVAL;
- }
-@@ -2431,7 +2300,8 @@ int dev_ioctl(unsigned int cmd, void *ar
- }
- dev_load(ifr.ifr_name);
- rtnl_lock();
-- ret = dev_ifsioc(&ifr, cmd);
-+ /* Follow me in net/core/wireless.c */
-+ ret = wireless_process_ioctl(&ifr, cmd);
- rtnl_unlock();
- if (!ret && IW_IS_GET(cmd) &&
- copy_to_user(arg, &ifr, sizeof(struct ifreq)))
-@@ -2856,6 +2726,7 @@ int __init net_dev_init(void)
- proc_net_create("dev", 0, dev_get_info);
- create_proc_read_entry("net/softnet_stat", 0, 0, dev_proc_stats, NULL);
- #ifdef WIRELESS_EXT
-+ /* Available in net/core/wireless.c */
- proc_net_create("wireless", 0, dev_get_wireless_info);
- #endif /* WIRELESS_EXT */
- #endif /* CONFIG_PROC_FS */
-diff -u -p -r --new-file linux/net/core-w12/wireless.c linux/net/core/wireless.c
---- linux/net/core-w12/wireless.c Wed Dec 31 16:00:00 1969
-+++ linux/net/core/wireless.c Mon Jan 21 11:13:23 2002
-@@ -0,0 +1,733 @@
-+/*
-+ * This file implement the Wireless Extensions APIs.
-+ *
-+ * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
-+ * Copyright (c) 1997-2001 Jean Tourrilhes, All Rights Reserved.
-+ *
-+ * (As all part of the Linux kernel, this file is GPL)
-+ */
-+
-+/************************** DOCUMENTATION **************************/
-+/*
-+ * API definition :
-+ * --------------
-+ * See <linux/wireless.h> for details of the APIs and the rest.
-+ *
-+ * History :
-+ * -------
-+ *
-+ * v1 - 5.12.01 - Jean II
-+ * o Created this file.
-+ *
-+ * v2 - 13.12.01 - Jean II
-+ * o Move /proc/net/wireless stuff from net/core/dev.c to here
-+ * o Make Wireless Extension IOCTLs go through here
-+ * o Added iw_handler handling ;-)
-+ * o Added standard ioctl description
-+ * o Initial dumb commit strategy based on orinoco.c
-+ */
-+
-+/***************************** INCLUDES *****************************/
-+
-+#include <asm/uaccess.h> /* copy_to_user() */
-+#include <linux/config.h> /* Not needed ??? */
-+#include <linux/types.h> /* off_t */
-+#include <linux/netdevice.h> /* struct ifreq, dev_get_by_name() */
-+
-+#include <linux/wireless.h> /* Pretty obvious */
-+#include <net/iw_handler.h> /* New driver API */
-+
-+/**************************** CONSTANTS ****************************/
-+
-+/* This will be turned on later on... */
-+#undef WE_STRICT_WRITE /* Check write buffer size */
-+
-+/* Debuging stuff */
-+#undef WE_IOCTL_DEBUG /* Debug IOCTL API */
-+
-+/************************* GLOBAL VARIABLES *************************/
-+/*
-+ * You should not use global variables, because or re-entrancy.
-+ * On our case, it's only const, so it's OK...
-+ */
-+static const struct iw_ioctl_description standard_ioctl[] = {
-+ /* SIOCSIWCOMMIT (internal) */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCGIWNAME */
-+ { IW_HEADER_TYPE_CHAR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWNWID */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-+ /* SIOCGIWNWID */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWFREQ */
-+ { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-+ /* SIOCGIWFREQ */
-+ { IW_HEADER_TYPE_FREQ, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWMODE */
-+ { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_EVENT},
-+ /* SIOCGIWMODE */
-+ { IW_HEADER_TYPE_UINT, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWSENS */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWSENS */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWRANGE */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCGIWRANGE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, sizeof(struct iw_range), IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWPRIV */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCGIWPRIV (handled directly by us) */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWSTATS */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCGIWSTATS (handled directly by us) */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWSPY */
-+ { IW_HEADER_TYPE_POINT, 0, sizeof(struct sockaddr), 0, IW_MAX_SPY, 0},
-+ /* SIOCGIWSPY */
-+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_SPY, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWAP */
-+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, 0},
-+ /* SIOCGIWAP */
-+ { IW_HEADER_TYPE_ADDR, 0, 0, 0, 0, IW_DESCR_FLAG_DUMP},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCGIWAPLIST */
-+ { IW_HEADER_TYPE_POINT, 0, (sizeof(struct sockaddr) + sizeof(struct iw_quality)), 0, IW_MAX_AP, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWESSID */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_EVENT},
-+ /* SIOCGIWESSID */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, IW_DESCR_FLAG_DUMP},
-+ /* SIOCSIWNICKN */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
-+ /* SIOCGIWNICKN */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ESSID_MAX_SIZE, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* -- hole -- */
-+ { IW_HEADER_TYPE_NULL, 0, 0, 0, 0, 0},
-+ /* SIOCSIWRATE */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWRATE */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWRTS */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWRTS */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWFRAG */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWFRAG */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWTXPOW */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWTXPOW */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWRETRY */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWRETRY */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCSIWENCODE */
-+ { IW_HEADER_TYPE_POINT, 4, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_EVENT | IW_DESCR_FLAG_RESTRICT},
-+ /* SIOCGIWENCODE */
-+ { IW_HEADER_TYPE_POINT, 0, 1, 0, IW_ENCODING_TOKEN_MAX, IW_DESCR_FLAG_DUMP | IW_DESCR_FLAG_RESTRICT},
-+ /* SIOCSIWPOWER */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+ /* SIOCGIWPOWER */
-+ { IW_HEADER_TYPE_PARAM, 0, 0, 0, 0, 0},
-+};
-+
-+/* Size (in bytes) of the various private data types */
-+char priv_type_size[] = { 0, 1, 1, 0, 4, 4, 0, 0 };
-+
-+/************************ COMMON SUBROUTINES ************************/
-+/*
-+ * Stuff that may be used in various place or doesn't fit in one
-+ * of the section below.
-+ */
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Return the driver handler associated with a specific Wireless Extension.
-+ * Called from various place, so make sure it remains efficient.
-+ */
-+static inline iw_handler get_handler(struct net_device *dev,
-+ unsigned int cmd)
-+{
-+ unsigned int index; /* MUST be unsigned */
-+
-+ /* Check if we have some wireless handlers defined */
-+ if(dev->wireless_handlers == NULL)
-+ return NULL;
-+
-+ /* Try as a standard command */
-+ index = cmd - SIOCIWFIRST;
-+ if(index < dev->wireless_handlers->num_standard)
-+ return dev->wireless_handlers->standard[index];
-+
-+ /* Try as a private command */
-+ index = cmd - SIOCIWFIRSTPRIV;
-+ if(index < dev->wireless_handlers->num_private)
-+ return dev->wireless_handlers->private[index];
-+
-+ /* Not found */
-+ return NULL;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Get statistics out of the driver
-+ */
-+static inline struct iw_statistics *get_wireless_stats(struct net_device *dev)
-+{
-+ return (dev->get_wireless_stats ?
-+ dev->get_wireless_stats(dev) :
-+ (struct iw_statistics *) NULL);
-+ /* In the future, get_wireless_stats may move from 'struct net_device'
-+ * to 'struct iw_handler_def', to de-bloat struct net_device.
-+ * Definitely worse a thought... */
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Call the commit handler in the driver
-+ * (if exist and if conditions are right)
-+ *
-+ * Note : our current commit strategy is currently pretty dumb,
-+ * but we will be able to improve on that...
-+ * The goal is to try to agreagate as many changes as possible
-+ * before doing the commit. Drivers that will define a commit handler
-+ * are usually those that need a reset after changing parameters, so
-+ * we want to minimise the number of reset.
-+ * A cool idea is to use a timer : at each "set" command, we re-set the
-+ * timer, when the timer eventually fires, we call the driver.
-+ * Hopefully, more on that later.
-+ *
-+ * Also, I'm waiting to see how many people will complain about the
-+ * netif_running(dev) test. I'm open on that one...
-+ * Hopefully, the driver will remember to do a commit in "open()" ;-)
-+ */
-+static inline int call_commit_handler(struct net_device * dev)
-+{
-+ if((netif_running(dev)) &&
-+ (dev->wireless_handlers->standard[0] != NULL)) {
-+ /* Call the commit handler on the driver */
-+ return dev->wireless_handlers->standard[0](dev, NULL,
-+ NULL, NULL);
-+ } else
-+ return 0; /* Command completed successfully */
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Number of private arguments
-+ */
-+static inline int get_priv_size(__u16 args)
-+{
-+ int num = args & IW_PRIV_SIZE_MASK;
-+ int type = (args & IW_PRIV_TYPE_MASK) >> 12;
-+
-+ return num * priv_type_size[type];
-+}
-+
-+
-+/******************** /proc/net/wireless SUPPORT ********************/
-+/*
-+ * The /proc/net/wireless file is a human readable user-space interface
-+ * exporting various wireless specific statistics from the wireless devices.
-+ * This is the most popular part of the Wireless Extensions ;-)
-+ *
-+ * This interface is a pure clone of /proc/net/dev (in net/core/dev.c).
-+ * The content of the file is basically the content of "struct iw_statistics".
-+ */
-+
-+#ifdef CONFIG_PROC_FS
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Print one entry (line) of /proc/net/wireless
-+ */
-+static inline int sprintf_wireless_stats(char *buffer, struct net_device *dev)
-+{
-+ /* Get stats from the driver */
-+ struct iw_statistics *stats;
-+ int size;
-+
-+ stats = get_wireless_stats(dev);
-+ if (stats != (struct iw_statistics *) NULL) {
-+ size = sprintf(buffer,
-+ "%6s: %04x %3d%c %3d%c %3d%c %6d %6d %6d %6d %6d %6d\n",
-+ dev->name,
-+ stats->status,
-+ stats->qual.qual,
-+ stats->qual.updated & 1 ? '.' : ' ',
-+ stats->qual.level,
-+ stats->qual.updated & 2 ? '.' : ' ',
-+ stats->qual.noise,
-+ stats->qual.updated & 4 ? '.' : ' ',
-+ stats->discard.nwid,
-+ stats->discard.code,
-+ stats->discard.fragment,
-+ stats->discard.retries,
-+ stats->discard.misc,
-+ stats->miss.beacon);
-+ stats->qual.updated = 0;
-+ }
-+ else
-+ size = 0;
-+
-+ return size;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Print info for /proc/net/wireless (print all entries)
-+ */
-+int dev_get_wireless_info(char * buffer, char **start, off_t offset,
-+ int length)
-+{
-+ int len = 0;
-+ off_t begin = 0;
-+ off_t pos = 0;
-+ int size;
-+
-+ struct net_device * dev;
-+
-+ size = sprintf(buffer,
-+ "Inter-| sta-| Quality | Discarded packets | Missed\n"
-+ " face | tus | link level noise | nwid crypt frag retry misc | beacon\n"
-+ );
-+
-+ pos += size;
-+ len += size;
-+
-+ read_lock(&dev_base_lock);
-+ for (dev = dev_base; dev != NULL; dev = dev->next) {
-+ size = sprintf_wireless_stats(buffer + len, dev);
-+ len += size;
-+ pos = begin + len;
-+
-+ if (pos < offset) {
-+ len = 0;
-+ begin = pos;
-+ }
-+ if (pos > offset + length)
-+ break;
-+ }
-+ read_unlock(&dev_base_lock);
-+
-+ *start = buffer + (offset - begin); /* Start of wanted data */
-+ len -= (offset - begin); /* Start slop */
-+ if (len > length)
-+ len = length; /* Ending slop */
-+ if (len < 0)
-+ len = 0;
-+
-+ return len;
-+}
-+#endif /* CONFIG_PROC_FS */
-+
-+/************************** IOCTL SUPPORT **************************/
-+/*
-+ * The original user space API to configure all those Wireless Extensions
-+ * is through IOCTLs.
-+ * In there, we check if we need to call the new driver API (iw_handler)
-+ * or just call the driver ioctl handler.
-+ */
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Allow programatic access to /proc/net/wireless even if /proc
-+ * doesn't exist... Also more efficient...
-+ */
-+static inline int dev_iwstats(struct net_device *dev, struct ifreq *ifr)
-+{
-+ /* Get stats from the driver */
-+ struct iw_statistics *stats;
-+
-+ stats = get_wireless_stats(dev);
-+ if (stats != (struct iw_statistics *) NULL) {
-+ struct iwreq * wrq = (struct iwreq *)ifr;
-+
-+ /* Copy statistics to the user buffer */
-+ if(copy_to_user(wrq->u.data.pointer, stats,
-+ sizeof(struct iw_statistics)))
-+ return -EFAULT;
-+
-+ /* Check if we need to clear the update flag */
-+ if(wrq->u.data.flags != 0)
-+ stats->qual.updated = 0;
-+ return 0;
-+ } else
-+ return -EOPNOTSUPP;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Export the driver private handler definition
-+ * They will be picked up by tools like iwpriv...
-+ */
-+static inline int ioctl_export_private(struct net_device * dev,
-+ struct ifreq * ifr)
-+{
-+ struct iwreq * iwr = (struct iwreq *) ifr;
-+
-+ /* Check if the driver has something to export */
-+ if((dev->wireless_handlers->num_private_args == 0) ||
-+ (dev->wireless_handlers->private_args == NULL))
-+ return -EOPNOTSUPP;
-+
-+ /* Check NULL pointer */
-+ if(iwr->u.data.pointer == NULL)
-+ return -EFAULT;
-+#ifdef WE_STRICT_WRITE
-+ /* Check if there is enough buffer up there */
-+ if(iwr->u.data.length < (SIOCIWLASTPRIV - SIOCIWFIRSTPRIV + 1))
-+ return -E2BIG;
-+#endif /* WE_STRICT_WRITE */
-+
-+ /* Set the number of available ioctls. */
-+ iwr->u.data.length = dev->wireless_handlers->num_private_args;
-+
-+ /* Copy structure to the user buffer. */
-+ if (copy_to_user(iwr->u.data.pointer,
-+ dev->wireless_handlers->private_args,
-+ sizeof(struct iw_priv_args) * iwr->u.data.length))
-+ return -EFAULT;
-+
-+ return 0;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Wrapper to call a standard Wireless Extension handler.
-+ * We do various checks and also take care of moving data between
-+ * user space and kernel space.
-+ */
-+static inline int ioctl_standard_call(struct net_device * dev,
-+ struct ifreq * ifr,
-+ unsigned int cmd,
-+ iw_handler handler)
-+{
-+ struct iwreq * iwr = (struct iwreq *) ifr;
-+ const struct iw_ioctl_description * descr;
-+ struct iw_request_info info;
-+ int ret = -EINVAL;
-+
-+ /* Get the description of the IOCTL */
-+ descr = &(standard_ioctl[cmd - SIOCIWFIRST]);
-+
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "%s : Found standard handler for 0x%04X\n",
-+ ifr->ifr_name, cmd);
-+ printk(KERN_DEBUG "Header type : %d, token type : %d, token_size : %d, max_token : %d\n", descr->header_type, descr->token_type, descr->token_size, descr->max_tokens);
-+#endif /* WE_IOCTL_DEBUG */
-+
-+ /* Prepare the call */
-+ info.cmd = cmd;
-+ info.flags = 0;
-+
-+ /* Check if we have a pointer to user space data or not */
-+ if(descr->header_type != IW_HEADER_TYPE_POINT) {
-+ /* No extra arguments. Trivial to handle */
-+ ret = handler(dev, &info, &(iwr->u), NULL);
-+ } else {
-+ char * extra;
-+ int err;
-+
-+ /* Check what user space is giving us */
-+ if(IW_IS_SET(cmd)) {
-+ /* Check NULL pointer */
-+ if((iwr->u.data.pointer == NULL) &&
-+ (iwr->u.data.length != 0))
-+ return -EFAULT;
-+ /* Check if number of token fits within bounds */
-+ if(iwr->u.data.length > descr->max_tokens)
-+ return -E2BIG;
-+ if(iwr->u.data.length < descr->min_tokens)
-+ return -EINVAL;
-+ } else {
-+ /* Check NULL pointer */
-+ if(iwr->u.data.pointer == NULL)
-+ return -EFAULT;
-+#ifdef WE_STRICT_WRITE
-+ /* Check if there is enough buffer up there */
-+ if(iwr->u.data.length < descr->max_tokens)
-+ return -E2BIG;
-+#endif /* WE_STRICT_WRITE */
-+ }
-+
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Malloc %d bytes\n",
-+ descr->max_tokens * descr->token_size);
-+#endif /* WE_IOCTL_DEBUG */
-+
-+ /* Always allocate for max space. Easier, and won't last
-+ * long... */
-+ extra = kmalloc(descr->max_tokens * descr->token_size,
-+ GFP_KERNEL);
-+ if (extra == NULL) {
-+ return -ENOMEM;
-+ }
-+
-+ /* If it is a SET, get all the extra data in here */
-+ if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
-+ err = copy_from_user(extra, iwr->u.data.pointer,
-+ iwr->u.data.length *
-+ descr->token_size);
-+ if (err) {
-+ kfree(extra);
-+ return -EFAULT;
-+ }
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Got %d bytes\n",
-+ iwr->u.data.length * descr->token_size);
-+#endif /* WE_IOCTL_DEBUG */
-+ }
-+
-+ /* Call the handler */
-+ ret = handler(dev, &info, &(iwr->u), extra);
-+
-+ /* If we have something to return to the user */
-+ if (!ret && IW_IS_GET(cmd)) {
-+ err = copy_to_user(iwr->u.data.pointer, extra,
-+ iwr->u.data.length *
-+ descr->token_size);
-+ if (err)
-+ ret = -EFAULT;
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Wrote %d bytes\n",
-+ iwr->u.data.length * descr->token_size);
-+#endif /* WE_IOCTL_DEBUG */
-+ }
-+
-+ /* Cleanup - I told you it wasn't that long ;-) */
-+ kfree(extra);
-+ }
-+
-+ /* Call commit handler if needed and defined */
-+ if(ret == -EIWCOMMIT)
-+ ret = call_commit_handler(dev);
-+
-+ /* Here, we will generate the appropriate event if needed */
-+
-+ return ret;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Wrapper to call a private Wireless Extension handler.
-+ * We do various checks and also take care of moving data between
-+ * user space and kernel space.
-+ * It's not as nice and slimline as the standard wrapper. The cause
-+ * is struct iw_priv_args, which was not really designed for the
-+ * job we are going here.
-+ *
-+ * IMPORTANT : This function prevent to set and get data on the same
-+ * IOCTL and enforce the SET/GET convention. Not doing it would be
-+ * far too hairy...
-+ * If you need to set and get data at the same time, please don't use
-+ * a iw_handler but process it in your ioctl handler (i.e. use the
-+ * old driver API).
-+ */
-+static inline int ioctl_private_call(struct net_device * dev,
-+ struct ifreq * ifr,
-+ unsigned int cmd,
-+ iw_handler handler)
-+{
-+ struct iwreq * iwr = (struct iwreq *) ifr;
-+ struct iw_priv_args * descr = NULL;
-+ struct iw_request_info info;
-+ int extra_size = 0;
-+ int i;
-+ int ret = -EINVAL;
-+
-+ /* Get the description of the IOCTL */
-+ for(i = 0; i < dev->wireless_handlers->num_private_args; i++)
-+ if(cmd == dev->wireless_handlers->private_args[i].cmd) {
-+ descr = &(dev->wireless_handlers->private_args[i]);
-+ break;
-+ }
-+
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "%s : Found private handler for 0x%04X\n",
-+ ifr->ifr_name, cmd);
-+ if(descr) {
-+ printk(KERN_DEBUG "Name %s, set %X, get %X\n",
-+ descr->name, descr->set_args, descr->get_args);
-+ }
-+#endif /* WE_IOCTL_DEBUG */
-+
-+ /* Compute the size of the set/get arguments */
-+ if(descr != NULL) {
-+ if(IW_IS_SET(cmd)) {
-+ /* Size of set arguments */
-+ extra_size = get_priv_size(descr->set_args);
-+
-+ /* Does it fits in iwr ? */
-+ if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
-+ (extra_size < IFNAMSIZ))
-+ extra_size = 0;
-+ } else {
-+ /* Size of set arguments */
-+ extra_size = get_priv_size(descr->get_args);
-+
-+ /* Does it fits in iwr ? */
-+ if((descr->get_args & IW_PRIV_SIZE_FIXED) &&
-+ (extra_size < IFNAMSIZ))
-+ extra_size = 0;
-+ }
-+ }
-+
-+ /* Prepare the call */
-+ info.cmd = cmd;
-+ info.flags = 0;
-+
-+ /* Check if we have a pointer to user space data or not. */
-+ if(extra_size == 0) {
-+ /* No extra arguments. Trivial to handle */
-+ ret = handler(dev, &info, &(iwr->u), (char *) &(iwr->u));
-+ } else {
-+ char * extra;
-+ int err;
-+
-+ /* Check what user space is giving us */
-+ if(IW_IS_SET(cmd)) {
-+ /* Check NULL pointer */
-+ if((iwr->u.data.pointer == NULL) &&
-+ (iwr->u.data.length != 0))
-+ return -EFAULT;
-+
-+ /* Does it fits within bounds ? */
-+ if(iwr->u.data.length > (descr->set_args &
-+ IW_PRIV_SIZE_MASK))
-+ return -E2BIG;
-+ } else {
-+ /* Check NULL pointer */
-+ if(iwr->u.data.pointer == NULL)
-+ return -EFAULT;
-+ }
-+
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Malloc %d bytes\n", extra_size);
-+#endif /* WE_IOCTL_DEBUG */
-+
-+ /* Always allocate for max space. Easier, and won't last
-+ * long... */
-+ extra = kmalloc(extra_size, GFP_KERNEL);
-+ if (extra == NULL) {
-+ return -ENOMEM;
-+ }
-+
-+ /* If it is a SET, get all the extra data in here */
-+ if(IW_IS_SET(cmd) && (iwr->u.data.length != 0)) {
-+ err = copy_from_user(extra, iwr->u.data.pointer,
-+ extra_size);
-+ if (err) {
-+ kfree(extra);
-+ return -EFAULT;
-+ }
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Got %d elem\n", iwr->u.data.length);
-+#endif /* WE_IOCTL_DEBUG */
-+ }
-+
-+ /* Call the handler */
-+ ret = handler(dev, &info, &(iwr->u), extra);
-+
-+ /* If we have something to return to the user */
-+ if (!ret && IW_IS_GET(cmd)) {
-+ err = copy_to_user(iwr->u.data.pointer, extra,
-+ extra_size);
-+ if (err)
-+ ret = -EFAULT;
-+#ifdef WE_IOCTL_DEBUG
-+ printk(KERN_DEBUG "Wrote %d elem\n",
-+ iwr->u.data.length);
-+#endif /* WE_IOCTL_DEBUG */
-+ }
-+
-+ /* Cleanup - I told you it wasn't that long ;-) */
-+ kfree(extra);
-+ }
-+
-+
-+ /* Call commit handler if needed and defined */
-+ if(ret == -EIWCOMMIT)
-+ ret = call_commit_handler(dev);
-+
-+ return ret;
-+}
-+
-+/* ---------------------------------------------------------------- */
-+/*
-+ * Main IOCTl dispatcher. Called from the main networking code
-+ * (dev_ioctl() in net/core/dev.c).
-+ * Check the type of IOCTL and call the appropriate wrapper...
-+ */
-+int wireless_process_ioctl(struct ifreq *ifr, unsigned int cmd)
-+{
-+ struct net_device *dev;
-+ iw_handler handler;
-+
-+ /* Permissions are already checked in dev_ioctl() before calling us.
-+ * The copy_to/from_user() of ifr is also dealt with in there */
-+
-+ /* Make sure the device exist */
-+ if ((dev = __dev_get_by_name(ifr->ifr_name)) == NULL)
-+ return -ENODEV;
-+
-+ /* A bunch of special cases, then the generic case...
-+ * Note that 'cmd' is already filtered in dev_ioctl() with
-+ * (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) */
-+ switch(cmd)
-+ {
-+ case SIOCGIWSTATS:
-+ /* Get Wireless Stats */
-+ return dev_iwstats(dev, ifr);
-+
-+ case SIOCGIWPRIV:
-+ /* Check if we have some wireless handlers defined */
-+ if(dev->wireless_handlers != NULL) {
-+ /* We export to user space the definition of
-+ * the private handler ourselves */
-+ return ioctl_export_private(dev, ifr);
-+ }
-+ // ## Fall-through for old API ##
-+ default:
-+ /* Generic IOCTL */
-+ /* Basic check */
-+ if (!netif_device_present(dev))
-+ return -ENODEV;
-+ /* New driver API : try to find the handler */
-+ handler = get_handler(dev, cmd);
-+ if(handler != NULL) {
-+ /* Standard and private are not the same */
-+ if(cmd < SIOCIWFIRSTPRIV)
-+ return ioctl_standard_call(dev,
-+ ifr,
-+ cmd,
-+ handler);
-+ else
-+ return ioctl_private_call(dev,
-+ ifr,
-+ cmd,
-+ handler);
-+ }
-+ /* Old driver API : call driver ioctl handler */
-+ if (dev->do_ioctl) {
-+ return dev->do_ioctl(dev, ifr, cmd);
-+ }
-+ return -EOPNOTSUPP;
-+ }
-+ /* Not reached */
-+ return -EINVAL;
-+}