diff -r -u orinoco-0.13a.orig/hermes.h orinoco-0.13a/hermes.h
--- orinoco-0.13a.orig/hermes.h	2002-10-02 17:39:49.000000000 -0700
+++ orinoco-0.13a/hermes.h	2002-12-05 22:15:56.000000000 -0800
@@ -233,24 +233,56 @@
 /* Grabbed from wlan-ng - Thanks Mark... - Jean II
  * This is the result of a scan inquiry command */
 /* Structure describing info about an Access Point */
-struct hermes_scan_apinfo {
+
+struct prism2_scan_apinfo {
 	u16 channel;		/* Channel where the AP sits */
 	u16 noise;		/* Noise level */
 	u16 level;		/* Signal level */
 	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
 	u16 beacon_interv;	/* Beacon interval ? */
 	u16 capabilities;	/* Capabilities ? */
+	u16 essid_len;		/* ESSID length */
 	u8 essid[32];		/* ESSID of the network */
 	u8 rates[10];		/* Bit rate supported */
 	u16 proberesp_rate;	/* ???? */
 } __attribute__ ((packed));
 /* Container */
-struct hermes_scan_frame {
+struct prism2_scan_frame {
 	u16 rsvd;                   /* ??? */
 	u16 scanreason;             /* ??? */
-	struct hermes_scan_apinfo aps[35];        /* Scan result */
+	struct prism2_scan_apinfo aps[35];        /* Scan result */
 } __attribute__ ((packed));

+/* Same stuff for the Lucent/Agere card.
+ * Thanks to h1kari <h1kari@dachb0den.com> - Jean II */
+struct agere_scan_apinfo {
+	u16 channel;		/* Channel where the AP sits */
+	u16 noise;		/* Noise level */
+	u16 level;		/* Signal level */
+	u8 bssid[ETH_ALEN];	/* MAC address of the Access Point */
+	u16 beacon_interv;	/* Beacon interval ? */
+	u16 capabilities;	/* Capabilities ? */
+	/* bits: 0-ess, 1-ibss, 4-privacy [wep] */
+	u16 essid_len;		/* ESSID length */
+	u8 essid[32];		/* ESSID of the network */
+} __attribute__ ((packed));
+/* No container */
+
+/* Hack to be able to read both type */
+union hermes_scan_info {
+	struct agere_scan_apinfo	a;
+	struct prism2_scan_apinfo	p;
+};
+
+/* Link status. Once again, grabbed from wlan-ng - Thanks Mark... - Jean II */
+#define HERMES_LINK_NOTCONNECTED	(0)
+#define HERMES_LINK_CONNECTED		(1)
+#define HERMES_LINK_DISCONNECTED	(2)
+#define HERMES_LINK_AP_CHANGE		(3)
+#define HERMES_LINK_AP_OUTOFRANGE	(4)
+#define HERMES_LINK_AP_INRANGE		(5)
+#define HERMES_LINK_ASSOCFAIL		(6)
+
 #define HERMES_LINKSTATUS_NOT_CONNECTED   (0x0000)
 #define HERMES_LINKSTATUS_CONNECTED       (0x0001)
 #define HERMES_LINKSTATUS_DISCONNECTED    (0x0002)
diff -r -u orinoco-0.13a.orig/orinoco.c orinoco-0.13a/orinoco.c
--- orinoco-0.13a.orig/orinoco.c	2002-10-02 17:39:49.000000000 -0700
+++ orinoco-0.13a/orinoco.c	2002-12-13 21:39:10.000000000 -0800
@@ -378,14 +378,33 @@
 #include <linux/if_arp.h>
 #include <linux/etherdevice.h>
 #include <linux/wireless.h>
+#if WIRELESS_EXT > 12
+#include <net/iw_handler.h>
+#endif	/* WIRELESS_EXT > 12 */

 #include "hermes.h"
 #include "hermes_rid.h"
 #include "orinoco.h"
 #include "ieee802_11.h"

+#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 ;-) */
+};
+
+/* Private ioctl is migrating to a new range... */
+#ifndef SIOCIWFIRSTPRIV
+#define SIOCIWFIRSTPRIV		SIOCDEVPRIVATE
+#endif /* SIOCIWFIRSTPRIV */
+#endif	/* WIRELESS_EXT <= 12 */
+
 /********************************************************************/
-/* Module information                                               */
+/* Module information						    */
 /********************************************************************/

 MODULE_AUTHOR("David Gibson <hermes@gibson.dropbear.id.au>");
@@ -489,6 +508,43 @@
 	u16 ethertype;
 } __attribute__ ((packed));

+/* Used in Event handling
+ We avoid using nested strcutres as they break on ARM -- Moustafa
+*/
+struct hermes_tx_descriptor_802_11 {
+	/* hermes_tx_descriptor */
+	u16 status;
+	u16 reserved1;
+	u16 reserved2;
+	u32 sw_support;
+	u8 retry_count;
+	u8 tx_rate;
+	u16 tx_control;
+
+	/* ieee802_11_hdr */
+	u16 frame_ctl;
+	u16 duration_id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+	u8 addr3[ETH_ALEN];
+	u16 seq_ctl;
+	u8 addr4[ETH_ALEN];
+	u16 data_len;
+
+	/* ethhdr */
+	unsigned char   h_dest[ETH_ALEN];       /* destination eth addr */
+	unsigned char   h_source[ETH_ALEN];     /* source ether addr    */
+	unsigned short  h_proto;                /* packet type ID field */
+
+	/* p8022_hdr */
+	u8 dsap;
+	u8 ssap;
+	u8 ctrl;
+	u8 oui[3];
+
+	u16 ethertype;
+}  __attribute__ ((packed));
+
 /* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */
 u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};

@@ -515,8 +571,8 @@
 static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
 				char buf[IW_ESSID_MAX_SIZE+1]);
 static long orinoco_hw_get_freq(struct orinoco_private *priv);
-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
-				      s32 *rates, int max);
+static int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
+				int *numrates, s32 *rates, int max);
 static void __orinoco_set_multicast_list(struct net_device *dev);

 /* Interrupt handling routines */
@@ -529,7 +585,9 @@
 static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw);
 static void __orinoco_ev_alloc(struct orinoco_private *priv, hermes_t *hw);

+#if 0
 /* ioctl() routines */
+/* Either we fix those prototypes or we get rid of them - Jean II */
 static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq);
 static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq);
 static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq);
@@ -549,7 +607,7 @@
 static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq);
 static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq);
 static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq);
-
+#endif
 /* /proc debugging stuff */
 static int orinoco_proc_init(void);
 static void orinoco_proc_cleanup(void);
@@ -563,7 +621,7 @@
 	err = __orinoco_program_rids(priv);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d configuring card\n",
-		       dev->name, err);
+			dev->name, err);
 		return err;
 	}

@@ -572,7 +630,7 @@
 	err = hermes_enable_port(hw, 0);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d enabling MAC port\n",
-		       dev->name, err);
+			dev->name, err);
 		return err;
 	}

@@ -592,7 +650,7 @@
 	err = hermes_disable_port(hw, 0);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d disabling MAC port\n",
-		       dev->name, err);
+			dev->name, err);
 		return err;
 	}
 	hermes_set_irqmask(hw, 0);
@@ -615,8 +673,8 @@
 	if (err == -EIO) {
 		/* Try workaround for old Symbol firmware bug */
 		printk(KERN_WARNING "%s: firmware ALLOC bug detected "
-		       "(old Symbol firmware?). Trying to work around... ",
-		       dev->name);
+			"(old Symbol firmware?). Trying to work around... ",
+			dev->name);

 		priv->nicbuf_size = TX_NICBUF_SIZE_BUG;
 		err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid);
@@ -639,7 +697,7 @@
 	if (err)
 		return err;

-        priv->open = 1;
+	priv->open = 1;

 	err = __orinoco_up(dev);

@@ -676,7 +734,7 @@

 	/* Set the MAC address */
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR,
-			       HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
+			HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting MAC address\n", dev->name, err);
 		return err;
@@ -723,15 +781,15 @@
 	memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val));
 	/* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
-			       &idbuf);
+			 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			 &idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting OWNSSID\n", dev->name, err);
 		return err;
 	}
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
-			       &idbuf);
+			 HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2),
+			 &idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", dev->name, err);
 		return err;
@@ -741,8 +799,8 @@
 	idbuf.len = cpu_to_le16(strlen(priv->nick));
 	memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val));
 	err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME,
-			       HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
-			       &idbuf);
+			HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2),
+			&idbuf);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d setting nickname\n", dev->name, err);
 		return err;
@@ -754,7 +812,7 @@
 					   priv->ap_density);
 		if (err) {
 			printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE.  "
-			       "Disabling sensitivity control\n", dev->name, err);
+				"Disabling sensitivity control\n", dev->name, err);

 			priv->has_sensitivity = 0;
 		}
@@ -794,7 +852,7 @@
 					   priv->pm_on);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}

@@ -803,7 +861,7 @@
 					   priv->pm_mcast);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}
 		err = hermes_write_wordrec(hw, USER_BAP,
@@ -811,7 +869,7 @@
 					   priv->pm_period);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}
 		err = hermes_write_wordrec(hw, USER_BAP,
@@ -819,7 +877,7 @@
 					   priv->pm_timeout);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting up PM\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}
 	}
@@ -831,7 +889,7 @@
 					   priv->preamble);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d setting preamble\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}
 	}
@@ -841,7 +899,7 @@
 		err = __orinoco_hw_setup_wep(priv);
 		if (err) {
 			printk(KERN_ERR "%s: Error %d activating WEP\n",
-			       dev->name, err);
+				dev->name, err);
 			return err;
 		}
 	}
@@ -866,7 +924,7 @@
 	err = hermes_disable_port(hw, 0);
 	if (err) {
 		printk(KERN_ERR "%s: Unable to disable port in orinco_reconfigure()\n",
-		       priv->ndev->name);
+			priv->ndev->name);
 		goto out;
 	}

@@ -877,7 +935,7 @@
 	err = hermes_enable_port(hw, 0);
 	if (err) {
 		printk(KERN_ERR "%s: Unable to enable port in orinco_reconfigure()\n",
-		       priv->ndev->name);
+			priv->ndev->name);
 		goto out;
 	}

@@ -889,7 +947,7 @@

 /* This must be called from user context, without locks held - use
  * schedule_task() */
-static void orinoco_reset(struct net_device *dev)
+int orinoco_reset(struct net_device *dev)
 {
 	struct orinoco_private *priv = dev->priv;
 	int err;
@@ -899,7 +957,7 @@

 	err = orinoco_lock(priv, &flags);
 	if (err)
-		return;
+		return err;

 	priv->hw_unavailable = 1;
 	orinoco_unlock(priv, &flags);
@@ -908,16 +966,16 @@
 		err = (*priv->hard_reset)(priv);
 	if (err) {
 		printk(KERN_ERR "%s: orinoco_reset: Error %d performing hard reset\n",
-		       dev->name, err);
+			dev->name, err);
 		/* FIXME: shutdown of some sort */
-		return;
+		return err;
 	}

 	err = orinoco_reinit_firmware(dev);
 	if (err) {
 		printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n",
-		       dev->name, err);
-		return;
+			dev->name, err);
+		return err;
 	}

 	spin_lock_irqsave(&priv->lock, flags);
@@ -927,13 +985,13 @@
 	err = __orinoco_up(dev);
 	if (err) {
 		printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n",
-		       dev->name, err);
+			dev->name, err);
 	} else
 		dev->trans_start = jiffies;

 	orinoco_unlock(priv, &flags);

-	return;
+	return err;
 }

 /********************************************************************/
@@ -959,7 +1017,7 @@
 		break;
 	default:
 		printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n",
-		       priv->ndev->name);
+			priv->ndev->name);
 	}
 }

@@ -977,7 +1035,7 @@

 	if (orinoco_lock(priv, &flags) != 0) {
 		printk(KERN_DEBUG "%s: orinoco_set_multicast_list() "
-		       "called when hw_unavailable\n", dev->name);
+			"called when hw_unavailable\n", dev->name);
 		return;
 	}

@@ -997,7 +1055,7 @@

 	if (priv->bitratemode >= BITRATE_TABLE_SIZE) {
 		printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n",
-		       priv->ndev->name, priv->bitratemode);
+			priv->ndev->name, priv->bitratemode);
 		return -EINVAL;
 	}

@@ -1062,18 +1120,18 @@

 			/* Write all 4 keys */
 			for(i = 0; i < ORINOCO_MAX_KEYS; i++) {
-/*  				int keylen = le16_to_cpu(priv->keys[i].len); */
+				/*  				int keylen = le16_to_cpu(priv->keys[i].len); */

 				if (keylen > LARGE_KEY_SIZE) {
 					printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n",
-					       priv->ndev->name, i, keylen);
+						priv->ndev->name, i, keylen);
 					return -E2BIG;
 				}

 				err = hermes_write_ltv(hw, USER_BAP,
-						       HERMES_RID_CNFDEFAULTKEY0 + i,
-						       HERMES_BYTES_TO_RECLEN(keylen),
-						       priv->keys[i].data);
+						HERMES_RID_CNFDEFAULTKEY0 + i,
+						HERMES_BYTES_TO_RECLEN(keylen),
+						priv->keys[i].data);
 				if (err)
 					return err;
 			}
@@ -1116,7 +1174,7 @@
 	default:
 		if (priv->wep_on) {
 			printk(KERN_ERR "%s: WEP enabled, although not supported!\n",
-			       priv->ndev->name);
+				priv->ndev->name);
 			return -EINVAL;
 		}
 	}
@@ -1124,7 +1182,9 @@
 	return 0;
 }

-static int orinoco_hw_get_bssid(struct orinoco_private *priv, char buf[ETH_ALEN])
+/* This is called only once from orinoco_ioctl_getwap(). */
+static inline int orinoco_hw_get_bssid(struct orinoco_private *priv,
+					char buf[ETH_ALEN])
 {
 	hermes_t *hw = &priv->hw;
 	int err = 0;
@@ -1135,15 +1195,17 @@
 		return err;

 	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID,
-			      ETH_ALEN, NULL, buf);
+				ETH_ALEN, NULL, buf);

 	orinoco_unlock(priv, &flags);

 	return err;
 }

-static int orinoco_hw_get_essid(struct orinoco_private *priv, int *active,
-			      char buf[IW_ESSID_MAX_SIZE+1])
+/* This is called only once from orinoco_ioctl_getessid(). */
+static inline int orinoco_hw_get_essid(struct orinoco_private *priv,
+				int *active,
+				char buf[IW_ESSID_MAX_SIZE+1])
 {
 	hermes_t *hw = &priv->hw;
 	int err = 0;
@@ -1172,14 +1234,14 @@
 			HERMES_RID_CNFDESIREDSSID;

 		err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf),
-				      NULL, &essidbuf);
+					NULL, &essidbuf);
 		if (err)
 			goto fail_unlock;
 	} else {
 		*active = 0;

 		err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID,
-				      sizeof(essidbuf), NULL, &essidbuf);
+					sizeof(essidbuf), NULL, &essidbuf);
 		if (err)
 			goto fail_unlock;
 	}
@@ -1193,10 +1255,11 @@
  fail_unlock:
 	orinoco_unlock(priv, &flags);

-	return err;
+	return err;
 }

-static long orinoco_hw_get_freq(struct orinoco_private *priv)
+/* This is called only once from orinoco_ioctl_getfreq(). */
+static inline long orinoco_hw_get_freq(struct orinoco_private *priv)
 {

 	hermes_t *hw = &priv->hw;
@@ -1237,8 +1300,10 @@
 	return err ? err : freq;
 }

-static int orinoco_hw_get_bitratelist(struct orinoco_private *priv, int *numrates,
-				    s32 *rates, int max)
+/* This is called only once from orinoco_ioctl_getiwrange(). */
+static inline int orinoco_hw_get_bitratelist(struct orinoco_private *priv,
+					     int *numrates,
+					     int32_t *rates, int max)
 {
 	hermes_t *hw = &priv->hw;
 	struct hermes_idstring list;
@@ -1253,7 +1318,7 @@
 		return err;

 	err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES,
-			      sizeof(list), NULL, &list);
+				sizeof(list), NULL, &list);
 	orinoco_unlock(priv, &flags);

 	if (err)
@@ -1287,39 +1352,39 @@

 	printk(KERN_DEBUG "IEEE 802.11 header:\n");
 	printk(KERN_DEBUG "  frame_ctl   = 0x%04x\n",
-	       frame->p80211.frame_ctl);
+		frame->p80211.frame_ctl);
 	printk(KERN_DEBUG "  duration_id = 0x%04x\n",
-	       frame->p80211.duration_id);
+		frame->p80211.duration_id);
 	printk(KERN_DEBUG "  addr1       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr1[0], frame->p80211.addr1[1],
-	       frame->p80211.addr1[2], frame->p80211.addr1[3],
-	       frame->p80211.addr1[4], frame->p80211.addr1[5]);
+		frame->p80211.addr1[0], frame->p80211.addr1[1],
+		frame->p80211.addr1[2], frame->p80211.addr1[3],
+		frame->p80211.addr1[4], frame->p80211.addr1[5]);
 	printk(KERN_DEBUG "  addr2       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr2[0], frame->p80211.addr2[1],
-	       frame->p80211.addr2[2], frame->p80211.addr2[3],
-	       frame->p80211.addr2[4], frame->p80211.addr2[5]);
+		frame->p80211.addr2[0], frame->p80211.addr2[1],
+		frame->p80211.addr2[2], frame->p80211.addr2[3],
+		frame->p80211.addr2[4], frame->p80211.addr2[5]);
 	printk(KERN_DEBUG "  addr3       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr3[0], frame->p80211.addr3[1],
-	       frame->p80211.addr3[2], frame->p80211.addr3[3],
-	       frame->p80211.addr3[4], frame->p80211.addr3[5]);
+		frame->p80211.addr3[0], frame->p80211.addr3[1],
+		frame->p80211.addr3[2], frame->p80211.addr3[3],
+		frame->p80211.addr3[4], frame->p80211.addr3[5]);
 	printk(KERN_DEBUG "  seq_ctl     = 0x%04x\n",
-	       frame->p80211.seq_ctl);
+		frame->p80211.seq_ctl);
 	printk(KERN_DEBUG "  addr4       = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p80211.addr4[0], frame->p80211.addr4[1],
-	       frame->p80211.addr4[2], frame->p80211.addr4[3],
-	       frame->p80211.addr4[4], frame->p80211.addr4[5]);
+		frame->p80211.addr4[0], frame->p80211.addr4[1],
+		frame->p80211.addr4[2], frame->p80211.addr4[3],
+		frame->p80211.addr4[4], frame->p80211.addr4[5]);
 	printk(KERN_DEBUG "  data_len    = 0x%04x\n",
-	       frame->p80211.data_len);
+		frame->p80211.data_len);

 	printk(KERN_DEBUG "IEEE 802.3 header:\n");
 	printk(KERN_DEBUG "  dest        = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_dest[0], frame->p8023.h_dest[1],
-	       frame->p8023.h_dest[2], frame->p8023.h_dest[3],
-	       frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
+		frame->p8023.h_dest[0], frame->p8023.h_dest[1],
+		frame->p8023.h_dest[2], frame->p8023.h_dest[3],
+		frame->p8023.h_dest[4], frame->p8023.h_dest[5]);
 	printk(KERN_DEBUG "  src         = %02x:%02x:%02x:%02x:%02x:%02x\n",
-	       frame->p8023.h_source[0], frame->p8023.h_source[1],
-	       frame->p8023.h_source[2], frame->p8023.h_source[3],
-	       frame->p8023.h_source[4], frame->p8023.h_source[5]);
+		frame->p8023.h_source[0], frame->p8023.h_source[1],
+		frame->p8023.h_source[2], frame->p8023.h_source[3],
+		frame->p8023.h_source[4], frame->p8023.h_source[5]);
 	printk(KERN_DEBUG "  len         = 0x%04x\n", frame->p8023.h_proto);

 	printk(KERN_DEBUG "IEEE 802.2 LLC/SNAP header:\n");
@@ -1327,7 +1392,7 @@
 	printk(KERN_DEBUG "  SSAP        = 0x%02x\n", frame->p8022.ssap);
 	printk(KERN_DEBUG "  ctrl        = 0x%02x\n", frame->p8022.ctrl);
 	printk(KERN_DEBUG "  OUI         = %02x:%02x:%02x\n",
-	       frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
+		frame->p8022.oui[0], frame->p8022.oui[1], frame->p8022.oui[2]);
 	printk(KERN_DEBUG "  ethertype  = 0x%04x\n", frame->ethertype);
 }
 #endif
@@ -1358,6 +1423,10 @@
 	evstat = hermes_read_regn(hw, EVSTAT);
 	events = evstat & hw->inten;

+	/*  	if (! events) { */
+	/*  		printk(KERN_WARNING "%s: Null event\n", dev->name); */
+	/*  	} */
+
 	if (jiffies != last_irq_jiffy)
 		loops_this_jiffy = 0;
 	last_irq_jiffy = jiffies;
@@ -1366,7 +1435,7 @@
 		if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) {
 			printk(KERN_CRIT "%s: IRQ handler is looping too \
 much! Shutting down.\n",
-			       dev->name);
+				dev->name);
 			/* Perform an emergency shutdown */
 			hermes_set_irqmask(hw, 0);
 			break;
@@ -1414,7 +1483,7 @@
 	/* This seems to happen a fair bit under load, but ignoring it
 	   seems to work fine...*/
 	printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n",
-	       priv->ndev->name);
+		priv->ndev->name);
 }

 static void __orinoco_ev_infdrop(struct orinoco_private *priv, hermes_t *hw)
@@ -1441,10 +1510,10 @@

 	/* Read the info frame header - don't try too hard */
 	err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info),
-			       infofid, 0);
+				infofid, 0);
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading info frame. "
-		       "Frame dropped.\n", dev->name, err);
+			"Frame dropped.\n", dev->name, err);
 		return;
 	}

@@ -1458,7 +1527,7 @@

 		if (len > sizeof(tallies)) {
 			printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n",
-			       dev->name, len);
+				dev->name, len);
 			len = sizeof(tallies);
 		}

@@ -1483,16 +1552,80 @@
 			le16_to_cpu(tallies.TxRetryLimitExceeded);
 		/* wstats->miss.beacon - no match */
 #endif /* WIRELESS_EXT > 11 */
+		break;
+	}
+	case HERMES_INQ_SCAN: {
+		/* Result of a scanning. Contains information about
+		 * cells in the vicinity - Jean II */
+#if WIRELESS_EXT > 13
+		int len = le16_to_cpu(info.len) - 1;
+		union iwreq_data	wrqu;
+		unsigned char *buf;
+
+		DEBUG(1, "%s: scan frame is %d words.\n", dev->name, len);
+
+		/* Keep sanity (2048 bytes) */
+		if(len > 1024) {
+			printk(KERN_WARNING "%s: Scan results too large (%d words).\n", dev->name, len);
+			break;
+		}
+
+		/* We are a strict producer. If the previous scan results
+		 * have not been consumed, we just have to drop this
+		 * frame. We can't remove the previous results ourselves,
+		 * that would be *very* racy... Jean II */
+		if(priv->scan_result != NULL) {
+			printk(KERN_WARNING "%s: Previous scan results not consumed, dropping info frame.\n", dev->name);
+			break;
+		}
+
+		/* Allocate buffer for results */
+		buf = kmalloc(len * 2, GFP_ATOMIC);
+		if(buf == NULL)
+			/* No memory, so can't printk()... */
+			break;
+		DEBUG(1, "%s: scan KMALLOC %p\n", dev->name, buf);
+
+		/* Read directly the data (no seek) */
+		hermes_read_words(hw, HERMES_DATA1, (void *) buf, len);
+
+#ifdef ORINOCO_DEBUG
+		{
+			int	i;
+			printk(KERN_DEBUG "Scan result [%02X", buf[0]);
+			for(i = 1; i < (len * 2); i++)
+				printk(":%02X", buf[i]);
+			printk("]\n");
+		}
+#endif	/* ORINOCO_DEBUG */
+
+		/* Allow the clients to access the results */
+		priv->scan_len = len * 2;
+		priv->scan_result = buf;
+
+		/* Send an empty event to user space.
+		 * We don't send the received data on the event because
+		 * it would require us to do complex transcoding, and
+		 * we want to minimise the work done in the irq handler
+		 * Use a request to extract the data - Jean II */
+		wrqu.data.length = 0;
+		wrqu.data.flags = 0;
+		wireless_send_event(dev, SIOCGIWSCAN, &wrqu, NULL);
+#endif /* WIRELESS_EXT > 13 */
+		break;
 	}
-	break;
 	case HERMES_INQ_LINKSTATUS: {
+		/* Link status information frame.
+		 * The link status has changed, and the card tell us about
+		 * it. Most likely, the card has just connected to the cell
+		 * or created an Ad-Hoc cell, or roamed... - Jean II */
 		struct hermes_linkstatus linkstatus;
 		u16 newstatus;
 		const char *s;

 		if (len != sizeof(linkstatus)) {
 			printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n",
-			       dev->name, len);
+				dev->name, len);
 			break;
 		}

@@ -1503,36 +1636,59 @@
 		switch (newstatus) {
 		case HERMES_LINKSTATUS_NOT_CONNECTED:
 			s = "Not Connected";
-                       break;
-               case HERMES_LINKSTATUS_CONNECTED:
-		       s = "Connected";
-                       break;
-               case HERMES_LINKSTATUS_DISCONNECTED:
-		       s = "Disconnected";
-                       break;
-               case HERMES_LINKSTATUS_AP_CHANGE:
-		       s = "AP Changed";
-                       break;
-               case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
-		       s = "AP Out of Range";
-                       break;
-               case HERMES_LINKSTATUS_AP_IN_RANGE:
-		       s = "AP In Range";
-                       break;
-               case HERMES_LINKSTATUS_ASSOC_FAILED:
-		       s = "Association Failed";
-		       break;
+			break;
+		case HERMES_LINKSTATUS_CONNECTED:
+			s = "Connected";
+			break;
+		case HERMES_LINKSTATUS_DISCONNECTED:
+			s = "Disconnected";
+			break;
+		case HERMES_LINKSTATUS_AP_CHANGE:
+			s = "AP Changed";
+			break;
+		case HERMES_LINKSTATUS_AP_OUT_OF_RANGE:
+			s = "AP Out of Range";
+			break;
+		case HERMES_LINKSTATUS_AP_IN_RANGE:
+			s = "AP In Range";
+			break;
+		case HERMES_LINKSTATUS_ASSOC_FAILED:
+			s = "Association Failed";
+			break;
 		default:
 			s = "UNKNOWN";
 		}
+
+		 printk(KERN_INFO "%s: New link status: %s (%04x)\n",
+			dev->name, s, newstatus);
+#if WIRELESS_EXT > 13
+		union iwreq_data	wrqu;
+
+		/* The info frame contains only one word which is the
+		 * status (see hermes.h). The status is pretty boring
+		 * in itself, that's why we export the new BSSID...
+		 * Jean II */
+
+		/* Do we have a valid AP address ? */
+		if((newstatus == HERMES_LINKSTATUS_CONNECTED) ||
+		   (newstatus == HERMES_LINKSTATUS_AP_CHANGE) ||
+		   (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE))
+			err = hermes_read_ltv(hw, IRQ_BAP,
+						HERMES_RID_CURRENTBSSID,
+						ETH_ALEN, NULL,
+						wrqu.ap_addr.sa_data);
+		else
+			memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN);
+		wrqu.ap_addr.sa_family = ARPHRD_ETHER;

-		printk(KERN_INFO "%s: New link status: %s (%04x)\n",
-		       dev->name, s, newstatus);
+		/* Send event to user space */
+		wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL);
+#endif /* WIRELESS_EXT > 13 */
 	}
 	break;
 	default:
 		printk(KERN_DEBUG "%s: Unknown information frame received (type %04x).\n",
-		      dev->name, type);
+			dev->name, type);
 		/* We don't actually do anything about it */
 		break;
 	}
@@ -1555,10 +1711,10 @@
 	rxfid = hermes_read_regn(hw, RXFID);

 	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc),
-			       rxfid, 0);
+				rxfid, 0);
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading Rx descriptor. "
-		       "Frame dropped.\n", dev->name, err);
+			"Frame dropped.\n", dev->name, err);
 		stats->rx_errors++;
 		goto drop;
 	}
@@ -1569,7 +1725,7 @@
 		if (status & HERMES_RXSTAT_UNDECRYPTABLE) {
 			wstats->discard.code++;
 			DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n",
-			       dev->name);
+				dev->name);
 		} else {
 			stats->rx_crc_errors++;
 			DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", dev->name);
@@ -1579,13 +1735,13 @@
 	}

 	/* For now we ignore the 802.11 header completely, assuming
-           that the card's firmware has handled anything vital */
+	   that the card's firmware has handled anything vital */

 	err = hermes_bap_pread(hw, IRQ_BAP, &hdr, sizeof(hdr),
-			       rxfid, HERMES_802_3_OFFSET);
+				rxfid, HERMES_802_3_OFFSET);
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading frame header. "
-		       "Frame dropped.\n", dev->name, err);
+			"Frame dropped.\n", dev->name, err);
 		stats->rx_errors++;
 		goto drop;
 	}
@@ -1602,7 +1758,7 @@
 	}
 	if (length > IEEE802_11_DATA_LEN) {
 		printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n",
-		       dev->name, length);
+			dev->name, length);
 		stats->rx_length_errors++;
 		stats->rx_errors++;
 		goto drop;
@@ -1616,7 +1772,7 @@
 	skb = dev_alloc_skb(length+ETH_HLEN+2+1);
 	if (!skb) {
 		printk(KERN_WARNING "%s: Can't allocate skb for Rx\n",
-		       dev->name);
+			dev->name);
 		goto drop;
 	}

@@ -1660,10 +1816,10 @@

 	p = skb_put(skb, data_len);
 	err = hermes_bap_pread(hw, IRQ_BAP, p, RUP_EVEN(data_len),
-			       rxfid, data_off);
+				rxfid, data_off);
 	if (err) {
 		printk(KERN_ERR "%s: error %d reading frame. "
-		       "Frame dropped.\n", dev->name, err);
+			"Frame dropped.\n", dev->name, err);
 		stats->rx_errors++;
 		goto drop;
 	}
@@ -1696,30 +1852,68 @@
 	struct net_device *dev = priv->ndev;
 	struct net_device_stats *stats = &priv->stats;
 	u16 fid = hermes_read_regn(hw, TXCOMPLFID);
-	struct hermes_tx_descriptor desc;
+	/* Removed orinoco_txframe_hdr as it is no longer supported
+	   (contains nested structures) -- Moustafa
+	*/
+	struct hermes_tx_descriptor_802_11 hdr;
 	int err = 0;
-
+
 	if (fid == DUMMY_FID)
 		return; /* Nothing's really happened */
-
-	err = hermes_bap_pread(hw, IRQ_BAP, &desc, sizeof(desc), fid, 0);
+
+	/* Read the frame header */
+	err = hermes_bap_pread(hw, IRQ_BAP, &hdr,
+				sizeof(struct hermes_tx_descriptor) +
+				sizeof(struct ieee802_11_hdr),
+				fid, 0);
 	if (err) {
 		printk(KERN_WARNING "%s: Unable to read descriptor on Tx error "
-		       "(FID=%04X error %d)\n",
-		       dev->name, fid, err);
+			"(FID=%04X error %d)\n",
+			dev->name, fid, err);
 	} else {
-		DEBUG(1, "%s: Tx error, status %d\n",
-		      dev->name, le16_to_cpu(desc.status));
+		int status = le16_to_cpu(hdr.status);
+
+		printk(KERN_INFO "%s: Tx error, status %d (FID=%04X)\n",
+			dev->name, status, fid);
+
+#if WIRELESS_EXT > 13
+		/* We produce a TXDROP event only for retry or lifetime
+		 * exceeded, because that's the only status that really mean
+		 * that this particular node went away.
+		 * Other errors means that *we* screwed up. - Jean II */
+		if(status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) {
+			union iwreq_data	wrqu;
+
+			/* Copy 802.11 dest address.
+			 * We use the 802.11 header because the frame may
+			 * not be 802.3 or may be mangled...
+			 * In Ad-Hoc mode, it will be the node address.
+			 * In managed mode, it will be most likely the AP addr
+			 * User space will figure out how to convert it to
+			 * whatever it needs (IP address or else).
+			 * - Jean II */
+			memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN);
+			wrqu.addr.sa_family = ARPHRD_ETHER;
+
+			/* Send event to user space */
+			wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL);
+		}
+#endif /* WIRELESS_EXT > 13 */
 	}
-
+
 	stats->tx_errors++;
-
+	netif_wake_queue(dev);
+
 	hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID);
 }

 static void __orinoco_ev_tx(struct orinoco_private *priv, hermes_t *hw)
 {
+	/*  	struct net_device *dev = priv->ndev; */
 	struct net_device_stats *stats = &priv->stats;
+	/*  	u16 fid = hermes_read_regn(hw, TXCOMPLFID); */
+
+	/*  	DEBUG(2, "%s: Transmit completed (FID=%04X)\n", priv->ndev->name, fid); */

 	stats->tx_packets++;

@@ -1734,7 +1928,7 @@
 	if (fid != priv->txfid) {
 		if (fid != DUMMY_FID)
 			printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n",
-			       dev->name, fid);
+				dev->name, fid);
 		return;
 	} else {
 		netif_wake_queue(dev);
@@ -1755,7 +1949,7 @@
 	if (sta_id->variant == 1)
 		return FIRMWARE_TYPE_AGERE;
 	else if ((sta_id->variant == 2) &&
-		   ((firmver == 0x10001) || (firmver == 0x20001)))
+		((firmver == 0x10001) || (firmver == 0x20001)))
 		return FIRMWARE_TYPE_SYMBOL;
 	else
 		return FIRMWARE_TYPE_INTERSIL;
@@ -1774,7 +1968,7 @@
 	err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id);
 	if (err) {
 		printk(KERN_WARNING "%s: Error %d reading firmware info. Wildly guessing capabilities...\n",
-		       dev->name, err);
+			dev->name, err);
 		memset(&sta_id, 0, sizeof(sta_id));
 	}
 	le16_to_cpus(&sta_id.id);
@@ -1783,8 +1977,8 @@
 	le16_to_cpus(&sta_id.minor);

 	printk(KERN_DEBUG "%s: Station identity %04x:%04x:%04x:%04x\n",
-	       dev->name, sta_id.id, sta_id.variant,
-	       sta_id.major, sta_id.minor);
+		dev->name, sta_id.id, sta_id.variant,
+		sta_id.major, sta_id.minor);

 	if (! priv->firmware_type)
 		priv->firmware_type = determine_firmware_type(dev, &sta_id);
@@ -1805,8 +1999,8 @@
 		/* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout,
 		   ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */
 		printk(KERN_DEBUG "%s: Looks like a Lucent/Agere firmware "
-		       "version %d.%02d\n", dev->name,
-		       sta_id.major, sta_id.minor);
+			"version %d.%02d\n", dev->name,
+			sta_id.major, sta_id.minor);

 		firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor;

@@ -1830,12 +2024,12 @@
 		memset(tmp, 0, sizeof(tmp));
 		/* Get the Symbol firmware version */
 		err = hermes_read_ltv(hw, USER_BAP,
-				      HERMES_RID_SECONDARYVERSION_SYMBOL,
-				      SYMBOL_MAX_VER_LEN, NULL, &tmp);
+					HERMES_RID_SECONDARYVERSION_SYMBOL,
+					SYMBOL_MAX_VER_LEN, NULL, &tmp);
 		if (err) {
 			printk(KERN_WARNING
-			       "%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
-			       dev->name, err);
+				"%s: Error %d reading Symbol firmware info. Wildly guessing capabilities...\n",
+				dev->name, err);
 			firmver = 0;
 			tmp[0] = '\0';
 		} else {
@@ -1851,8 +2045,8 @@
 		}

 		printk(KERN_DEBUG "%s: Looks like a Symbol firmware "
-		       "version [%s] (parsing to %X)\n", dev->name,
-		       tmp, firmver);
+			"version [%s] (parsing to %X)\n", dev->name,
+			tmp, firmver);

 		priv->has_ibss = (firmver >= 0x20000);
 		priv->has_wep = (firmver >= 0x15012);
@@ -2142,7 +2336,7 @@
 }

 static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac,
-				    int level, int noise)
+				      int level, int noise)
 {
 	struct orinoco_private *priv = (struct orinoco_private *)dev->priv;
 	int i;
@@ -2226,7 +2420,7 @@
 	eh = (struct ethhdr *)skb->data;

 	memset(&desc, 0, sizeof(desc));
- 	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
+	desc.tx_control = cpu_to_le16(HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX);
 	err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), txfid, 0);
 	if (err) {
 		printk(KERN_ERR "%s: Error %d writing Tx descriptor to BAP\n",
@@ -2408,152 +2602,259 @@
 /* Wireless extensions support                                      */
 /********************************************************************/

-static int orinoco_ioctl_getiwrange(struct net_device *dev, struct iw_point *rrq)
+/* Removed iwreq_data as they are not supported
+   before WIRELESS_EXT 13 -- Moustafa
+*/
+static int orinoco_ioctl_getname(struct net_device *dev,
+				 struct iw_request_info *info,
+				 char *wrqu,
+				 char *extra)
+{
+	DEBUG(1, "%s: SIOCGIWNAME\n", dev->name);
+
+	strcpy(wrqu, "IEEE 802.11-DS");
+	return 0;
+}
+
+static int orinoco_ioctl_getwap(struct net_device *dev,
+				struct iw_request_info *info,
+				struct sockaddr *ap_addr,
+				char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+
+	DEBUG(1, "%s: SIOCGIWAP\n", dev->name);
+
+	ap_addr->sa_family = ARPHRD_ETHER;
+	return orinoco_hw_get_bssid(priv, ap_addr->sa_data);
+}
+
+static int orinoco_ioctl_setmode(struct net_device *dev,
+				 struct iw_request_info *info,
+				 __u32 *mode,
+				 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int err = 0;
+	unsigned long flags;
+
+	DEBUG(1, "%s: SIOCSIWMODE\n", dev->name);
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+	err = -EINPROGRESS;		/* Call commit handler */
+
+	switch (*mode) {
+	case IW_MODE_ADHOC:
+		if (! (priv->has_ibss || priv->has_port3) )
+			err = -EINVAL;
+		else {
+			priv->iw_mode = IW_MODE_ADHOC;
+		}
+		break;
+
+	case IW_MODE_INFRA:
+		priv->iw_mode = IW_MODE_INFRA;
+		break;
+
+	default:
+		err = -EINVAL;
+		break;
+	}
+	set_port_type(priv);
+	orinoco_unlock(priv, &flags);
+
+	return err;
+}
+
+static int orinoco_ioctl_getmode(struct net_device *dev,
+				 struct iw_request_info *info,
+				 __u32 *mode,
+				 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	unsigned long flags;
+
+	DEBUG(1, "%s: SIOCGIWMODE\n", dev->name);
+
+	/* No real need to lock here */
+	orinoco_lock(priv, &flags);
+	*mode = priv->iw_mode;
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
+static int orinoco_ioctl_getiwrange(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_point *rrq,
+				    char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int err = 0;
 	int mode;
-	struct iw_range range;
+	struct iw_range *range = (struct iw_range *) extra;
 	int numrates;
 	int i, k;
 	unsigned long flags;

+	DEBUG(1, "%s: SIOCGIWRANGE\n", dev->name);
 	TRACE_ENTER(dev->name);

-	err = verify_area(VERIFY_WRITE, rrq->pointer, sizeof(range));
-	if (err)
-		return err;
-
-	rrq->length = sizeof(range);
+	rrq->length = sizeof(struct iw_range);

 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;

 	mode = priv->iw_mode;
-	orinoco_unlock(priv, &flags);

-	memset(&range, 0, sizeof(range));
+	memset(range, 0, sizeof(struct iw_range));

 	/* Much of this shamelessly taken from wvlan_cs.c. No idea
 	 * what it all means -dgibson */
 #if WIRELESS_EXT > 10
-	range.we_version_compiled = WIRELESS_EXT;
-	range.we_version_source = 11;
+	range->we_version_compiled = WIRELESS_EXT;
+	range->we_version_source = 13;
 #endif /* WIRELESS_EXT > 10 */

-	range.min_nwid = range.max_nwid = 0; /* We don't use nwids */
+	// Already done in memset, don't redo it
+	range->min_nwid = range->max_nwid = 0; /* We don't use nwids */

 	/* Set available channels/frequencies */
-	range.num_channels = NUM_CHANNELS;
+	range->num_channels = NUM_CHANNELS;
 	k = 0;
 	for (i = 0; i < NUM_CHANNELS; i++) {
 		if (priv->channel_mask & (1 << i)) {
-			range.freq[k].i = i + 1;
-			range.freq[k].m = channel_frequency[i] * 100000;
-			range.freq[k].e = 1;
+			range->freq[k].i = i + 1;
+			range->freq[k].m = channel_frequency[i] * 100000;
+			range->freq[k].e = 1;
 			k++;
 		}

 		if (k >= IW_MAX_FREQUENCIES)
 			break;
 	}
-	range.num_frequency = k;
+	range->num_frequency = k;

-	range.sensitivity = 3;
+	range->sensitivity = 3;
+
+	/* Group all operation that need locking here - Jean II */
+	/* Actually, as we just read a bunch of ints, we don't really
+	 * need any locking (writing an int is atomic) - Jean II */
+	mode = priv->iw_mode;
+	if (priv->has_wep) {
+		range->max_encoding_tokens = ORINOCO_MAX_KEYS;
+
+		range->encoding_size[0] = SMALL_KEY_SIZE;
+		range->num_encoding_sizes = 1;
+
+		if (priv->has_big_wep) {
+			range->encoding_size[1] = LARGE_KEY_SIZE;
+			range->num_encoding_sizes = 2;
+		}
+	} else {
+		// Already done in memset, don't redo it
+		range->num_encoding_sizes = 0;
+		range->max_encoding_tokens = 0;
+	}
+	orinoco_unlock(priv, &flags);

 	if ((mode == IW_MODE_ADHOC) && (priv->spy_number == 0)){
 		/* Quality stats meaningless in ad-hoc mode */
-		range.max_qual.qual = 0;
-		range.max_qual.level = 0;
-		range.max_qual.noise = 0;
+		range->max_qual.qual = 0;
+		range->max_qual.level = 0;
+		range->max_qual.noise = 0;
+		// Already done in memset, don't redo it
 #if WIRELESS_EXT > 11
-		range.avg_qual.qual = 0;
-		range.avg_qual.level = 0;
-		range.avg_qual.noise = 0;
+		range->avg_qual.qual = 0;
+		range->avg_qual.level = 0;
+		range->avg_qual.noise = 0;
 #endif /* WIRELESS_EXT > 11 */

 	} else {
-		range.max_qual.qual = 0x8b - 0x2f;
-		range.max_qual.level = 0x2f - 0x95 - 1;
-		range.max_qual.noise = 0x2f - 0x95 - 1;
+		range->max_qual.qual = 0x8b - 0x2f;
+		range->max_qual.level = 0x2f - 0x95 - 1;
+		range->max_qual.noise = 0x2f - 0x95 - 1;
 #if WIRELESS_EXT > 11
 		/* Need to get better values */
-		range.avg_qual.qual = 0x24;
-		range.avg_qual.level = 0xC2;
-		range.avg_qual.noise = 0x9E;
+		range->avg_qual.qual = 0x24;
+		range->avg_qual.level = 0xC2;
+		range->avg_qual.noise = 0x9E;
 #endif /* WIRELESS_EXT > 11 */
 	}

 	err = orinoco_hw_get_bitratelist(priv, &numrates,
-				       range.bitrate, IW_MAX_BITRATES);
+					 range->bitrate, IW_MAX_BITRATES);
 	if (err)
 		return err;
-	range.num_bitrates = numrates;
+	range->num_bitrates = numrates;

 	/* Set an indication of the max TCP throughput in bit/s that we can
 	 * expect using this interface. May be use for QoS stuff...
 	 * Jean II */
 	if(numrates > 2)
-		range.throughput = 5 * 1000 * 1000;	/* ~5 Mb/s */
+		range->throughput = 5 * 1000 * 1000;	/* ~5 Mb/s */
 	else
-		range.throughput = 1.5 * 1000 * 1000;	/* ~1.5 Mb/s */
-
-	range.min_rts = 0;
-	range.max_rts = 2347;
-	range.min_frag = 256;
-	range.max_frag = 2346;
+		range->throughput = 1.5 * 1000 * 1000;	/* ~1.5 Mb/s */

 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
 	if (priv->has_wep) {
-		range.max_encoding_tokens = ORINOCO_MAX_KEYS;
+		range->max_encoding_tokens = ORINOCO_MAX_KEYS;

-		range.encoding_size[0] = SMALL_KEY_SIZE;
-		range.num_encoding_sizes = 1;
+		range->encoding_size[0] = SMALL_KEY_SIZE;
+		range->num_encoding_sizes = 1;

 		if (priv->has_big_wep) {
-			range.encoding_size[1] = LARGE_KEY_SIZE;
-			range.num_encoding_sizes = 2;
+			range->encoding_size[1] = LARGE_KEY_SIZE;
+			range->num_encoding_sizes = 2;
 		}
 	} else {
-		range.num_encoding_sizes = 0;
-		range.max_encoding_tokens = 0;
+		range->num_encoding_sizes = 0;
+		range->max_encoding_tokens = 0;
 	}
 	orinoco_unlock(priv, &flags);
-
-	range.min_pmp = 0;
-	range.max_pmp = 65535000;
-	range.min_pmt = 0;
-	range.max_pmt = 65535 * 1000;	/* ??? */
-	range.pmp_flags = IW_POWER_PERIOD;
-	range.pmt_flags = IW_POWER_TIMEOUT;
-	range.pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
-
-	range.num_txpower = 1;
-	range.txpower[0] = 15; /* 15dBm */
-	range.txpower_capa = IW_TXPOW_DBM;
+
+	/* These 4 were in the patch, but not orig 11a or 13a.  Maybe bogus. */
+	range->min_rts = 0;
+	range->max_rts = 2347;
+	range->min_frag = 256;
+	range->max_frag = 2346;
+
+	range->min_pmp = 0;
+	range->max_pmp = 65535000;
+	range->min_pmt = 0;
+	range->max_pmt = 65535 * 1000;	/* ??? */
+	range->pmp_flags = IW_POWER_PERIOD;
+	range->pmt_flags = IW_POWER_TIMEOUT;
+	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_UNICAST_R;
+
+	range->num_txpower = 1;
+	range->txpower[0] = 15; /* 15dBm */
+	range->txpower_capa = IW_TXPOW_DBM;

 #if WIRELESS_EXT > 10
-	range.retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
-	range.retry_flags = IW_RETRY_LIMIT;
-	range.r_time_flags = IW_RETRY_LIFETIME;
-	range.min_retry = 0;
-	range.max_retry = 65535;	/* ??? */
-	range.min_r_time = 0;
-	range.max_r_time = 65535 * 1000;	/* ??? */
+	range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME;
+	range->retry_flags = IW_RETRY_LIMIT;
+	range->r_time_flags = IW_RETRY_LIFETIME;
+	range->min_retry = 0;
+	range->max_retry = 65535;	/* ??? */
+	range->min_r_time = 0;
+	range->max_r_time = 65535 * 1000;	/* ??? */
 #endif /* WIRELESS_EXT > 10 */

-	if (copy_to_user(rrq->pointer, &range, sizeof(range)))
-		return -EFAULT;
-
 	TRACE_EXIT(dev->name);

 	return 0;
 }

-static int orinoco_ioctl_setiwencode(struct net_device *dev, struct iw_point *erq)
+
+static int orinoco_ioctl_setiwencode(struct net_device *dev,
+				     struct iw_request_info *info,
+				     struct iw_point *erq,
+				     char *keybuf)
 {
 	struct orinoco_private *priv = dev->priv;
 	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
@@ -2562,30 +2863,25 @@
 	int restricted = priv->wep_restrict;
 	u16 xlen = 0;
 	int err = 0;
-	char keybuf[ORINOCO_MAX_KEY_SIZE];
 	unsigned long flags;

-	if (erq->pointer) {
-		/* We actually have a key to set */
-		if ( (erq->length < SMALL_KEY_SIZE) || (erq->length > ORINOCO_MAX_KEY_SIZE) )
-			return -EINVAL;
-
-		if (copy_from_user(keybuf, erq->pointer, erq->length))
-			return -EFAULT;
+	DEBUG(1, "%s: SIOCSIWENCODE\n", dev->name);
+
+	if (! priv->has_wep) {
+		return -EOPNOTSUPP;
 	}

 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
+	err = -EINPROGRESS;         /* Call commit handler */

-	if (erq->pointer) {
-		if (erq->length > ORINOCO_MAX_KEY_SIZE) {
-			err = -E2BIG;
-			goto out;
-		}
-
+	if (erq->length > 0) {
+		/* Check key size. Either it's small size, or it large (but
+		 * only if the device support large keys) - Jean II */
 		if ( (erq->length > LARGE_KEY_SIZE)
-		     || ( ! priv->has_big_wep && (erq->length > SMALL_KEY_SIZE))  ) {
+		     || ( ! priv->has_big_wep &&
+			  (erq->length > SMALL_KEY_SIZE))  ) {
 			err = -EINVAL;
 			goto out;
 		}
@@ -2632,7 +2928,7 @@
 	if (erq->flags & IW_ENCODE_RESTRICTED)
 		restricted = 1;

-	if (erq->pointer) {
+	if (erq->length > 0) {
 		priv->keys[index].len = cpu_to_le16(xlen);
 		memset(priv->keys[index].data, 0, sizeof(priv->keys[index].data));
 		memcpy(priv->keys[index].data, keybuf, erq->length);
@@ -2648,15 +2944,21 @@
 	return err;
 }

-static int orinoco_ioctl_getiwencode(struct net_device *dev, struct iw_point *erq)
+static int orinoco_ioctl_getiwencode(struct net_device *dev,
+				     struct iw_request_info *info,
+				     struct iw_point *erq,
+				     char *keybuf)
 {
 	struct orinoco_private *priv = dev->priv;
 	int index = (erq->flags & IW_ENCODE_INDEX) - 1;
 	u16 xlen = 0;
-	char keybuf[ORINOCO_MAX_KEY_SIZE];
 	int err;
 	unsigned long flags;

+	if (! priv->has_wep) {
+		return -EOPNOTSUPP;
+	}
+
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
@@ -2681,40 +2983,38 @@

 	erq->length = xlen;

-	if (erq->pointer) {
-		memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);
-	}
+	memcpy(keybuf, priv->keys[index].data, ORINOCO_MAX_KEY_SIZE);

 	orinoco_unlock(priv, &flags);

-	if (erq->pointer) {
-		if (copy_to_user(erq->pointer, keybuf, xlen))
-			return -EFAULT;
-	}
-
 	return 0;
 }

-static int orinoco_ioctl_setessid(struct net_device *dev, struct iw_point *erq)
+static int orinoco_ioctl_setessid(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_point *erq,
+				  char *essidbuf)
 {
 	struct orinoco_private *priv = dev->priv;
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
 	int err;
 	unsigned long flags;

 	/* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it
 	 * anyway... - Jean II */

-	memset(&essidbuf, 0, sizeof(essidbuf));
-
-	if (erq->flags) {
-		if (erq->length > IW_ESSID_MAX_SIZE)
-			return -E2BIG;
+	/* Hum... Should not use Wireless Extension constant (may change),
+	 * should use our own... - Jean II */
+	if (erq->length > IW_ESSID_MAX_SIZE)
+		return -E2BIG;

-		if (copy_from_user(&essidbuf, erq->pointer, erq->length))
-			return -EFAULT;
+	orinoco_lock(priv, &flags);
+
+	/* NULL the string (for NULL termination & ESSID = ANY) - Jean II */
+	memset(priv->desired_essid, 0, sizeof(priv->desired_essid));

-		essidbuf[erq->length] = '\0';
+	/* If not ANY, get the new ESSID */
+	if (erq->flags) {
+		memcpy(priv->desired_essid, essidbuf, erq->length);
 	}

 	err = orinoco_lock(priv, &flags);
@@ -2725,17 +3025,20 @@

 	orinoco_unlock(priv, &flags);

-	return 0;
+	return -EINPROGRESS;		/* Call commit handler */
 }

-static int orinoco_ioctl_getessid(struct net_device *dev, struct iw_point *erq)
+static int orinoco_ioctl_getessid(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_point *erq,
+				  char *essidbuf)
 {
 	struct orinoco_private *priv = dev->priv;
-	char essidbuf[IW_ESSID_MAX_SIZE+1];
-	int active;
+	int active;	/* ??? */
 	int err = 0;
 	unsigned long flags;

+	DEBUG(1, "%s: SIOCGIWESSID\n", dev->name);
 	TRACE_ENTER(dev->name);

 	if (netif_running(dev)) {
@@ -2752,29 +3055,27 @@

 	erq->flags = 1;
 	erq->length = strlen(essidbuf) + 1;
-	if (erq->pointer)
-		if ( copy_to_user(erq->pointer, essidbuf, erq->length) )
-			return -EFAULT;

 	TRACE_EXIT(dev->name);

 	return 0;
 }

-static int orinoco_ioctl_setnick(struct net_device *dev, struct iw_point *nrq)
+static int orinoco_ioctl_setnick(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_point *nrq,
+				 char *nickbuf)
 {
 	struct orinoco_private *priv = dev->priv;
-	char nickbuf[IW_ESSID_MAX_SIZE+1];
 	int err;
 	unsigned long flags;

 	if (nrq->length > IW_ESSID_MAX_SIZE)
 		return -E2BIG;

-	memset(nickbuf, 0, sizeof(nickbuf));
+	orinoco_lock(priv, &flags);

-	if (copy_from_user(nickbuf, nrq->pointer, nrq->length))
-		return -EFAULT;
+	memset(priv->nick, 0, sizeof(priv->nick));

 	nickbuf[nrq->length] = '\0';

@@ -2786,13 +3087,15 @@

 	orinoco_unlock(priv, &flags);

-	return 0;
+	return -EINPROGRESS;		/* Call commit handler */
 }

-static int orinoco_ioctl_getnick(struct net_device *dev, struct iw_point *nrq)
+static int orinoco_ioctl_getnick(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_point *nrq,
+				 char *nickbuf)
 {
 	struct orinoco_private *priv = dev->priv;
-	char nickbuf[IW_ESSID_MAX_SIZE+1];
 	int err;
 	unsigned long flags;

@@ -2803,21 +3106,23 @@
 	memcpy(nickbuf, priv->nick, IW_ESSID_MAX_SIZE+1);
 	orinoco_unlock(priv, &flags);

-	nrq->length = strlen(nickbuf)+1;
-
-	if (copy_to_user(nrq->pointer, nickbuf, sizeof(nickbuf)))
-		return -EFAULT;
+	nrq->length = strlen(nickbuf) + 1;

 	return 0;
 }

-static int orinoco_ioctl_setfreq(struct net_device *dev, struct iw_freq *frq)
+static int orinoco_ioctl_setfreq(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_freq *frq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int chan = -1;
 	int err;
 	unsigned long flags;

+	DEBUG(1, "%s: SIOCSIWFREQ\n", dev->name);
+
 	/* We can only use this in Ad-Hoc demo mode to set the operating
 	 * frequency, or in IBSS mode to set the frequency where the IBSS
 	 * will be created - Jean II */
@@ -2850,10 +3155,28 @@
 	priv->channel = chan;
 	orinoco_unlock(priv, &flags);

+	return -EINPROGRESS;		/* Call commit handler */
+}
+
+static int orinoco_ioctl_getfreq(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_freq *frq,
+				 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+
+	DEBUG(1, "%s: SIOCGIWFREQ\n", dev->name);
+
+	/* Locking done in there */
+	frq->m = orinoco_hw_get_freq(priv);
+	frq->e = 1;
 	return 0;
 }

-static int orinoco_ioctl_getsens(struct net_device *dev, struct iw_param *srq)
+static int orinoco_ioctl_getsens(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *srq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	hermes_t *hw = &priv->hw;
@@ -2861,8 +3184,7 @@
 	int err;
 	unsigned long flags;

-	if (!priv->has_sensitivity)
-		return -EOPNOTSUPP;
+	DEBUG(1, "%s: SIOCGIWSENS\n", dev->name);

 	err = orinoco_lock(priv, &flags);
 	if (err)
@@ -2879,15 +3201,17 @@
 	return 0;
 }

-static int orinoco_ioctl_setsens(struct net_device *dev, struct iw_param *srq)
+static int orinoco_ioctl_setsens(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *srq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int val = srq->value;
 	int err;
 	unsigned long flags;

-	if (!priv->has_sensitivity)
-		return -EOPNOTSUPP;
+	DEBUG(1, "%s: SIOCSIWSENS\n", dev->name);

 	if ((val < 1) || (val > 3))
 		return -EINVAL;
@@ -2898,16 +3222,21 @@
 	priv->ap_density = val;
 	orinoco_unlock(priv, &flags);

-	return 0;
+	return -EINPROGRESS;		/* Call commit handler */
 }

-static int orinoco_ioctl_setrts(struct net_device *dev, struct iw_param *rrq)
+static int orinoco_ioctl_setrts(struct net_device *dev,
+				struct iw_request_info *info,
+				struct iw_param *rrq,
+				char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int val = rrq->value;
 	int err;
 	unsigned long flags;

+	DEBUG(1, "%s: SIOCSIWRTS\n", dev->name);
+
 	if (rrq->disabled)
 		val = 2347;

@@ -2921,10 +3250,28 @@
 	priv->rts_thresh = val;
 	orinoco_unlock(priv, &flags);

+	return -EINPROGRESS;		/* Call commit handler */
+}
+
+static int orinoco_ioctl_getrts(struct net_device *dev,
+				struct iw_request_info *info,
+				struct iw_param *rrq,
+				char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+
+	DEBUG(1, "%s: SIOCGIWRTS\n", dev->name);
+
+	rrq->value = priv->rts_thresh;
+	rrq->disabled = (rrq->value == 2347);
+	rrq->fixed = 1;
 	return 0;
 }

-static int orinoco_ioctl_setfrag(struct net_device *dev, struct iw_param *frq)
+static int orinoco_ioctl_setfrag(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *frq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int err = 0;
@@ -2933,6 +3280,7 @@
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
+	err = -EINPROGRESS;         /* Call commit handler */

 	if (priv->has_mwo) {
 		if (frq->disabled)
@@ -2947,10 +3295,12 @@
 		if (frq->disabled)
 			priv->frag_thresh = 2346;
 		else {
-			if ( (frq->value < 256) || (frq->value > 2346) )
+			if ( (frq->value < 256) ||
+			     (frq->value > 2346) )
 				err = -EINVAL;
 			else
-				priv->frag_thresh = frq->value & ~0x1; /* must be even */
+				/* value must be even */
+				priv->frag_thresh = frq->value & ~0x1;
 		}
 	}

@@ -2959,7 +3309,10 @@
 	return err;
 }

-static int orinoco_ioctl_getfrag(struct net_device *dev, struct iw_param *frq)
+static int orinoco_ioctl_getfrag(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *frq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	hermes_t *hw = &priv->hw;
@@ -2997,7 +3350,10 @@
 	return err;
 }

-static int orinoco_ioctl_setrate(struct net_device *dev, struct iw_param *rrq)
+static int orinoco_ioctl_setrate(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *rrq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int err = 0;
@@ -3006,6 +3362,8 @@
 	int i;
 	unsigned long flags;

+	DEBUG(1, "%s: SIOCSIWRATE\n", dev->name);
+
 	/* As the user space doesn't know our highest rate, it uses -1
 	 * to ask us to set the highest rate.  Test it using "iwconfig
 	 * ethX rate auto" - Jean II */
@@ -3034,13 +3392,17 @@
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
+	err = -EINPROGRESS;		/* Call commit handler */
 	priv->bitratemode = ratemode;
 	orinoco_unlock(priv, &flags);

 	return err;
 }

-static int orinoco_ioctl_getrate(struct net_device *dev, struct iw_param *rrq)
+static int orinoco_ioctl_getrate(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *rrq,
+				 char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	hermes_t *hw = &priv->hw;
@@ -3082,7 +3444,7 @@
 				rrq->value = 5500000;
 			else
 				rrq->value = val * 1000000;
-                        break;
+			break;
 		case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */
 		case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */
 			for (i = 0; i < BITRATE_TABLE_SIZE; i++)
@@ -3107,7 +3469,10 @@
 	return err;
 }

-static int orinoco_ioctl_setpower(struct net_device *dev, struct iw_param *prq)
+static int orinoco_ioctl_setpower(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *prq,
+				  char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	int err = 0;
@@ -3116,6 +3481,7 @@
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
+	err = -EINPROGRESS;         /* Call commit handler */

 	if (prq->disabled) {
 		priv->pm_on = 0;
@@ -3160,7 +3526,10 @@
 	return err;
 }

-static int orinoco_ioctl_getpower(struct net_device *dev, struct iw_param *prq)
+static int orinoco_ioctl_getpower(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *prq,
+				  char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	hermes_t *hw = &priv->hw;
@@ -3171,7 +3540,6 @@
 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
-
 	err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFPMENABLED, &enable);
 	if (err)
 		goto out;
@@ -3209,8 +3577,26 @@
 	return err;
 }

+static int orinoco_ioctl_gettxpower(struct net_device *dev,
+				    struct iw_request_info *info,
+				    struct iw_param *trq,
+				    char *extra)
+{
+	DEBUG(1, "%s: SIOCGIWTXPOW\n", dev->name);
+
+	/* The card only supports one tx power, so this is easy */
+	trq->value = 15; /* dBm */
+	trq->fixed = 1;
+	trq->disabled = 0;
+	trq->flags = IW_TXPOW_DBM;
+	return 0;
+}
+
 #if WIRELESS_EXT > 10
-static int orinoco_ioctl_getretry(struct net_device *dev, struct iw_param *rrq)
+static int orinoco_ioctl_getretry(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_param *rrq,
+				  char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
 	hermes_t *hw = &priv->hw;
@@ -3263,11 +3649,101 @@
 }
 #endif /* WIRELESS_EXT > 10 */

-static int orinoco_ioctl_setibssport(struct net_device *dev, struct iwreq *wrq)
+static int orinoco_ioctl_reset(struct net_device *dev,
+			       struct iw_request_info *info,
+			       void *wrqu,
+			       char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	int val = *( (int *) wrq->u.name );
-	int err;
+
+	DEBUG(1, "%s: SIOCIWFIRSTPRIV + 0x%d (force_reset)\n",
+	      dev->name, info->cmd - SIOCIWFIRSTPRIV);
+
+	if (! capable(CAP_NET_ADMIN))
+		return -EPERM;
+
+	printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name);
+
+	/* COR reset as needed */
+	/* card_reset_handler renamed to hard_reset -- Moustafa */
+	if((info->cmd == (SIOCIWFIRSTPRIV + 0x1)) &&
+	   (priv->hard_reset != NULL))
+		priv->hard_reset(priv);
+
+	/* Firmware reset */
+	orinoco_reset(dev);
+
+	return 0;
+}
+
+static int orinoco_ioctl_setpreamble(struct net_device *dev,
+				     struct iw_request_info *info,
+				     void *wrqu,
+				     char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+
+	DEBUG(1, "%s: SIOCIWFIRSTPRIV + 0x4 (set_preamble)\n",
+	      dev->name);
+
+	/* 802.11b has recently defined some short preamble.
+	 * Basically, the Phy header has been reduced in size.
+	 * This increase performance, especially at high rates
+	 * (the preamble is transmitted at 1Mb/s), unfortunately
+	 * this give compatibility troubles... - Jean II */
+	if(priv->has_preamble) {
+		int err = 0;
+		unsigned long flags;
+		int val = *( (int *) extra );
+
+		err = orinoco_lock(priv, &flags);
+		if (err)
+		       return err;
+		if(val)
+			priv->preamble = 1;
+		else
+			priv->preamble = 0;
+		orinoco_unlock(priv, &flags);
+
+		return -EINPROGRESS;		/* Call commit handler */
+	} else
+		return -EOPNOTSUPP;
+}
+
+static int orinoco_ioctl_getpreamble(struct net_device *dev,
+				     struct iw_request_info *info,
+				     void *wrqu,
+				     char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+
+	DEBUG(1, "%s: SIOCIWFIRSTPRIV + 0x5 (get_preamble)\n",
+	      dev->name);
+
+	if(priv->has_preamble) {
+		int err = 0;
+		unsigned long flags;
+		int *val = (int *) extra;
+
+		err = orinoco_lock(priv, &flags);
+		if (err)
+		       return err;
+		*val = priv->preamble;
+		orinoco_unlock(priv, &flags);
+
+		return 0;
+	} else
+		return -EOPNOTSUPP;
+}
+
+static int orinoco_ioctl_setibssport(struct net_device *dev,
+				     struct iw_request_info *info,
+				     void *wrqu,
+				     char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int val = *( (int *) extra );
+	int err = 0;
 	unsigned long flags;

 	err = orinoco_lock(priv, &flags);
@@ -3280,13 +3756,16 @@
 	set_port_type(priv);

 	orinoco_unlock(priv, &flags);
-	return 0;
+	return -EINPROGRESS;
 }

-static int orinoco_ioctl_getibssport(struct net_device *dev, struct iwreq *wrq)
+static int orinoco_ioctl_getibssport(struct net_device *dev,
+				     struct iw_request_info *info,
+				     void *wrqu,
+				     char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	int *val = (int *)wrq->u.name;
+	int *val = (int *) extra;
 	int err;
 	unsigned long flags;

@@ -3300,16 +3779,20 @@
 	return 0;
 }

-static int orinoco_ioctl_setport3(struct net_device *dev, struct iwreq *wrq)
+static int orinoco_ioctl_setport3(struct net_device *dev,
+				  struct iw_request_info *info,
+				  void *wrqu,
+				  char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	int val = *( (int *) wrq->u.name );
+	int val = *( (int *) extra );
 	int err = 0;
 	unsigned long flags;

 	err = orinoco_lock(priv, &flags);
 	if (err)
 		return err;
+	err = -EINPROGRESS;         /* Call commit handler */

 	switch (val) {
 	case 0: /* Try to do IEEE ad-hoc mode */
@@ -3342,10 +3825,13 @@
 	return err;
 }

-static int orinoco_ioctl_getport3(struct net_device *dev, struct iwreq *wrq)
+static int orinoco_ioctl_getport3(struct net_device *dev,
+				  struct iw_request_info *info,
+				  void *wrqu,
+				  char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	int *val = (int *)wrq->u.name;
+	int *val = (int *) extra;
 	int err;
 	unsigned long flags;

@@ -3361,25 +3847,19 @@

 /* Spy is used for link quality/strength measurements in Ad-Hoc mode
  * Jean II */
-static int orinoco_ioctl_setspy(struct net_device *dev, struct iw_point *srq)
+static int orinoco_ioctl_setspy(struct net_device *dev,
+				struct iw_request_info *info,
+				struct iw_point *srq,
+				char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	struct sockaddr address[IW_MAX_SPY];
+	struct sockaddr *address = (struct sockaddr *) extra;
 	int number = srq->length;
 	int i;
-	int err = 0;
+	int err = 0;		/* Do NOT call commit handler */
 	unsigned long flags;

-	/* Check the number of addresses */
-	if (number > IW_MAX_SPY)
-		return -E2BIG;
-
-	/* Get the data in the driver */
-	if (srq->pointer) {
-		if (copy_from_user(address, srq->pointer,
-				   sizeof(struct sockaddr) * number))
-			return -EFAULT;
-	}
+	DEBUG(1, "%s: SIOCSIWSPY\n", dev->name);

 	/* Make sure nobody mess with the structure while we do */
 	err = orinoco_lock(priv, &flags);
@@ -3408,11 +3888,13 @@
 	return err;
 }

-static int orinoco_ioctl_getspy(struct net_device *dev, struct iw_point *srq)
+static int orinoco_ioctl_getspy(struct net_device *dev,
+				struct iw_request_info *info,
+				struct iw_point *srq,
+				char *extra)
 {
 	struct orinoco_private *priv = dev->priv;
-	struct sockaddr address[IW_MAX_SPY];
-	struct iw_quality spy_stat[IW_MAX_SPY];
+	struct sockaddr *address = (struct sockaddr *) extra;
 	int number;
 	int i;
 	int err;
@@ -3423,41 +3905,410 @@
 		return err;

 	number = priv->spy_number;
-	if ((number > 0) && (srq->pointer)) {
-		/* Create address struct */
-		for (i = 0; i < number; i++) {
-			memcpy(address[i].sa_data, priv->spy_address[i],
-			       ETH_ALEN);
-			address[i].sa_family = AF_UNIX;
-		}
+	/* Create address struct */
+	for (i = 0; i < number; i++) {
+		memcpy(address[i].sa_data, priv->spy_address[i],
+		       ETH_ALEN);
+		address[i].sa_family = AF_UNIX;
+	}
+	if (number > 0) {
 		/* Copy stats */
 		/* In theory, we should disable irqs while copying the stats
 		 * because the rx path migh update it in the middle...
 		 * Bah, who care ? - Jean II */
-		memcpy(&spy_stat, priv->spy_stat,
-		       sizeof(struct iw_quality) * IW_MAX_SPY);
-		for (i=0; i < number; i++)
-			priv->spy_stat[i].updated = 0;
+		memcpy(extra  + (sizeof(struct sockaddr) * number),
+		       priv->spy_stat, sizeof(struct iw_quality) * number);
 	}
+	/* Reset updated flags. */
+	for (i=0; i < number; i++)
+		priv->spy_stat[i].updated = 0;

 	orinoco_unlock(priv, &flags);

-	/* Push stuff to user space */
 	srq->length = number;
-	if(copy_to_user(srq->pointer, address,
-			 sizeof(struct sockaddr) * number))
-		return -EFAULT;
-	if(copy_to_user(srq->pointer + (sizeof(struct sockaddr)*number),
-			&spy_stat, sizeof(struct iw_quality) * number))
-		return -EFAULT;

 	return 0;
 }

+#if WIRELESS_EXT > 13
+/* Trigger a scan (look for other cells in the vicinity */
+static int orinoco_ioctl_setscan(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_param *srq,
+				 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	hermes_t *hw = &priv->hw;
+	int err = 0;
+	unsigned long flags;
+
+	/* Note : you may have realised that, as this is a SET operation,
+	 * this is priviledged and therefore a normal user can't
+	 * perform scanning.
+	 * This is not an error, while the device perform scanning,
+	 * traffic doesn't flow, so it's a perfect DoS...
+	 * Jean II */
+
+	orinoco_lock(priv, &flags);
+
+	/* Note : because we don't lock out the irq handler, the way
+	 * we access scan variables in priv is critical.
+	 *	o scan_inprogress : not touched by irq handler
+	 *	o scan_mode : not touched by irq handler
+	 *	o scan_result : irq is strict producer, non-irq is strict
+	 *		consumer.
+	 *	o scan_len : synchronised with scan_result
+	 * Before modifying anything on those variables, please think hard !
+	 * Jean II */
+
+	/* If there is still some left-over scan results, get rid of it */
+	if(priv->scan_result != NULL) {
+		/* What's likely is that a client did crash or was killed
+		 * between triggering the scan request and reading the
+		 * results, so we need to reset everything.
+		 * Some clients that are too slow may suffer from that...
+		 * Jean II */
+		DEBUG(1, "%s: scan KFREE %p\n", dev->name, priv->scan_result);
+		kfree(priv->scan_result);
+		priv->scan_result = NULL;
+	}
+
+	/* Save flags */
+	priv->scan_mode = srq->flags;
+
+	/* Always trigger scanning, even if it's in progress.
+	 * This way, if the info frame get lost, we will recover somewhat
+	 * gracefully  - Jean II */
+
+	/* Simple scanning for now...
+	 * We will do better later - Jean II */
+	err = hermes_inquire(hw, HERMES_INQ_SCAN);
+
+	/* One more client */
+	priv->scan_inprogress = 1;
+
+	orinoco_unlock(priv, &flags);
+	return 0;
+}
+
+/* Translate scan data returned from the card to a card independant
+ * format that the Wireless Tools will understand - Jean II */
+static inline int orinoco_translate_scan(struct net_device *dev,
+					 char *buffer,
+					 char *scan,
+					 int scan_len)
+{
+	struct orinoco_private *priv = dev->priv;
+	int			offset;		/* In the scan data */
+	union hermes_scan_info *atom;
+	int			atom_len;
+	u16			capabilities;
+	struct iw_event		iwe;		/* Temporary buffer */
+	char *			current_ev = buffer;
+	char *			end_buf = buffer + IW_SCAN_MAX_DATA;
+
+	if(priv->firmware_type == FIRMWARE_TYPE_AGERE) {
+		atom_len = sizeof(struct agere_scan_apinfo);
+		offset = 0;
+	} else {
+		atom_len = sizeof(struct prism2_scan_apinfo);
+		//offset = sizeof(struct prism2_scan_frame);
+		offset = 4;
+	}
+
+	DEBUG(4, "%s: scan_len = %d, atom_len = %d\n", dev->name,
+	      scan_len, atom_len);
+
+	/* Read the entries one by one */
+	for(; offset + atom_len <= scan_len; offset += atom_len) {
+		/* Get next atom */
+		atom = (union hermes_scan_info *) (scan + offset);
+
+		DEBUG(4, "%s: offset = %d, current_ev = %p, end_buf = %p, ap_addr = %02x:%02x:%02x:%02x:%02x:%02x\n", dev->name, offset, current_ev, end_buf, atom->a.bssid[0], atom->a.bssid[1], atom->a.bssid[2], atom->a.bssid[3], atom->a.bssid[4], atom->a.bssid[5]);
+
+		/* First entry *MUST* be the AP MAC address */
+		iwe.cmd = SIOCGIWAP;
+		iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
+		memcpy(iwe.u.ap_addr.sa_data, atom->a.bssid, ETH_ALEN);
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_ADDR_LEN);
+
+		/* Other entries will be displayed in the order we give them */
+
+		/* Add the ESSID */
+		iwe.u.data.length = le16_to_cpu(atom->a.essid_len);
+		if(iwe.u.data.length > 32)
+			iwe.u.data.length = 32;
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.data.flags = 1;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
+
+		/* Add mode */
+		iwe.cmd = SIOCGIWMODE;
+		capabilities = le16_to_cpu(atom->a.capabilities);
+		if(capabilities & 0x3) {
+			if(capabilities & 0x1)
+				iwe.u.mode = IW_MODE_INFRA;
+			else
+				iwe.u.mode = IW_MODE_ADHOC;
+			current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_UINT_LEN);
+		}
+
+		/* Add frequency */
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = channel_frequency[le16_to_cpu(atom->a.channel)-1] * 100000;
+		iwe.u.freq.e = 1;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_FREQ_LEN);
+
+		/* Add quality statistics */
+		iwe.cmd = IWEVQUAL;
+		iwe.u.qual.level = (__u8) le16_to_cpu(atom->a.level) - 0x95;
+		iwe.u.qual.noise = (__u8) le16_to_cpu(atom->a.noise) - 0x95;
+		current_ev = iwe_stream_add_event(current_ev, end_buf, &iwe, IW_EV_QUAL_LEN);
+
+		/* Add encryption capability */
+		/* Note : it works on Lucent/Agere cards, need to check
+		 * on PrismII cards - Jean */
+		iwe.cmd = SIOCGIWENCODE;
+		if(capabilities & 0x10)
+			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+		else
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+		iwe.u.data.length = 0;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe, atom->a.essid);
+
+		/* Bit rate is only available with PrismII firmwares */
+		if(priv->firmware_type != FIRMWARE_TYPE_AGERE) {
+			char *	current_val = current_ev + IW_EV_LCP_LEN;
+			int	i;
+
+			iwe.cmd = SIOCGIWRATE;
+			/* Those two flags are ignored... */
+			iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0;
+			/* Max 10 values */
+			for(i = 0; i < 10; i++) {
+				/* NULL terminated */
+				if(atom->p.rates[i] == 0x0)
+					break;
+				/* Bit rate given in 500 kb/s units (+ 0x80) */
+				iwe.u.bitrate.value = ((atom->p.rates[i] & 0x7f) * 500000);
+				current_val = iwe_stream_add_value(current_ev, current_val, end_buf, &iwe, IW_EV_PARAM_LEN);
+			}
+			/* Check if we added any event */
+			if((current_val - current_ev) > IW_EV_LCP_LEN)
+				current_ev = current_val;
+		}
+
+		/* The other data in the scan result are not really
+		 * interesting, so for now drop it - Jean II */
+	}
+	return current_ev - buffer;
+}
+
+/* Return results of a scan */
+static int orinoco_ioctl_getscan(struct net_device *dev,
+				 struct iw_request_info *info,
+				 struct iw_point *srq,
+				 char *extra)
+{
+	struct orinoco_private *priv = dev->priv;
+	int err = 0;
+	unsigned long flags;
+
+	err = orinoco_lock(priv, &flags);
+	if (err)
+		return err;
+
+	/* If no results yet, ask to try again later */
+	if(priv->scan_result == NULL) {
+		if(priv->scan_inprogress)
+			/* Important note : we don't want to block the caller
+			 * until results are ready for various reasons.
+			 * First, managing wait queues is complex and racy.
+			 * Second, we grab some rtnetlink lock before comming
+			 * here (in dev_ioctl()).
+			 * Third, we generate an Wireless Event, so the
+			 * caller can wait itself on that - Jean II */
+			err = -EAGAIN;
+		else
+			/* Client error, no scan results...
+			 * The caller need to restart the scan. */
+			err = -ENODATA;
+	} else {
+		/* We have some results to push back to user space */
+
+		/* Translate to WE format */
+		srq->length = orinoco_translate_scan(dev, extra,
+						     priv->scan_result,
+						     priv->scan_len);
+
+		/* Return flags */
+		srq->flags = (__u16) priv->scan_mode;
+
+		/* Results are here, so scan no longer in progress */
+		priv->scan_inprogress = 0;
+
+		/* In any case, Scan results will be cleaned up in the
+		 * reset function and when exiting the driver.
+		 * The person triggering the scanning may never come to
+		 * pick the results, so we need to do it in those places.
+		 * Jean II */
+
+#ifdef SCAN_SINGLE_READ
+		/* If you enable this option, only one client (the first
+		 * one) will be able to read the result (and only one
+		 * time). If there is multiple concurent clients that
+		 * want to read scan results, this behavior is not
+		 * advisable - Jean II */
+		DEBUG(1, "%s: scan KFREE %p\n",
+		      dev->name, priv->scan_result);
+		kfree(priv->scan_result);
+		priv->scan_result = NULL;
+#endif /* SCAN_SINGLE_READ */
+		/* Here, if too much time has elapsed since last scan,
+		 * we may want to clean up scan results... - Jean II */
+	}
+
+	orinoco_unlock(priv, &flags);
+	return err;
+}
+#endif	/* WIRELESS_EXT > 13 */
+
+/* Commit handler, called after a bunch of SET operation */
+static int orinoco_ioctl_commit(struct net_device *dev,
+				struct iw_request_info *info,	/* NULL */
+				void *wrqu,                     /* NULL */
+				char *extra)			/* NULL */
+{
+	struct orinoco_private *priv = dev->priv;
+	int err = 0;
+
+	DEBUG(1, "%s: SIOCSIWCOMMIT (set change commit)\n", dev->name);
+
+	err = orinoco_reconfigure(priv);
+	if (err) {
+		/* Ouch ! What are we supposed to do ? */
+		printk(KERN_ERR "orinoco_cs: Failed to set parameters on %s\n",
+		       dev->name);
+		netif_device_detach(dev);
+		/* orinoco_shutdown(dev); seems to have vanished */
+	}
+
+	return err;
+}
+
+static const struct iw_priv_args orinoco_privtab[] = {
+	{ SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
+	{ SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
+	{ SIOCIWFIRSTPRIV + 0x2,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_port3" },
+	{ SIOCIWFIRSTPRIV + 0x3, 0,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  "get_port3" },
+	{ SIOCIWFIRSTPRIV + 0x4,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_preamble" },
+	{ SIOCIWFIRSTPRIV + 0x5, 0,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  "get_preamble" },
+	{ SIOCIWFIRSTPRIV + 0x6,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  0, "set_ibssport" },
+	{ SIOCIWFIRSTPRIV + 0x7, 0,
+	  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	  "get_ibssport" }
+};
+
+#if WIRELESS_EXT > 12
+
+/*
+ * Structures to export the Wireless Handlers
+ */
+
+static const iw_handler		orinoco_handler[] =
+{
+	(iw_handler) orinoco_ioctl_commit,		/* SIOCSIWCOMMIT */
+	(iw_handler) orinoco_ioctl_getname,		/* SIOCGIWNAME */
+	(iw_handler) NULL,				/* SIOCSIWNWID */
+	(iw_handler) NULL,				/* SIOCGIWNWID */
+	(iw_handler) orinoco_ioctl_setfreq,		/* SIOCSIWFREQ */
+	(iw_handler) orinoco_ioctl_getfreq,		/* SIOCGIWFREQ */
+	(iw_handler) orinoco_ioctl_setmode,		/* SIOCSIWMODE */
+	(iw_handler) orinoco_ioctl_getmode,		/* SIOCGIWMODE */
+	(iw_handler) orinoco_ioctl_setsens,		/* SIOCSIWSENS */
+	(iw_handler) orinoco_ioctl_getsens,		/* SIOCGIWSENS */
+	(iw_handler) NULL,				/* SIOCSIWRANGE */
+	(iw_handler) orinoco_ioctl_getiwrange,		/* SIOCGIWRANGE */
+	(iw_handler) NULL,				/* SIOCSIWPRIV */
+	(iw_handler) NULL,				/* SIOCGIWPRIV */
+	(iw_handler) NULL,				/* SIOCSIWSTATS */
+	(iw_handler) NULL,				/* SIOCGIWSTATS */
+	(iw_handler) orinoco_ioctl_setspy,		/* SIOCSIWSPY */
+	(iw_handler) orinoco_ioctl_getspy,		/* SIOCGIWSPY */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* SIOCSIWAP */
+	(iw_handler) orinoco_ioctl_getwap,		/* SIOCGIWAP */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* SIOCGIWAPLIST */
+#if WIRELESS_EXT > 13
+	(iw_handler) orinoco_ioctl_setscan,		/* SIOCSIWSCAN */
+	(iw_handler) orinoco_ioctl_getscan,		/* SIOCGIWSCAN */
+#else	/* WIRELESS_EXT > 13 */
+	(iw_handler) NULL,				/* SIOCSIWSCAN */
+	(iw_handler) NULL,				/* SIOCGIWSCAN */
+#endif	/* WIRELESS_EXT > 13 */
+	(iw_handler) orinoco_ioctl_setessid,		/* SIOCSIWESSID */
+	(iw_handler) orinoco_ioctl_getessid,		/* SIOCGIWESSID */
+	(iw_handler) orinoco_ioctl_setnick,		/* SIOCSIWNICKN */
+	(iw_handler) orinoco_ioctl_getnick,		/* SIOCGIWNICKN */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) NULL,				/* -- hole -- */
+	(iw_handler) orinoco_ioctl_setrate,		/* SIOCSIWRATE */
+	(iw_handler) orinoco_ioctl_getrate,		/* SIOCGIWRATE */
+	(iw_handler) orinoco_ioctl_setrts,		/* SIOCSIWRTS */
+	(iw_handler) orinoco_ioctl_getrts,		/* SIOCGIWRTS */
+	(iw_handler) orinoco_ioctl_setfrag,		/* SIOCSIWFRAG */
+	(iw_handler) orinoco_ioctl_getfrag,		/* SIOCGIWFRAG */
+	(iw_handler) NULL,				/* SIOCSIWTXPOW */
+	(iw_handler) orinoco_ioctl_gettxpower,		/* SIOCGIWTXPOW */
+	(iw_handler) NULL,				/* SIOCSIWRETRY */
+	(iw_handler) orinoco_ioctl_getretry,		/* SIOCGIWRETRY */
+	(iw_handler) orinoco_ioctl_setiwencode,		/* SIOCSIWENCODE */
+	(iw_handler) orinoco_ioctl_getiwencode,		/* SIOCGIWENCODE */
+	(iw_handler) orinoco_ioctl_setpower,		/* SIOCSIWPOWER */
+	(iw_handler) orinoco_ioctl_getpower,		/* SIOCGIWPOWER */
+};
+
+/*
+  Added typecasting since we no longer use iwreq_data -- Moustafa
+ */
+static const iw_handler		orinoco_private_handler[] =
+{
+	(iw_handler) orinoco_ioctl_reset,		/* SIOCIWFIRSTPRIV */
+	(iw_handler) orinoco_ioctl_reset,		/* SIOCIWFIRSTPRIV + 1 */
+	(iw_handler) orinoco_ioctl_setport3,		/* SIOCIWFIRSTPRIV + 2 */
+	(iw_handler) orinoco_ioctl_getport3,		/* SIOCIWFIRSTPRIV + 3 */
+	(iw_handler) orinoco_ioctl_setpreamble,	/* SIOCIWFIRSTPRIV + 4 */
+	(iw_handler) orinoco_ioctl_getpreamble,	/* SIOCIWFIRSTPRIV + 5 */
+	(iw_handler) orinoco_ioctl_setibssport,	/* SIOCIWFIRSTPRIV + 6 */
+	(iw_handler) orinoco_ioctl_getibssport,	/* SIOCIWFIRSTPRIV + 7 */
+};
+
+static const struct iw_handler_def	orinoco_handler_def =
+{
+	num_standard:	sizeof(orinoco_handler)/sizeof(iw_handler),
+	num_private:	sizeof(orinoco_private_handler)/sizeof(iw_handler),
+	num_private_args: sizeof(orinoco_privtab)/sizeof(struct iw_priv_args),
+	standard:	(iw_handler *) orinoco_handler,
+	private:	(iw_handler *) orinoco_private_handler,
+	private_args:	(struct iw_priv_args *) orinoco_privtab,
+};
+
+#else /* WIRELESS_EXT > 12 */
 static int
 orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	struct orinoco_private *priv = dev->priv;
 	struct iwreq *wrq = (struct iwreq *)rq;
 	int err = 0;
 	int tmp;
@@ -3477,172 +4328,195 @@

 	switch (cmd) {
 	case SIOCGIWNAME:
-		strcpy(wrq->u.name, "IEEE 802.11-DS");
+		orinoco_ioctl_getname(dev, NULL, &(wrq->u), NULL);
 		break;

 	case SIOCGIWAP:
-		wrq->u.ap_addr.sa_family = ARPHRD_ETHER;
-		err = orinoco_hw_get_bssid(priv, wrq->u.ap_addr.sa_data);
+		err = orinoco_ioctl_getwap(dev, NULL, &(wrq->u.ap_addr), NULL);
 		break;

 	case SIOCGIWRANGE:
-		err = orinoco_ioctl_getiwrange(dev, &wrq->u.data);
+		{
+			struct iw_range range;
+			err = orinoco_ioctl_getiwrange(dev, NULL,
+						       &(wrq->u.data),
+						       (char *) &range);
+			if (copy_to_user(wrq->u.data.pointer, &range,
+					 sizeof(struct iw_range)))
+				err = -EFAULT;
+		}
 		break;

 	case SIOCSIWMODE:
-		err = orinoco_lock(priv, &flags);
-		if (err)
-			return err;
-		switch (wrq->u.mode) {
-		case IW_MODE_ADHOC:
-			if (! (priv->has_ibss || priv->has_port3) )
-				err = -EINVAL;
-			else {
-				priv->iw_mode = IW_MODE_ADHOC;
-				changed = 1;
-			}
-			break;
-
-		case IW_MODE_INFRA:
-			priv->iw_mode = IW_MODE_INFRA;
-			changed = 1;
-			break;
-
-		default:
-			err = -EINVAL;
-			break;
-		}
-		set_port_type(priv);
-		orinoco_unlock(priv, &flags);
+		err = orinoco_ioctl_setmode(dev, NULL, &(wrq->u.mode), NULL);
 		break;

 	case SIOCGIWMODE:
-		err = orinoco_lock(priv, &flags);
-		if (err)
-			return err;
-		wrq->u.mode = priv->iw_mode;
-		orinoco_unlock(priv, &flags);
+		orinoco_ioctl_getmode(dev, NULL, &(wrq->u.mode), NULL);
 		break;

 	case SIOCSIWENCODE:
-		if (! priv->has_wep) {
-			err = -EOPNOTSUPP;
-			break;
+		{
+			char keybuf[ORINOCO_MAX_KEY_SIZE];
+			if (! priv->has_wep) {
+				err = -EOPNOTSUPP;
+			} else if (wrq->u.encoding.pointer) {
+				/* We actually have a key to set */
+				if (wrq->u.encoding.length > ORINOCO_MAX_KEY_SIZE) {
+					err = -E2BIG;
+					break;
+				}
+				if (copy_from_user(keybuf,
+						   wrq->u.encoding.pointer,
+						   wrq->u.encoding.length)) {
+					err = -EFAULT;
+					break;
+				}
+			} else if (wrq->u.encoding.length != 0) {
+				err = -EINVAL;
+				break;
+			}
+			err = orinoco_ioctl_setiwencode(dev, NULL, &(wrq->u.encoding), keybuf);
 		}
-
-		err = orinoco_ioctl_setiwencode(dev, &wrq->u.encoding);
-		if (! err)
-			changed = 1;
 		break;

 	case SIOCGIWENCODE:
+		if (! capable(CAP_NET_ADMIN)) {
+			err = -EPERM;
+			break;
+		}
 		if (! priv->has_wep) {
 			err = -EOPNOTSUPP;
 			break;
 		}
-
-		if (! capable(CAP_NET_ADMIN)) {
-			err = -EPERM;
-			break;
+		{
+			char keybuf[ORINOCO_MAX_KEY_SIZE];
+			err = orinoco_ioctl_getiwencode(dev, NULL,
+							&(wrq->u.encoding),
+							keybuf);
+			if (wrq->u.encoding.pointer) {
+				if (copy_to_user(wrq->u.encoding.pointer,
+						 keybuf,
+						 wrq->u.encoding.length))
+					err= -EFAULT;
+			}
 		}
-
-		err = orinoco_ioctl_getiwencode(dev, &wrq->u.encoding);
 		break;

 	case SIOCSIWESSID:
-		err = orinoco_ioctl_setessid(dev, &wrq->u.essid);
-		if (! err)
-			changed = 1;
+		{
+			char essidbuf[IW_ESSID_MAX_SIZE+1];
+			if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
+				err = -E2BIG;
+				break;
+			}
+			if (copy_from_user(essidbuf, wrq->u.essid.pointer,
+					   wrq->u.essid.length)) {
+				err = -EFAULT;
+				break;
+			}
+			err = orinoco_ioctl_setessid(dev, NULL,
+						     &(wrq->u.essid),
+						     essidbuf);
+		}
 		break;

 	case SIOCGIWESSID:
-		err = orinoco_ioctl_getessid(dev, &wrq->u.essid);
+		{
+			char essidbuf[IW_ESSID_MAX_SIZE+1];
+			err = orinoco_ioctl_getessid(dev, NULL,
+						     &(wrq->u.essid),
+						     essidbuf);
+			if (wrq->u.essid.pointer)
+				if ( copy_to_user(wrq->u.essid.pointer,
+						  essidbuf,
+						  wrq->u.essid.length) )
+					err = -EFAULT;
+		}
 		break;

 	case SIOCSIWNICKN:
-		err = orinoco_ioctl_setnick(dev, &wrq->u.data);
-		if (! err)
-			changed = 1;
+		{
+			char nickbuf[IW_ESSID_MAX_SIZE+1];
+			if (wrq->u.essid.length > IW_ESSID_MAX_SIZE) {
+				err = -E2BIG;
+				break;
+			}
+			if (copy_from_user(nickbuf, wrq->u.essid.pointer,
+					   wrq->u.essid.length)) {
+				err = -EFAULT;
+				break;
+			}
+			err = orinoco_ioctl_setnick(dev, NULL, &(wrq->u.essid),
+						    nickbuf);
+		}
 		break;

 	case SIOCGIWNICKN:
-		err = orinoco_ioctl_getnick(dev, &wrq->u.data);
+		{
+			char nickbuf[IW_ESSID_MAX_SIZE+1];
+			err = orinoco_ioctl_getnick(dev, NULL, &(wrq->u.essid),
+						    nickbuf);
+			if (wrq->u.essid.pointer)
+				if ( copy_to_user(wrq->u.essid.pointer,
+						  nickbuf,
+						  wrq->u.essid.length) )
+					err = -EFAULT;
+		}
 		break;

 	case SIOCGIWFREQ:
-		tmp = orinoco_hw_get_freq(priv);
-		if (tmp < 0) {
-			err = tmp;
-		} else {
-			wrq->u.freq.m = tmp;
-			wrq->u.freq.e = 1;
-		}
+		orinoco_ioctl_getfreq(dev, NULL, &(wrq->u.freq), NULL);
 		break;

 	case SIOCSIWFREQ:
-		err = orinoco_ioctl_setfreq(dev, &wrq->u.freq);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setfreq(dev, NULL, &(wrq->u.freq), NULL);
 		break;

 	case SIOCGIWSENS:
-		err = orinoco_ioctl_getsens(dev, &wrq->u.sens);
+		err = orinoco_ioctl_getsens(dev, NULL, &(wrq->u.sens), NULL);
 		break;

 	case SIOCSIWSENS:
-		err = orinoco_ioctl_setsens(dev, &wrq->u.sens);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setsens(dev, NULL, &(wrq->u.sens), NULL);
 		break;

 	case SIOCGIWRTS:
-		wrq->u.rts.value = priv->rts_thresh;
-		wrq->u.rts.disabled = (wrq->u.rts.value == 2347);
-		wrq->u.rts.fixed = 1;
+		orinoco_ioctl_getrts(dev, NULL, &(wrq->u.rts), NULL);
 		break;

 	case SIOCSIWRTS:
-		err = orinoco_ioctl_setrts(dev, &wrq->u.rts);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setrts(dev, NULL, &(wrq->u.rts), NULL);
 		break;

 	case SIOCSIWFRAG:
-		err = orinoco_ioctl_setfrag(dev, &wrq->u.frag);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setfrag(dev, NULL, &(wrq->u.frag), NULL);
 		break;

 	case SIOCGIWFRAG:
-		err = orinoco_ioctl_getfrag(dev, &wrq->u.frag);
+		err = orinoco_ioctl_getfrag(dev, NULL, &(wrq->u.frag), NULL);
 		break;

 	case SIOCSIWRATE:
-		err = orinoco_ioctl_setrate(dev, &wrq->u.bitrate);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setrate(dev, NULL, &(wrq->u.bitrate),
+					    NULL);
 		break;

 	case SIOCGIWRATE:
-		err = orinoco_ioctl_getrate(dev, &wrq->u.bitrate);
+		err = orinoco_ioctl_getrate(dev, NULL, &(wrq->u.bitrate),
+					    NULL);
 		break;

 	case SIOCSIWPOWER:
-		err = orinoco_ioctl_setpower(dev, &wrq->u.power);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setpower(dev, NULL, &(wrq->u.power), NULL);
 		break;

 	case SIOCGIWPOWER:
-		err = orinoco_ioctl_getpower(dev, &wrq->u.power);
+		err = orinoco_ioctl_getpower(dev, NULL, &(wrq->u.power), NULL);
 		break;

 	case SIOCGIWTXPOW:
-		/* The card only supports one tx power, so this is easy */
-		wrq->u.txpower.value = 15; /* dBm */
-		wrq->u.txpower.fixed = 1;
-		wrq->u.txpower.disabled = 0;
-		wrq->u.txpower.flags = IW_TXPOW_DBM;
+		orinoco_ioctl_gettxpower(dev, NULL, &(wrq->u.txpower), NULL);
 		break;

 #if WIRELESS_EXT > 10
@@ -3651,49 +4525,62 @@
 		break;

 	case SIOCGIWRETRY:
-		err = orinoco_ioctl_getretry(dev, &wrq->u.retry);
+		err = orinoco_ioctl_getretry(dev, NULL, &(wrq->u.retry), NULL);
 		break;
 #endif /* WIRELESS_EXT > 10 */

 	case SIOCSIWSPY:
-		err = orinoco_ioctl_setspy(dev, &wrq->u.data);
+		{
+			struct sockaddr address[IW_MAX_SPY];
+			/* Check the number of addresses */
+			if (wrq->u.data.length > IW_MAX_SPY) {
+				err = -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)) {
+					err = -EFAULT;
+					break;
+				}
+			} else if (wrq->u.data.length != 0) {
+				err = -EINVAL;
+				break;
+			}
+			err = orinoco_ioctl_setspy(dev, NULL, &(wrq->u.data),
+						   (char *) address);
+		}
 		break;

 	case SIOCGIWSPY:
-		err = orinoco_ioctl_getspy(dev, &wrq->u.data);
+		{
+			char buffer[IW_MAX_SPY * (sizeof(struct sockaddr) +
+						  sizeof(struct iw_quality))];
+			err = orinoco_ioctl_getspy(dev, NULL, &(wrq->u.data),
+						   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)))
+						 ))
+					err = -EFAULT;
+			}
+		}
 		break;

 	case SIOCGIWPRIV:
 		if (wrq->u.data.pointer) {
-			struct iw_priv_args privtab[] = {
-				{ SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" },
-				{ SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" },
-				{ SIOCIWFIRSTPRIV + 0x2,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  0, "set_port3" },
-				{ SIOCIWFIRSTPRIV + 0x3, 0,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  "get_port3" },
-				{ SIOCIWFIRSTPRIV + 0x4,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  0, "set_preamble" },
-				{ SIOCIWFIRSTPRIV + 0x5, 0,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  "get_preamble" },
-				{ SIOCIWFIRSTPRIV + 0x6,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  0, "set_ibssport" },
-				{ SIOCIWFIRSTPRIV + 0x7, 0,
-				  IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
-				  "get_ibssport" }
-			};
-
-			err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(privtab));
+			err = verify_area(VERIFY_WRITE, wrq->u.data.pointer, sizeof(orinoco_privtab));
 			if (err)
 				break;

-			wrq->u.data.length = sizeof(privtab) / sizeof(privtab[0]);
-			if (copy_to_user(wrq->u.data.pointer, privtab, sizeof(privtab)))
+			wrq->u.data.length = sizeof(orinoco_privtab) / sizeof(orinoco_privtab[0]);
+			if (copy_to_user(wrq->u.data.pointer, orinoco_privtab, sizeof(orinoco_privtab)))
 				err = -EFAULT;
 		}
 		break;
@@ -3704,7 +4591,7 @@
 			err = -EPERM;
 			break;
 		}
-
+
 		printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name);

 		schedule_task(&priv->timeout_task);
@@ -3716,13 +4603,13 @@
 			break;
 		}

-		err = orinoco_ioctl_setport3(dev, wrq);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setport3(dev, NULL, &(wrq->u),
+					     (char *) &(wrq->u));
 		break;

 	case SIOCIWFIRSTPRIV + 0x3: /* get_port3 */
-		err = orinoco_ioctl_getport3(dev, wrq);
+		err = orinoco_ioctl_getport3(dev, NULL, &(wrq->u),
+					     (char *) &(wrq->u));
 		break;

 	case SIOCIWFIRSTPRIV + 0x4: /* set_preamble */
@@ -3731,38 +4618,13 @@
 			break;
 		}

-		/* 802.11b has recently defined some short preamble.
-		 * Basically, the Phy header has been reduced in size.
-		 * This increase performance, especially at high rates
-		 * (the preamble is transmitted at 1Mb/s), unfortunately
-		 * this give compatibility troubles... - Jean II */
-		if(priv->has_preamble) {
-			int val = *( (int *) wrq->u.name );
-
-			err = orinoco_lock(priv, &flags);
-			if (err)
-				return err;
-			if (val)
-				priv->preamble = 1;
-			else
-				priv->preamble = 0;
-			orinoco_unlock(priv, &flags);
-			changed = 1;
-		} else
-			err = -EOPNOTSUPP;
+		err = orinoco_ioctl_setpreamble(dev, NULL, &(wrq->u),
+						(char *) &(wrq->u));
 		break;

 	case SIOCIWFIRSTPRIV + 0x5: /* get_preamble */
-		if(priv->has_preamble) {
-			int *val = (int *)wrq->u.name;
-
-			err = orinoco_lock(priv, &flags);
-			if (err)
-				return err;
-			*val = priv->preamble;
-			orinoco_unlock(priv, &flags);
-		} else
-			err = -EOPNOTSUPP;
+		err = orinoco_ioctl_getpreamble(dev, NULL, &(wrq->u),
+						(char *) &(wrq->u));
 		break;
 	case SIOCIWFIRSTPRIV + 0x6: /* set_ibssport */
 		if (! capable(CAP_NET_ADMIN)) {
@@ -3770,13 +4632,13 @@
 			break;
 		}

-		err = orinoco_ioctl_setibssport(dev, wrq);
-		if (! err)
-			changed = 1;
+		err = orinoco_ioctl_setibssport(dev, NULL, &(wrq->u),
+						(char *) &(wrq->u));
 		break;

 	case SIOCIWFIRSTPRIV + 0x7: /* get_ibssport */
-		err = orinoco_ioctl_getibssport(dev, wrq);
+		err = orinoco_ioctl_getibssport(dev, NULL, &(wrq->u),
+						(char *) &(wrq->u));
 		break;


@@ -3784,14 +4646,18 @@
 		err = -EOPNOTSUPP;
 	}

-	if (! err && changed && netif_running(dev)) {
-		err = orinoco_reconfigure(priv);
-	}
+	if (err == -EINPROGRESS) {
+		if(netif_running(dev))
+			err = orinoco_ioctl_commit(dev, rq, cmd, NULL);
+		else
+			err = 0;	/* Success */
+	}

 	TRACE_EXIT(dev->name);

 	return err;
 }
+#endif /* WIRELESS_EXT > 12 */

 /********************************************************************/
 /* procfs stuff                                                     */
@@ -3952,7 +4818,7 @@
 	PROC_REC(CHANNELLIST,WORDS),
 	PROC_REC(REGULATORYDOMAINS,WORDS),
 	PROC_REC(TEMPTYPE,WORDS),
-/*  	PROC_REC(CIS,BYTES), */
+	/*  	PROC_REC(CIS,BYTES), */
 	PROC_REC(STAID,WORDS),
 	PROC_REC(CURRENTSSID,STRING),
 	PROC_REC(CURRENTBSSID,BYTES),
@@ -3983,7 +4849,7 @@

 static int
 orinoco_proc_get_hermes_recs(char *page, char **start, off_t requested_offset,
-			   int requested_len, int *eof, void *data)
+			     int requested_len, int *eof, void *data)
 {
 	struct orinoco_private *priv = (struct orinoco_private *)data;
 	struct net_device *dev = priv->ndev;
@@ -4095,7 +4961,7 @@

 static int
 orinoco_proc_get_hermes_prof(char *page, char **start, off_t requested_offset,
-			    int requested_len, int *eof, void *data)
+			     int requested_len, int *eof, void *data)
 {
 	struct orinoco_private *priv = (struct orinoco_private *)data;
 	hermes_t *hw = &priv->hw;
@@ -4155,7 +5021,7 @@
 	}

 	e = create_proc_read_entry("recs", S_IFREG | S_IRUGO,
-			       priv->dir_dev, orinoco_proc_get_hermes_recs, priv);
+				   priv->dir_dev, orinoco_proc_get_hermes_recs, priv);
 	if (! e) {
 		printk(KERN_ERR "Unable to initialize /proc/hermes/%s/recs\n",  dev->name);
 		goto fail;
@@ -4163,14 +5029,14 @@

 #ifdef HERMES_DEBUG_BUFFER
 	e = create_proc_read_entry("buf", S_IFREG | S_IRUGO,
-					       priv->dir_dev, orinoco_proc_get_hermes_buf, priv);
+				   priv->dir_dev, orinoco_proc_get_hermes_buf, priv);
 	if (! e) {
 		printk(KERN_ERR "Unable to intialize /proc/hermes/%s/buf\n", dev->name);
 		goto fail;
 	}

 	e = create_proc_read_entry("prof", S_IFREG | S_IRUGO,
-					       priv->dir_dev, orinoco_proc_get_hermes_prof, priv);
+				   priv->dir_dev, orinoco_proc_get_hermes_prof, priv);
 	if (! e) {
 		printk(KERN_ERR "Unable to intialize /proc/hermes/%s/prof\n", dev->name);
 		goto fail;
@@ -4187,7 +5053,22 @@
 orinoco_proc_dev_cleanup(struct net_device *dev)
 {
 	struct orinoco_private *priv = dev->priv;
+	int err = 0;
+	unsigned long flags;

+	/* This seems to be the only function called when the driver exits,
+	 * so add my extra cleanup here - Jean II
+	 * On lock error, if you clean up someone might dereference NULL, but
+	 * if you don't, you have a memory leak.  FIXME.  */
+	err = orinoco_lock(priv, &flags);
+	if (!err && priv->scan_result != NULL) {
+		DEBUG(1, "%s: scan KFREE %p\n", dev->name, priv->scan_result);
+		priv->scan_inprogress = 0;
+		kfree(priv->scan_result);
+		priv->scan_result = NULL;
+	}
+	orinoco_unlock(priv, &flags);
+
 	if (priv->dir_dev) {
 		remove_proc_entry("prof", priv->dir_dev);
 		remove_proc_entry("buf", priv->dir_dev);
@@ -4226,7 +5107,13 @@
 	dev->watchdog_timeo = HZ; /* 1 second timeout */
 	dev->get_stats = orinoco_get_stats;
 	dev->get_wireless_stats = orinoco_get_wireless_stats;
+
+#if WIRELESS_EXT > 12
+	dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def;
+#else /* WIRELESS_EXT > 12 */
 	dev->do_ioctl = orinoco_ioctl;
+#endif /* WIRELESS_EXT > 12 */
+
 	dev->change_mtu = orinoco_change_mtu;
 	dev->set_multicast_list = orinoco_set_multicast_list;

@@ -4277,3 +5164,5 @@

 module_init(init_orinoco);
 module_exit(exit_orinoco);
+
+
diff -r -u orinoco-0.13a.orig/orinoco.h orinoco-0.13a/orinoco.h
--- orinoco-0.13a.orig/orinoco.h	2002-10-02 17:39:49.000000000 -0700
+++ orinoco-0.13a/orinoco.h	2002-12-13 20:14:10.000000000 -0800
@@ -92,6 +92,13 @@
 	int port_type, createibss;
 	int promiscuous, mc_count;

+	/* Scanning support */
+	int	scan_inprogress;	/* Scan pending... */
+	__u32	scan_mode;		/* Type of scan done */
+	char *	scan_result;		/* Result of previous scan */
+	int	scan_len;		/* Lenght of result */
+	/* More to come related to monitor mode */
+
 	/* /proc based debugging stuff */
 	struct proc_dir_entry *dir_dev;
 };
@@ -112,6 +119,13 @@
 extern int __orinoco_down(struct net_device *dev);
 int orinoco_reinit_firmware(struct net_device *dev);

+#if WIRELESS_EXT <= 12
+extern int orinoco_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+#endif /* WIRELESS_EXT <= 12 */
+
+/* utility routines */
+/* extern void orinoco_shutdown(struct net_device *dev); seems to be gone */
+extern int orinoco_reset(struct net_device *dev);
 extern int orinoco_proc_dev_init(struct net_device *dev);
 extern void orinoco_proc_dev_cleanup(struct net_device *dev);
 extern void orinoco_interrupt(int irq, void * dev_id, struct pt_regs *regs);
