Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 1387

kernel-2.6.18-194.11.1.el5.src.rpm

diff -Nur -p linux-2.6-orig/drivers/net/wireless/Kconfig linux-2.6-libertas/drivers/net/wireless/Kconfig
--- linux-2.6-orig/drivers/net/wireless/Kconfig	2006-08-06 15:20:11.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/Kconfig	2006-08-22 01:37:03.000000000 -0300
@@ -291,6 +291,19 @@ config IPW2200_DEBUG
 	  If you are not trying to debug or develop the IPW2200 driver, you 
 	  most likely want to say N here.
 
+config LIBERTAS_USB
+	tristate "Marvell Libertas 802.11a/b/g cards"
+	depends on NET_RADIO && USB
+	select FW_LOADER
+	---help---
+	  A driver for Marvel Libertas USB devices.
+
+config LIBERTAS_USB_DEBUG
+	bool "Enable full debugging output in the Libertas USB module."
+	depends on LIBERTAS_USB
+	---help---
+	  Debugging support.
+
 config AIRO
 	tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards"
  	depends on NET_RADIO && ISA_DMA_API && (PCI || BROKEN)
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/config/hostcmd.conf linux-2.6-libertas/drivers/net/wireless/libertas/config/hostcmd.conf
--- linux-2.6-orig/drivers/net/wireless/libertas/config/hostcmd.conf	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/config/hostcmd.conf	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,75 @@
+#	File : hostcmd.conf
+#
+# (c) Copyright © 2003-2006, Marvell International Ltd. 
+# All Rights Reserved
+#
+# This software file (the "File") is distributed by Marvell International 
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+# (the "License").  You may use, redistribute and/or modify this File in 
+# accordance with the terms and conditions of the License, a copy of which 
+# is available along with the File in the license.txt file or by writing to 
+# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+# 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+# this warranty disclaimer.
+#
+
+
+######################### Subscribe Events command ##################
+subevent_get={
+	CmdCode=0x0075		# do NOT change this line
+
+	Action:2=0		# GET
+	Events:2=0
+}
+
+subevent_set={
+	CmdCode=0x0075		# do NOT change this line
+
+	Action:2=1		# SET
+	Events:2=0x3f		# bit0 - RSSI_LOW; bit1 - SNR_LOW
+				# bit2 - FAILED_COUNT; bit3 - Beacon Missed
+				# bit4 - RSSI_HIGH; bit5 - SNR_HIGH
+				# bit6-15 reserved
+
+	LowRssiTlvType:2=0x0104
+	LowRssiTlvLength:2={
+		Threshold:1=40
+		ReportingFreq:1=0
+	}
+
+	LowSnrTlvType:2=0x0105
+	LowSnrTlvLength:2={
+		Threshold:1=56
+		ReportingFreq:1=0
+	}
+
+	FailedCountTlvType:2=0x0106
+	FailedCountTlvLength:2={
+		Threshold:1=5
+		ReportingFreq:1=0
+	}
+
+	BeaconMissTlvType:2=0x0107
+	BeaconMissTlvLength:2={
+		BeaconMissed:1=60
+		Reserved:1=0
+	}
+
+	HighRssiTlvType:2=0x0116
+	HighRssiTlvLength:2={
+		Threshold:1=70
+		ReportingFreq:1=0
+	}
+
+	HighSnrTlvType:2=0x0117
+	HighSnrTlvLength:2={
+		Threshold:1=86
+		ReportingFreq:1=0
+	}
+}
+######################### Subscribe Events command ##################
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/hostcmd.h linux-2.6-libertas/drivers/net/wireless/libertas/hostcmd.h
--- linux-2.6-orig/drivers/net/wireless/libertas/hostcmd.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/hostcmd.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,965 @@
+/* @file hostcmd.h
+ * 
+ * @brief This file contains the function prototypes, data structure 
+ * and defines for all the host/station commands
+ *
+ * (c) Copyright © 2003-2006, Marvell International Ltd. 
+ * All Rights Reserved
+ *
+ * This software file (the "File") is distributed by Marvell International 
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+ * (the "License").  You may use, redistribute and/or modify this File in 
+ * accordance with the terms and conditions of the License, a copy of which 
+ * is available along with the File in the license.txt file or by writing to 
+ * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+ * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+ * this warranty disclaimer.
+ *
+ */
+/********************************************************
+Change log:
+	10/11/05: Add Doxygen format comments
+	01/11/06: Update association struct to reflect IEEE passthrough response
+		  Conditionalize new scan/join structures
+	04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+	
+********************************************************/
+
+#ifndef __HOSTCMD__H
+#define __HOSTCMD__H
+
+#include "wlan_11d.h"
+#include "wlan_types.h"
+
+/* 802.11-related definitions */
+
+/* TxPD descriptor */
+struct TxPD {
+	/* Current Tx packet status */
+	u32 TxStatus;
+	/* Tx Control */
+	u32 TxControl;
+	u32 TxPacketLocation;
+	/* Tx packet length */
+	u16 TxPacketLength;
+	/* First 2 byte of destination MAC address */
+	u8 TxDestAddrHigh[2];
+	/* Last 4 byte of destination MAC address */
+	u8 TxDestAddrLow[4];
+	/* Pkt Priority */
+	u8 Priority;
+	/* Pkt Trasnit Power control */
+	u8 PowerMgmt;
+	/* Amount of time the packet has been queued in the driver (units = 2ms) */
+	u8 PktDelay_2ms;
+	/* Reserved */
+	u8 Reserved1;
+};
+
+/* RxPD Descriptor */
+struct RxPD {
+	/* Current Rx packet status */
+	u16 Status;
+
+	/* SNR */
+	u8 SNR;
+
+	/* Tx Control */
+	u8 RxControl;
+
+	/* Pkt Length */
+	u16 PktLen;
+
+	/* Noise Floor */
+	u8 NF;
+
+	/* Rx Packet Rate */
+	u8 RxRate;
+
+	/* Pkt addr */
+	u32 PktPtr;
+
+	/* Next Rx RxPD addr */
+	u32 NextRxPDPtr;
+
+	/* Pkt Priority */
+	u8 Priority;
+	u8 Reserved[3];
+};
+
+#if defined(__KERNEL__)
+
+/* CmdCtrlNode */
+struct CmdCtrlNode {
+	/* CMD link list */
+	struct list_head list;
+
+	u32 Status;
+
+	/* CMD ID */
+	u32 cmd_oid;
+
+	/*CMD wait option: wait for finish or no wait */
+	u16 wait_option;
+
+	/* command parameter */
+	void *pdata_buf;
+
+	/*command data */
+	u8 *BufVirtualAddr;
+
+	u16 CmdFlags;
+
+	/* wait queue */
+	u16 CmdWaitQWoken;
+	wait_queue_head_t cmdwait_q;
+} __attribute__ ((packed));
+
+#endif
+
+/* MRVL_WEP_KEY */
+struct MRVL_WEP_KEY {
+	u32 Length;
+	u32 KeyIndex;
+	u32 KeyLength;
+	u8 KeyMaterial[MRVL_KEY_BUFFER_SIZE_IN_BYTE];
+};
+
+/* WLAN_802_11_KEY */
+struct WLAN_802_11_KEY {
+	u32 Length;
+	u32 KeyIndex;
+	u32 KeyLength;
+	u8 BSSID[ETH_ALEN];
+	unsigned long long KeyRSC;
+	u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH];
+} __attribute__ ((packed));
+
+/* MRVL_WPA_KEY */
+struct MRVL_WPA_KEY {
+	u32 KeyIndex;
+	u32 KeyLength;
+	u32 KeyRSC;
+	u8 KeyMaterial[MRVL_MAX_KEY_WPA_KEY_LENGTH];
+};
+
+/* MRVL_WLAN_WPA_KEY */
+#if 0
+// unused at the moment
+struct MRVL_WLAN_WPA_KEY {
+	u8 EncryptionKey[16];
+	u8 MICKey1[8];
+	u8 MICKey2[8];
+};
+#endif
+
+/* IE_WPA */
+struct IE_WPA {
+	u8 Elementid;
+	u8 Len;
+	u8 oui[4];
+	u16 version;
+};
+
+/* WLAN_802_11_WEP */
+#if 0
+// unused at the moment
+struct WLAN_802_11_WEP {
+	/* Length of this structure */
+	u32 Length;
+
+	/* 0 is the per-client key, 1-N are the global keys */
+	u32 KeyIndex;
+
+	/* length of key in bytes */
+	u32 KeyLength;
+
+	/* variable length depending on above field */
+	u8 KeyMaterial[1];
+} __attribute__ ((packed));
+#endif
+
+/* WLAN_802_11_SSID */
+struct WLAN_802_11_SSID {
+	/* SSID Length */
+	u32 SsidLength;
+
+	/* SSID information field */
+	u8 Ssid[WLAN_MAX_SSID_LENGTH];
+};
+
+struct WPA_SUPPLICANT {
+	u8 Wpa_ie[256];
+	u8 Wpa_ie_len;
+};
+
+/* wlan_offset_value */
+struct wlan_offset_value {
+	u32 offset;
+	u32 value;
+};
+
+/* WLAN_802_11_FIXED_IEs */
+struct WLAN_802_11_FIXED_IEs {
+	u8 Timestamp[8];
+	u16 BeaconInterval;
+	u16 Capabilities;
+};
+
+/* WLAN_802_11_VARIABLE_IEs */
+struct WLAN_802_11_VARIABLE_IEs {
+	u8 ElementID;
+	u8 Length;
+	u8 data[1];
+};
+
+/* WLAN_802_11_AI_RESFI */
+struct WLAN_802_11_AI_RESFI {
+	u16 Capabilities;
+	u16 StatusCode;
+	u16 AssociationId;
+};
+
+/* WLAN_802_11_AI_REQFI */
+struct WLAN_802_11_AI_REQFI {
+	u16 Capabilities;
+	u16 ListenInterval;
+	u8 CurrentAPAddress[ETH_ALEN];
+};
+
+/* Define general data structure */
+/* HostCmd_DS_GEN */
+struct HostCmd_DS_GEN {
+	u16 Command;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+};
+
+#define S_DS_GEN sizeof(struct HostCmd_DS_GEN)
+/*
+ * Define data structure for HostCmd_CMD_GET_HW_SPEC
+ * This structure defines the response for the GET_HW_SPEC command
+ */
+/* HostCmd_DS_GET_HW_SPEC */
+struct HostCmd_DS_GET_HW_SPEC {
+	/* HW Interface version number */
+	u16 HWIfVersion;
+
+	/* HW version number */
+	u16 Version;
+
+	/* Max number of TxPD FW can handle */
+	u16 NumOfTxPD;
+
+	/* Max no of Multicast address */
+	u16 NumOfMCastAdr;
+
+	/* MAC address */
+	u8 PermanentAddr[6];
+
+	/* Region Code */
+	u16 RegionCode;
+
+	/* Number of antenna used */
+	u16 NumberOfAntenna;
+
+	/* FW release number, example 0x1234=1.2.3.4 */
+	u32 FWReleaseNumber;
+
+	/* Base Address of TxPD queue */
+	u32 WcbBase;
+	/* Read Pointer of RxPd queue */
+	u32 RxPdRdPtr;
+
+	/* Write Pointer of RxPd queue */
+	u32 RxPdWrPtr;
+
+	/*FW/HW Capability */
+	u32 fwCapInfo;
+} __attribute__ ((packed));
+
+/* HostCmd_CMD_EEPROM_UPDATE */
+struct HostCmd_DS_EEPROM_UPDATE {
+	u16 Action;
+	u32 Value;
+} __attribute__ ((packed));
+
+/* HostCmd_CMD_802_11_RESET */
+struct HostCmd_DS_802_11_RESET {
+	u16 Action;
+};
+
+struct HostCmd_DS_802_11_SUBSCRIBE_EVENT {
+	u16 Action;
+	u16 Events;
+};
+
+/* 
+ * This scan handle Country Information IE(802.11d compliant) 
+ * Define data structure for HostCmd_CMD_802_11_SCAN 
+ */
+/* HostCmd_DS_802_11_SCAN */
+struct HostCmd_DS_802_11_SCAN {
+	u8 BSSType;
+	u8 BSSID[ETH_ALEN];
+	u8 TlvBuffer[1];
+#if 0
+	MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
+	MrvlIEtypes_ChanListParamSet_t ChanListParamSet;
+	MrvlIEtypes_RatesParamSet_t OpRateSet;
+#endif
+};
+
+struct HostCmd_DS_802_11_SCAN_RSP {
+	u16 BSSDescriptSize;
+	u8 NumberOfSets;
+	u8 BssDescAndTlvBuffer[1];
+};
+
+/* HostCmd_CMD_802_11_GET_LOG */
+struct HostCmd_DS_802_11_GET_LOG {
+	u32 mcasttxframe;
+	u32 failed;
+	u32 retry;
+	u32 multiretry;
+	u32 framedup;
+	u32 rtssuccess;
+	u32 rtsfailure;
+	u32 ackfailure;
+	u32 rxfrag;
+	u32 mcastrxframe;
+	u32 fcserror;
+	u32 txframe;
+	u32 wepundecryptable;
+};
+
+/* HostCmd_CMD_MAC_CONTROL */
+struct HostCmd_DS_MAC_CONTROL {
+	u16 Action;
+	u16 Reserved;
+};
+
+/* HostCmd_CMD_MAC_MULTICAST_ADR */
+struct HostCmd_DS_MAC_MULTICAST_ADR {
+	u16 Action;
+	u16 NumOfAdrs;
+	u8 MACList[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE];
+};
+
+/* HostCmd_CMD_802_11_AUTHENTICATE */
+struct HostCmd_DS_802_11_AUTHENTICATE {
+	u8 MacAddr[ETH_ALEN];
+	u8 AuthType;
+	u8 Reserved[10];
+};
+
+/* HostCmd_RET_802_11_AUTHENTICATE */
+struct HostCmd_DS_802_11_AUTHENTICATE_RSP {
+	u8 MacAddr[6];
+	u8 AuthType;
+	u8 AuthStatus;
+};
+
+/* HostCmd_CMD_802_11_DEAUTHENTICATE */
+struct HostCmd_DS_802_11_DEAUTHENTICATE {
+	u8 MacAddr[6];
+	u16 ReasonCode;
+};
+
+/* HostCmd_DS_802_11_ASSOCIATE */
+struct HostCmd_DS_802_11_ASSOCIATE {
+	u8 PeerStaAddr[6];
+	struct IEEEtypes_CapInfo CapInfo;
+	u16 ListenInterval;
+	u16 BcnPeriod;
+	u8 DtimPeriod;
+
+#if 0
+	MrvlIEtypes_SsIdParamSet_t SsIdParamSet;
+	MrvlIEtypes_PhyParamSet_t PhyParamSet;
+	MrvlIEtypes_SsParamSet_t SsParamSet;
+	MrvlIEtypes_RatesParamSet_t RatesParamSet;
+#endif
+} __attribute__ ((packed));
+
+/* HostCmd_CMD_802_11_DISASSOCIATE */
+struct HostCmd_DS_802_11_DISASSOCIATE {
+	u8 DestMacAddr[6];
+	u16 ReasonCode;
+};
+
+/* HostCmd_RET_802_11_ASSOCIATE */
+struct HostCmd_DS_802_11_ASSOCIATE_RSP {
+	struct IEEEtypes_AssocRsp assocRsp;
+} __attribute__ ((packed));
+
+/* HostCmd_RET_802_11_AD_HOC_JOIN */
+struct HostCmd_DS_802_11_AD_HOC_RESULT {
+	u8 PAD[3];
+	u8 BSSID[ETH_ALEN];
+};
+
+/* HostCmd_CMD_802_11_SET_WEP */
+struct HostCmd_DS_802_11_SET_WEP {
+	/* ACT_ADD, ACT_REMOVE or ACT_ENABLE */
+	u16 Action;
+
+	/* Key Index selected for Tx */
+	u16 KeyIndex;
+
+	/* 40, 128bit or TXWEP */
+	u8 WEPTypeForKey1;
+
+	u8 WEPTypeForKey2;
+	u8 WEPTypeForKey3;
+	u8 WEPTypeForKey4;
+	u8 WEP1[16];
+	u8 WEP2[16];
+	u8 WEP3[16];
+	u8 WEP4[16];
+};
+
+/* HostCmd_CMD_802_3_GET_STAT */
+struct HostCmd_DS_802_3_GET_STAT {
+	u32 XmitOK;
+	u32 RcvOK;
+	u32 XmitError;
+	u32 RcvError;
+	u32 RcvNoBuffer;
+	u32 RcvCRCError;
+};
+
+/* HostCmd_CMD_802_11_GET_STAT */
+struct HostCmd_DS_802_11_GET_STAT {
+	u32 TXFragmentCnt;
+	u32 MCastTXFrameCnt;
+	u32 FailedCnt;
+	u32 RetryCnt;
+	u32 MultipleRetryCnt;
+	u32 RTSSuccessCnt;
+	u32 RTSFailureCnt;
+	u32 ACKFailureCnt;
+	u32 FrameDuplicateCnt;
+	u32 RXFragmentCnt;
+	u32 MCastRXFrameCnt;
+	u32 FCSErrorCnt;
+	u32 BCastTXFrameCnt;
+	u32 BCastRXFrameCnt;
+	u32 TXBeacon;
+	u32 RXBeacon;
+	u32 WEPUndecryptable;
+};
+
+/* HostCmd_DS_802_11_AD_HOC_STOP */
+/* wtf?  -- pjones */
+struct HostCmd_DS_802_11_AD_HOC_STOP {
+
+};
+
+/* HostCmd_DS_802_11_BEACON_STOP */
+/* wtf?  -- pjones */
+struct HostCmd_DS_802_11_BEACON_STOP {
+
+};
+
+/* HostCmd_CMD_802_11_SNMP_MIB */
+struct HostCmd_DS_802_11_SNMP_MIB {
+	u16 QueryType;
+	u16 OID;
+	u16 BufSize;
+	u8 Value[128];
+};
+
+/* HostCmd_CMD_MAC_REG_MAP */
+struct HostCmd_DS_MAC_REG_MAP {
+	u16 BufferSize;
+	u8 RegMap[128];
+	u16 Reserved;
+};
+
+/* HostCmd_CMD_BBP_REG_MAP */
+struct HostCmd_DS_BBP_REG_MAP {
+	u16 BufferSize;
+	u8 RegMap[128];
+	u16 Reserved;
+};
+
+/* HostCmd_CMD_RF_REG_MAP */
+struct HostCmd_DS_RF_REG_MAP {
+	u16 BufferSize;
+	u8 RegMap[64];
+	u16 Reserved;
+};
+
+/* HostCmd_CMD_MAC_REG_ACCESS */
+struct HostCmd_DS_MAC_REG_ACCESS {
+	u16 Action;
+	u16 Offset;
+	u32 Value;
+};
+
+/* HostCmd_CMD_BBP_REG_ACCESS */
+struct HostCmd_DS_BBP_REG_ACCESS {
+	u16 Action;
+	u16 Offset;
+	u8 Value;
+	u8 Reserved[3];
+};
+
+/* HostCmd_CMD_RF_REG_ACCESS */
+struct HostCmd_DS_RF_REG_ACCESS {
+	u16 Action;
+	u16 Offset;
+	u8 Value;
+	u8 Reserved[3];
+};
+
+/* HostCmd_CMD_802_11_RADIO_CONTROL */
+struct HostCmd_DS_802_11_RADIO_CONTROL {
+	u16 Action;
+	u16 Control;
+};
+
+/* HostCmd_DS_802_11_SLEEP_PARAMS */
+struct HostCmd_DS_802_11_SLEEP_PARAMS {
+	/* ACT_GET/ACT_SET */
+	u16 Action;
+
+	/* Sleep clock error in ppm */
+	u16 Error;
+
+	/* Wakeup offset in usec */
+	u16 Offset;
+
+	/* Clock stabilization time in usec */
+	u16 StableTime;
+
+	/* Control periodic calibration */
+	u8 CalControl;
+
+	/* Control the use of external sleep clock */
+	u8 ExternalSleepClk;
+
+	/* Reserved field, should be set to zero */
+	u16 Reserved;
+};
+
+/* HostCmd_DS_802_11_SLEEP_PERIOD */
+struct HostCmd_DS_802_11_SLEEP_PERIOD {
+	/* ACT_GET/ACT_SET */
+	u16 Action;
+
+	/* Sleep Period in msec */
+	u16 Period;
+};
+
+/* HostCmd_DS_802_11_INACTIVITY_TIMEOUT */
+struct HostCmd_DS_802_11_INACTIVITY_TIMEOUT {
+	/* ACT_GET/ACT_SET */
+	u16 Action;
+
+	/* Inactivity timeout in msec */
+	u16 Timeout;
+};
+
+/* HostCmd_CMD_802_11_RF_CHANNEL */
+struct HostCmd_DS_802_11_RF_CHANNEL {
+	u16 Action;
+	u16 CurrentChannel;
+	u16 RFType;
+	u16 Reserved;
+	u8 ChannelList[32];
+};
+
+/* HostCmd_CMD_802_11_RSSI */
+struct HostCmd_DS_802_11_RSSI {
+	/* weighting factor */
+	u16 N;
+
+	u16 Reserved_0;
+	u16 Reserved_1;
+	u16 Reserved_2;
+};
+
+/* HostCmd_DS_802_11_RSSI_RSP */
+struct HostCmd_DS_802_11_RSSI_RSP {
+	u16 SNR;
+	u16 NoiseFloor;
+	u16 AvgSNR;
+	u16 AvgNoiseFloor;
+};
+
+/* HostCmd_DS_802_11_MAC_ADDRESS */
+struct HostCmd_DS_802_11_MAC_ADDRESS {
+	u16 Action;
+	u8 MacAdd[ETH_ALEN];
+};
+
+/* HostCmd_CMD_802_11_RF_TX_POWER */
+struct HostCmd_DS_802_11_RF_TX_POWER {
+	u16 Action;
+	u16 CurrentLevel;
+};
+
+/* HostCmd_CMD_802_11_RF_ANTENNA */
+struct HostCmd_DS_802_11_RF_ANTENNA {
+	u16 Action;
+
+	/* Number of antennas or 0xffff(diversity) */
+	u16 AntennaMode;
+
+};
+
+/* HostCmd_CMD_802_11_PS_MODE */
+struct HostCmd_DS_802_11_PS_MODE {
+	u16 Action;
+	u16 NullPktInterval;
+	u16 MultipleDtim;
+	u16 Reserved;
+	u16 LocalListenInterval;
+};
+
+/* PS_CMD_ConfirmSleep */
+struct PS_CMD_ConfirmSleep {
+	u16 Command;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+
+	u16 Action;
+	u16 Reserved1;
+	u16 MultipleDtim;
+	u16 Reserved;
+	u16 LocalListenInterval;
+};
+
+/* HostCmd_CMD_802_11_DATA_RATE */
+struct HostCmd_DS_802_11_DATA_RATE {
+	u16 Action;
+	u16 Reserverd;
+	u8 DataRate[HOSTCMD_SUPPORTED_RATES];
+};
+
+/* HostCmd_DS_802_11_RATE_ADAPT_RATESET */
+struct HostCmd_DS_802_11_RATE_ADAPT_RATESET {
+	u16 Action;
+	u16 EnableHwAuto;
+	u16 Bitmap;
+};
+
+/* HostCmd_DS_802_11_AD_HOC_START*/
+struct HostCmd_DS_802_11_AD_HOC_START {
+	u8 SSID[MRVDRV_MAX_SSID_LENGTH];
+	u8 BSSType;
+	u16 BeaconPeriod;
+	u8 DTIMPeriod;
+	union IEEEtypes_SsParamSet SsParamSet;
+	union IEEEtypes_PhyParamSet PhyParamSet;
+	u16 ProbeDelay;
+	struct IEEEtypes_CapInfo Cap;
+	u8 DataRate[HOSTCMD_SUPPORTED_RATES];
+	u8 tlv_memory_size_pad[100];
+} __attribute__ ((packed));
+
+/* AdHoc_BssDesc_t */
+struct AdHoc_BssDesc {
+	u8 BSSID[6];
+	u8 SSID[32];
+	u8 BSSType;
+	u16 BeaconPeriod;
+	u8 DTIMPeriod;
+	u8 TimeStamp[8];
+	u8 LocalTime[8];
+	union IEEEtypes_PhyParamSet PhyParamSet;
+	union IEEEtypes_SsParamSet SsParamSet;
+	struct IEEEtypes_CapInfo Cap;
+	u8 DataRates[HOSTCMD_SUPPORTED_RATES];
+
+	/* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the
+	 * Adhoc join command and will cause a binary layout mismatch with 
+	 * the firmware 
+	 */
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_AD_HOC_JOIN */
+struct HostCmd_DS_802_11_AD_HOC_JOIN {
+	struct AdHoc_BssDesc BssDescriptor;
+	u16 FailTimeOut;
+	u16 ProbeDelay;
+
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_ENABLE_RSN */
+struct HostCmd_DS_802_11_ENABLE_RSN {
+	u16 Action;
+	u16 Enable;
+};
+
+/* HostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS */
+struct HostCmd_DS_802_11_QUERY_TKIP_REPLY_CNTRS {
+	u16 CmdCode;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+	u32 NumTkipCntrs;
+};
+
+/* HostCmd_DS_802_11_PAIRWISE_TSC */
+struct HostCmd_DS_802_11_PAIRWISE_TSC {
+	u16 CmdCode;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+	u16 Action;
+	u32 Txlv32;
+	u16 Txlv16;
+};
+
+/* HostCmd_DS_802_11_GROUP_TSC */
+struct HostCmd_DS_802_11_GROUP_TSC {
+	u16 CmdCode;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+	u16 Action;
+	u32 Txlv32;
+	u16 Txlv16;
+};
+
+#if 0
+union KeyInfo_WEP_t {
+	u8 Reserved;
+
+	/* bits 1-4: Specifies the index of key */
+	u8 WepKeyIndex;
+
+	/* bit 0: Specifies that this key is 
+	 * to be used as the default for TX data packets */
+	u8 isWepDefaultKey;
+};
+
+union KeyInfo_TKIP_t {
+	u8 Reserved;
+
+	/* bit 2: Specifies that this key is 
+	 * enabled and valid to use */
+	u8 isKeyEnabled;
+
+	/* bit 1: Specifies that this key is
+	 * to be used as the unicast key */
+	u8 isUnicastKey;
+
+	/* bit 0: Specifies that this key is 
+	 * to be used as the multicast key */
+	u8 isMulticastKey;
+};
+
+union KeyInfo_AES_t {
+	u8 Reserved;
+
+	/* bit 2: Specifies that this key is
+	 * enabled and valid to use */
+	u8 isKeyEnabled;
+
+	/* bit 1: Specifies that this key is
+	 * to be used as the unicast key */
+	u8 isUnicastKey;
+
+	/* bit 0: Specifies that this key is 
+	 * to be used as the multicast key */
+	u8 isMulticastKey;
+} KeyInfo_AES_t;
+
+/* KeyMaterial_TKIP_t */
+struct KeyMaterial_TKIP_t {
+	/* TKIP encryption/decryption key */
+	u8 TkipKey[16];
+
+	/* TKIP TX MIC Key */
+	u8 TkipTxMicKey[16];
+
+	/* TKIP RX MIC Key */
+	u8 TkipRxMicKey[16];
+};
+
+/* KeyMaterial_AES_t */
+struct KeyMaterial_AES_t {
+	/* AES encryption/decryption key */
+	u8 AesKey[16];
+};
+#endif
+
+/* MrvlIEtype_KeyParamSet_t */
+struct MrvlIEtype_KeyParamSet {
+	/* Type ID */
+	u16 Type;
+
+	/* Length of Payload */
+	u16 Length;
+
+	/* Type of Key: WEP=0, TKIP=1, AES=2 */
+	u16 KeyTypeId;
+
+	/* Key Control Info specific to a KeyTypeId */
+	u16 KeyInfo;
+
+	/* Length of key */
+	u16 KeyLen;
+
+	/* Key material of size KeyLen */
+	u8 Key[32];
+};
+
+/* HostCmd_DS_802_11_KEY_MATERIAL */
+struct HostCmd_DS_802_11_KEY_MATERIAL {
+	u16 Action;
+	struct MrvlIEtype_KeyParamSet KeyParamSet;
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_EEPROM_ACCESS */
+struct HostCmd_DS_802_11_EEPROM_ACCESS {
+	u16 Action;
+
+	/* multiple 4 */
+	u16 Offset;
+	u16 ByteCount;
+	u8 Value;
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_TPC_CFG */
+struct HostCmd_DS_802_11_TPC_CFG {
+	u16 Action;
+	u8 Enable;
+	s8 P0;
+	s8 P1;
+	s8 P2;
+	u8 UseSNR;
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_LED_CTRL */
+struct HostCmd_DS_802_11_LED_CTRL {
+	u16 Action;
+	u16 NumLed;
+	u8 data[256];
+} __attribute__ ((packed));
+
+/** HostCmd_DS_802_11_PWR_CFG */
+struct HostCmd_DS_802_11_PWR_CFG {
+	u16 Action;
+	u8 Enable;
+	s8 PA_P0;
+	s8 PA_P1;
+	s8 PA_P2;
+} __attribute__ ((packed));
+
+/* HostCmd_DS_802_11_AFC */
+struct HostCmd_DS_802_11_AFC {
+	u16 afc_auto;
+	union {
+		struct {
+			u16 threshold;
+			u16 period;
+		} auto_mode;
+		struct {
+			s16 timing_offset;
+			s16 carrier_offset;
+		} manual_mode;
+	} b;
+} __attribute__ ((packed));
+
+#define afc_data b.data
+#define afc_thre b.auto_mode.threshold
+#define afc_period b.auto_mode.period
+#define afc_toff b.manual_mode.timing_offset
+#define afc_foff b.manual_mode.carrier_offset
+
+struct HostCmd_TX_RATE_QUERY {
+	u16 TxRate;
+} __attribute__ ((packed));
+
+struct HostCmd_DS_GET_TSF {
+	u64 TsfValue;
+} __attribute__ ((packed));
+
+/* HostCmd_CMD_DFT_ACCESS */
+struct HostCmd_DS_DFT_ACCESS {
+	u16 action;
+	u32 id;
+	u8 addr1[ETH_ALEN];
+	u8 addr2[ETH_ALEN];
+} __attribute__ ((packed));
+
+/* HostCmd_DS_COMMAND */
+struct HostCmd_DS_COMMAND {
+	/* Command Header */
+	u16 Command;
+	u16 Size;
+	u16 SeqNum;
+	u16 Result;
+
+	/* Command Body */
+	union {
+		struct HostCmd_DS_GET_HW_SPEC hwspec;
+		struct HostCmd_DS_802_11_PS_MODE psmode;
+		struct HostCmd_DS_802_11_SCAN scan;
+		struct HostCmd_DS_802_11_SCAN_RSP scanresp;
+		struct HostCmd_DS_MAC_CONTROL macctrl;
+		struct HostCmd_DS_802_11_ASSOCIATE associate;
+		struct HostCmd_DS_802_11_ASSOCIATE_RSP associatersp;
+		struct HostCmd_DS_802_11_DEAUTHENTICATE deauth;
+		struct HostCmd_DS_802_11_SET_WEP wep;
+		struct HostCmd_DS_802_11_AD_HOC_START ads;
+		struct HostCmd_DS_802_11_RESET reset;
+		struct HostCmd_DS_802_11_AD_HOC_RESULT result;
+		struct HostCmd_DS_802_11_GET_LOG glog;
+		struct HostCmd_DS_802_11_AUTHENTICATE auth;
+		struct HostCmd_DS_802_11_AUTHENTICATE_RSP rauth;
+		struct HostCmd_DS_802_11_GET_STAT gstat;
+		struct HostCmd_DS_802_3_GET_STAT gstat_8023;
+		struct HostCmd_DS_802_11_SNMP_MIB smib;
+		struct HostCmd_DS_802_11_RF_TX_POWER txp;
+		struct HostCmd_DS_802_11_RF_ANTENNA rant;
+		struct HostCmd_DS_802_11_DATA_RATE drate;
+		struct HostCmd_DS_802_11_RATE_ADAPT_RATESET rateset;
+		struct HostCmd_DS_MAC_MULTICAST_ADR madr;
+		struct HostCmd_DS_802_11_AD_HOC_JOIN adj;
+		struct HostCmd_DS_802_11_RADIO_CONTROL radio;
+		struct HostCmd_DS_802_11_RF_CHANNEL rfchannel;
+		struct HostCmd_DS_802_11_RSSI rssi;
+		struct HostCmd_DS_802_11_RSSI_RSP rssirsp;
+		struct HostCmd_DS_802_11_DISASSOCIATE dassociate;
+		struct HostCmd_DS_802_11_AD_HOC_STOP adhoc_stop;
+		struct HostCmd_DS_802_11_MAC_ADDRESS macadd;
+		struct HostCmd_DS_802_11_ENABLE_RSN enbrsn;
+		struct HostCmd_DS_802_11_KEY_MATERIAL keymaterial;
+		struct HostCmd_DS_MAC_REG_ACCESS macreg;
+		struct HostCmd_DS_BBP_REG_ACCESS bbpreg;
+		struct HostCmd_DS_RF_REG_ACCESS rfreg;
+		struct HostCmd_DS_802_11_BEACON_STOP beacon_stop;
+		struct HostCmd_DS_802_11_EEPROM_ACCESS rdeeprom;
+
+		struct HostCmd_DS_802_11D_DOMAIN_INFO domaininfo;
+		struct HostCmd_DS_802_11D_DOMAIN_INFO_RSP domaininforesp;
+
+		struct HostCmd_DS_802_11_SLEEP_PARAMS sleep_params;
+		struct HostCmd_DS_802_11_INACTIVITY_TIMEOUT inactivity_timeout;
+		struct HostCmd_DS_802_11_SLEEP_PERIOD ps_sleeppd;
+		struct HostCmd_DS_802_11_TPC_CFG tpccfg;
+		struct HostCmd_DS_802_11_PWR_CFG pwrcfg;
+		struct HostCmd_DS_802_11_AFC afc;
+		struct HostCmd_DS_802_11_LED_CTRL ledgpio;
+
+		struct HostCmd_TX_RATE_QUERY txrate;
+		struct HostCmd_DS_DFT_ACCESS dft;
+		struct HostCmd_DS_GET_TSF gettsf;
+	} params;
+} __attribute__ ((packed));
+
+#endif
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/host.h linux-2.6-libertas/drivers/net/wireless/libertas/host.h
--- linux-2.6-orig/drivers/net/wireless/libertas/host.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/host.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,460 @@
+/** @file host.h
+  *
+  * @brief This file contains definitions of WLAN commands.
+  *  
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+    10/11/05: Add Doxygen format comments
+    01/11/06: Remove assoc response codes; full IEEE assoc resp now returned
+    04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+    04/10/06: Add power_adapt_cfg_ext command
+    04/18/06: Remove old Subscrive Event and add new Subscribe Event
+	      implementation through generic hostcmd API
+********************************************************/
+
+#ifndef _HOST_H_
+#define _HOST_H_
+
+/** PUBLIC DEFINITIONS */
+#define DEFAULT_CHANNEL              1
+#define DEFAULT_CHANNEL_A           36
+#define DEFAULT_AD_HOC_CHANNEL       6
+#define DEFAULT_AD_HOC_CHANNEL_A    36
+
+/** IEEE 802.11 OIDs */
+#define OID_802_11_BSSID                      0x00008001
+#define OID_802_11_SSID                       0x00008002
+#define OID_802_11_NETWORK_TYPES_SUPPORTED    0x00008003
+#define OID_802_11_NETWORK_TYPE_IN_USE        0x00008004
+#define OID_802_11_RSSI                       0x00008006
+#define OID_802_11_RSSI_TRIGGER               0x00008007
+#define OID_802_11_INFRASTRUCTURE_MODE        0x00008008
+#define OID_802_11_FRAGMENTATION_THRESHOLD    0x00008009
+#define OID_802_11_RTS_THRESHOLD              0x0000800A
+#define OID_802_11_NUMBER_OF_ANTENNAS         0x0000800B
+#define OID_802_11_RX_ANTENNA_SELECTED        0x0000800C
+#define OID_802_11_TX_ANTENNA_SELECTED        0x0000800D
+#define OID_802_11_SUPPORTED_RATES            0x0000800E
+#define OID_802_11_DESIRED_RATES              0x00008010
+#define OID_802_11_CONFIGURATION              0x00008011
+#define OID_802_11_STATISTICS                 0x00008012
+#define OID_802_11_ADD_WEP                    0x00008013
+#define OID_802_11_REMOVE_WEP                 0x00008014
+#define OID_802_11_DISASSOCIATE               0x00008015
+#define OID_802_11_POWER_MODE                 0x00008016
+#define OID_802_11_BSSID_LIST                 0x00008017
+#define OID_802_11_AUTHENTICATION_MODE        0x00008018
+#define OID_802_11_PRIVACY_FILTER             0x00008019
+#define OID_802_11_BSSID_LIST_SCAN            0x0000801A
+#define OID_802_11_WEP_STATUS                 0x0000801B
+#define OID_802_11_RELOAD_DEFAULTS            0x0000801C
+#define OID_802_11_TX_RETRYCOUNT              0x0000801D
+#define OID_802_11D_ENABLE                    0x00008020
+
+/** Marvel specific OIDs */
+#define OID_MRVL_OEM_GET_ULONG                0xff010201
+#define OID_MRVL_OEM_SET_ULONG                0xff010202
+#define OID_MRVL_OEM_GET_STRING               0xff010203
+#define OID_MRVL_OEM_COMMAND                  0xff010204
+
+/** Command Processing States and Options */
+#define HostCmd_STATE_IDLE                    0x0000
+#define HostCmd_STATE_IN_USE_BY_HOST          0x0001
+#define HostCmd_STATE_IN_USE_BY_MINIPORT      0x0002
+#define HostCmd_STATE_FINISHED                0x000f
+
+#define HostCmd_Q_NONE                        0x0000
+#define HostCmd_Q_INIT                        0x0001
+#define HostCmd_Q_RESET                       0x0002
+#define HostCmd_Q_STAT                        0x0003
+
+#define HostCmd_OPTION_WAITFORRSP             0x0002
+
+/*  512 usec */
+#define HostCmd_DELAY_NORMAL                  0x00000200
+/*  256 usec */
+#define HostCmd_DELAY_MIN                     0x00000100
+/* 1024 usec */
+#define HostCmd_DELAY_MAX                     0x00000400
+
+/** Host Command ID */
+#define HostCmd_CMD_NONE                      0x0000
+#define HostCmd_CMD_CODE_DNLD                 0x0002
+#define HostCmd_CMD_GET_HW_SPEC               0x0003
+#define HostCmd_CMD_EEPROM_UPDATE             0x0004
+#define HostCmd_CMD_802_11_RESET              0x0005
+#define HostCmd_CMD_802_11_SCAN               0x0006
+#define HostCmd_CMD_802_11_GET_LOG            0x000b
+#define HostCmd_CMD_MAC_MULTICAST_ADR         0x0010
+#define HostCmd_CMD_802_11_AUTHENTICATE       0x0011
+#define HostCmd_CMD_802_11_EEPROM_ACCESS      0x0059
+#define HostCmd_CMD_802_11_ASSOCIATE          0x0050
+#define HostCmd_CMD_802_11_SET_WEP            0x0013
+#define HostCmd_CMD_802_11_GET_STAT           0x0014
+#define HostCmd_CMD_802_3_GET_STAT            0x0015
+#define HostCmd_CMD_802_11_SNMP_MIB           0x0016
+#define HostCmd_CMD_MAC_REG_MAP               0x0017
+#define HostCmd_CMD_BBP_REG_MAP               0x0018
+#define HostCmd_CMD_MAC_REG_ACCESS            0x0019
+#define HostCmd_CMD_BBP_REG_ACCESS            0x001a
+#define HostCmd_CMD_RF_REG_ACCESS             0x001b
+#define HostCmd_CMD_802_11_RADIO_CONTROL      0x001c
+#define HostCmd_CMD_802_11_RF_CHANNEL         0x001d
+#define HostCmd_CMD_802_11_RF_TX_POWER        0x001e
+#define HostCmd_CMD_802_11_RSSI               0x001f
+#define HostCmd_CMD_802_11_RF_ANTENNA         0x0020
+
+#define HostCmd_CMD_802_11_PS_MODE	      0x0021
+
+#define HostCmd_CMD_802_11_DATA_RATE          0x0022
+#define HostCmd_CMD_RF_REG_MAP                0x0023
+#define HostCmd_CMD_802_11_DEAUTHENTICATE     0x0024
+#define HostCmd_CMD_802_11_REASSOCIATE        0x0025
+#define HostCmd_CMD_802_11_DISASSOCIATE       0x0026
+#define HostCmd_CMD_MAC_CONTROL               0x0028
+#define HostCmd_CMD_802_11_AD_HOC_START       0x002b
+#define HostCmd_CMD_802_11_AD_HOC_JOIN        0x002c
+
+#define HostCmd_CMD_802_11_QUERY_TKIP_REPLY_CNTRS  0x002e
+#define HostCmd_CMD_802_11_ENABLE_RSN              0x002f
+#define HostCmd_CMD_802_11_PAIRWISE_TSC       0x0036
+#define HostCmd_CMD_802_11_GROUP_TSC          0x0037
+#define HostCmd_CMD_802_11_KEY_MATERIAL       0x005e
+
+#define HostCmd_CMD_802_11_SET_AFC            0x003c
+#define HostCmd_CMD_802_11_GET_AFC            0x003d
+
+#define HostCmd_CMD_802_11_AD_HOC_STOP        0x0040
+
+#define HostCmd_CMD_802_11_BEACON_STOP        0x0049
+
+#define HostCmd_CMD_802_11_MAC_ADDRESS        0x004D
+#define HostCmd_CMD_802_11_EEPROM_ACCESS      0x0059
+
+#define HostCmd_CMD_802_11_BAND_CONFIG        0x0058
+
+#define HostCmd_CMD_802_11D_DOMAIN_INFO       0x005b
+
+#define HostCmd_CMD_802_11_SLEEP_PARAMS          0x0066
+
+#define HostCmd_CMD_802_11_INACTIVITY_TIMEOUT    0x0067
+
+#define HostCmd_CMD_802_11_SLEEP_PERIOD          0x0068
+
+#define HostCmd_CMD_802_11_TPC_CFG               0x0072
+#define HostCmd_CMD_802_11_PWR_CFG               0x0073
+
+#define HostCmd_CMD_802_11_LED_GPIO_CTRL         0x004e
+
+#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT       0x0075
+
+#define HostCmd_CMD_802_11_RATE_ADAPT_RATESET    0x0076
+
+#define HostCmd_CMD_802_11_TX_RATE_QUERY	0x007f
+
+#define HostCmd_CMD_GET_TSF                      0x0080
+
+#define HostCmd_CMD_DFT_ACCESS			0x0087
+#define HostCmd_RET_DFT_ACCESS			0x8087
+
+/* For the IEEE Power Save */
+#define HostCmd_SubCmd_Enter_PS               0x0030
+#define HostCmd_SubCmd_Exit_PS                0x0031
+#define HostCmd_SubCmd_Sleep_Confirmed        0x0034
+#define HostCmd_SubCmd_Full_PowerDown         0x0035
+#define HostCmd_SubCmd_Full_PowerUp           0x0036
+
+/* Command RET code, MSB is set to 1 */
+#define HostCmd_RET_NONE                      0x8000
+#define HostCmd_RET_HW_SPEC_INFO              0x8003
+#define HostCmd_RET_EEPROM_UPDATE             0x8004
+#define HostCmd_RET_802_11_RESET              0x8005
+#define HostCmd_RET_802_11_SCAN               0x8006
+#define HostCmd_RET_802_11_GET_LOG            0x800b
+#define HostCmd_RET_MAC_CONTROL               0x8028
+#define HostCmd_RET_MAC_MULTICAST_ADR         0x8010
+#define HostCmd_RET_802_11_AUTHENTICATE       0x8011
+#define HostCmd_RET_802_11_DEAUTHENTICATE     0x8024
+#define HostCmd_RET_802_11_ASSOCIATE          0x8012
+#define HostCmd_RET_802_11_REASSOCIATE        0x8025
+#define HostCmd_RET_802_11_DISASSOCIATE       0x8026
+#define HostCmd_RET_802_11_SET_WEP            0x8013
+#define HostCmd_RET_802_11_STAT               0x8014
+#define HostCmd_RET_802_3_STAT                0x8015
+#define HostCmd_RET_802_11_SNMP_MIB           0x8016
+#define HostCmd_RET_MAC_REG_MAP               0x8017
+#define HostCmd_RET_BBP_REG_MAP               0x8018
+#define HostCmd_RET_RF_REG_MAP                0x8023
+#define HostCmd_RET_MAC_REG_ACCESS            0x8019
+#define HostCmd_RET_BBP_REG_ACCESS            0x801a
+#define HostCmd_RET_RF_REG_ACCESS             0x801b
+#define HostCmd_RET_802_11_RADIO_CONTROL      0x801c
+#define HostCmd_RET_802_11_RF_CHANNEL         0x801d
+#define HostCmd_RET_802_11_RSSI               0x801f
+#define HostCmd_RET_802_11_RF_TX_POWER        0x801e
+#define HostCmd_RET_802_11_RF_ANTENNA         0x8020
+#define HostCmd_RET_802_11_PS_MODE            0x8021
+#define HostCmd_RET_802_11_DATA_RATE          0x8022
+
+#define HostCmd_RET_802_11_AD_HOC_START       0x802B
+#define HostCmd_RET_802_11_AD_HOC_JOIN        0x802C
+
+#define HostCmd_RET_802_11_QUERY_TKIP_REPLY_CNTRS  0x802e
+#define HostCmd_RET_802_11_ENABLE_RSN              0x802f
+#define HostCmd_RET_802_11_PAIRWISE_TSC       0x8036
+#define HostCmd_RET_802_11_GROUP_TSC          0x8037
+#define HostCmd_RET_802_11_KEY_MATERIAL       0x805e
+
+#define HostCmd_ENABLE_RSN                    0x0001
+#define HostCmd_DISABLE_RSN                   0x0000
+#define TYPE_ANTENNA_DIVERSITY                0xffff
+
+#define HostCmd_ACT_SET                       0x0001
+#define HostCmd_ACT_GET                       0x0000
+
+#define HostCmd_ACT_GET_AES                   (HostCmd_ACT_GET + 2)
+#define HostCmd_ACT_SET_AES                   (HostCmd_ACT_SET + 2)
+#define HostCmd_ACT_REMOVE_AES                (HostCmd_ACT_SET + 3)
+
+#define HostCmd_RET_802_11_SET_AFC            0x803c
+#define HostCmd_RET_802_11_GET_AFC            0x803d
+
+#define HostCmd_RET_802_11_AD_HOC_STOP        0x8040
+
+#define HostCmd_RET_802_11_BEACON_STOP        0x8049
+
+#define HostCmd_RET_802_11_MAC_ADDRESS        0x804D
+#define HostCmd_RET_802_11_EEPROM_ACCESS      0x8059
+
+#define HostCmd_RET_802_11_BAND_CONFIG        0x8058
+
+#define HostCmd_RET_802_11_SLEEP_PARAMS          0x8066
+
+#define HostCmd_RET_802_11_INACTIVITY_TIMEOUT    0x8067
+
+#define HostCmd_RET_802_11_SLEEP_PERIOD          0x8068
+
+#define HostCmd_RET_802_11D_DOMAIN_INFO      (0x8000 |                  \
+                                              HostCmd_CMD_802_11D_DOMAIN_INFO)
+
+#define HostCmd_RET_802_11_TPC_CFG        (HostCmd_CMD_802_11_TPC_CFG | 0x8000)
+#define HostCmd_RET_802_11_PWR_CFG        (HostCmd_CMD_802_11_PWR_CFG | 0x8000)
+
+#define HostCmd_RET_802_11_LED_GPIO_CTRL     0x804e
+
+#define HostCmd_RET_802_11_SUBSCRIBE_EVENT	(HostCmd_CMD_802_11_SUBSCRIBE_EVENT | 0x8000)
+
+#define HostCmd_RET_802_11_RATE_ADAPT_RATESET	(HostCmd_CMD_802_11_RATE_ADAPT_RATESET | 0x8000)
+
+#define HostCmd_RTE_802_11_TX_RATE_QUERY 	(HostCmd_CMD_802_11_TX_RATE_QUERY | 0x8000)
+
+#define HostCmd_RET_GET_TSF             0x8080
+
+/** General Result Code*/
+/* OK */
+#define HostCmd_RESULT_OK                    0x0000
+/* Genenral error */
+#define HostCmd_RESULT_ERROR                 0x0001
+/* Command is not valid */
+#define HostCmd_RESULT_NOT_SUPPORT           0x0002
+/* Command is pending */
+#define HostCmd_RESULT_PENDING               0x0003
+/* System is busy (command ignored) */
+#define HostCmd_RESULT_BUSY                  0x0004
+/* Data buffer is not big enough */
+#define HostCmd_RESULT_PARTIAL_DATA          0x0005
+
+/* Definition of action or option for each command */
+
+/* Define general purpose action */
+#define HostCmd_ACT_GEN_READ                    0x0000
+#define HostCmd_ACT_GEN_WRITE                   0x0001
+#define HostCmd_ACT_GEN_GET                     0x0000
+#define HostCmd_ACT_GEN_SET                     0x0001
+#define HostCmd_ACT_GEN_REMOVE			0x0002
+#define HostCmd_ACT_GEN_OFF                     0x0000
+#define HostCmd_ACT_GEN_ON                      0x0001
+
+/* Define action or option for HostCmd_CMD_802_11_AUTHENTICATE */
+#define HostCmd_ACT_AUTHENTICATE                0x0001
+#define HostCmd_ACT_DEAUTHENTICATE              0x0002
+
+/* Define action or option for HostCmd_CMD_802_11_ASSOCIATE */
+#define HostCmd_ACT_ASSOCIATE                   0x0001
+#define HostCmd_ACT_DISASSOCIATE                0x0002
+#define HostCmd_ACT_REASSOCIATE                 0x0003
+
+#define HostCmd_CAPINFO_ESS                     0x0001
+#define HostCmd_CAPINFO_IBSS                    0x0002
+#define HostCmd_CAPINFO_CF_POLLABLE             0x0004
+#define HostCmd_CAPINFO_CF_REQUEST              0x0008
+#define HostCmd_CAPINFO_PRIVACY                 0x0010
+
+/* Define action or option for HostCmd_CMD_802_11_SET_WEP */
+#define HostCmd_ACT_ADD                         0x0002
+#define HostCmd_ACT_REMOVE                      0x0004
+#define HostCmd_ACT_USE_DEFAULT                 0x0008
+
+#define HostCmd_TYPE_WEP_40_BIT                 0x0001
+#define HostCmd_TYPE_WEP_104_BIT                0x0002
+
+#define HostCmd_NUM_OF_WEP_KEYS                 4
+
+#define HostCmd_WEP_KEY_INDEX_MASK              0x3fff
+
+/* Define action or option for HostCmd_CMD_802_11_RESET */
+#define HostCmd_ACT_NOT_REVERT_MIB              0x0001
+#define HostCmd_ACT_REVERT_MIB                  0x0002
+#define HostCmd_ACT_HALT                        0x0003
+
+/* Define action or option for HostCmd_CMD_802_11_SCAN */
+#define HostCmd_BSS_TYPE_BSS                    0x0001
+#define HostCmd_BSS_TYPE_IBSS                   0x0002
+#define HostCmd_BSS_TYPE_ANY                    0x0003
+
+/* Define action or option for HostCmd_CMD_802_11_SCAN */
+#define HostCmd_SCAN_TYPE_ACTIVE                0x0000
+#define HostCmd_SCAN_TYPE_PASSIVE               0x0001
+
+#define HostCmd_SCAN_802_11_B_CHANNELS          11
+
+#define HostCmd_SCAN_MIN_CH_TIME                6
+
+#define HostCmd_SCAN_MAX_CH_TIME                100
+
+#define HostCmd_SCAN_RADIO_TYPE_BG		0
+#define HostCmd_SCAN_RADIO_TYPE_A		1
+#define HostCmd_SCAN_PASSIVE_MAX_CH_TIME        100
+
+#define HostCmd_SCAN_PROBE_DELAY_TIME           0
+
+/* Define action or option for HostCmd_CMD_MAC_CONTROL */
+#define HostCmd_ACT_MAC_RX_ON                   0x0001
+#define HostCmd_ACT_MAC_TX_ON                   0x0002
+#define HostCmd_ACT_MAC_LOOPBACK_ON             0x0004
+#define HostCmd_ACT_MAC_WEP_ENABLE              0x0008
+#define HostCmd_ACT_MAC_INT_ENABLE              0x0010
+#define HostCmd_ACT_MAC_MULTICAST_ENABLE        0x0020
+#define HostCmd_ACT_MAC_BROADCAST_ENABLE        0x0040
+#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE      0x0080
+#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE    0x0100
+#define HostCmd_ACT_MAC_STRICT_PROTECTION_ENABLE  0x0400
+/* Define action or option or constant for HostCmd_CMD_MAC_MULTICAST_ADR */
+#define HostCmd_SIZE_MAC_ADR                    6
+#define HostCmd_MAX_MCAST_ADRS                  32
+
+/* Define action or option for HostCmd_CMD_802_11_SNMP_MIB */
+/* Boolean */
+#define HostCmd_TYPE_MIB_FLD_BOOLEAN            0x0001
+/* Integer */
+#define HostCmd_TYPE_MIB_FLD_INTEGER            0x0002
+/* Counter */
+#define HostCmd_TYPE_MIB_FLD_COUNTER            0x0003
+/* Octet string */
+#define HostCmd_TYPE_MIB_FLD_OCT_STR            0x0004
+/* String */
+#define HostCmd_TYPE_MIB_FLD_DISPLAY_STR        0x0005
+/* MAC address */
+#define HostCmd_TYPE_MIB_FLD_MAC_ADR            0x0006
+/* IP address */
+#define HostCmd_TYPE_MIB_FLD_IP_ADR             0x0007
+/* WEP */
+#define HostCmd_TYPE_MIB_FLD_WEP                0x0008
+
+/* Define action or option for HostCmd_CMD_802_11_RADIO_CONTROL */
+#define HostCmd_TYPE_AUTO_PREAMBLE              0x0001
+#define HostCmd_TYPE_SHORT_PREAMBLE             0x0002
+#define HostCmd_TYPE_LONG_PREAMBLE              0x0003
+
+#define TURN_ON_RF                              0x01
+#define RADIO_ON                                0x01
+#define RADIO_OFF                               0x00
+
+#define SET_AUTO_PREAMBLE                       0x05
+#define SET_SHORT_PREAMBLE                      0x03
+#define SET_LONG_PREAMBLE                       0x01
+
+/* Define action or option for CMD_802_11_RF_CHANNEL */
+#define HostCmd_OPT_802_11_RF_CHANNEL_GET       0x00
+#define HostCmd_OPT_802_11_RF_CHANNEL_SET       0x01
+
+/* Define action or option for HostCmd_CMD_802_11_RF_TX_POWER */
+#define HostCmd_ACT_TX_POWER_OPT_GET            0x0000
+#define HostCmd_ACT_TX_POWER_OPT_SET_HIGH       0x8007
+#define HostCmd_ACT_TX_POWER_OPT_SET_MID        0x8004
+#define HostCmd_ACT_TX_POWER_OPT_SET_LOW        0x8000
+
+#define HostCmd_ACT_TX_POWER_INDEX_HIGH         0x0007
+#define HostCmd_ACT_TX_POWER_INDEX_MID          0x0004
+#define HostCmd_ACT_TX_POWER_INDEX_LOW          0x0000
+
+/* Define action or option for HostCmd_CMD_802_11_DATA_RATE */
+#define HostCmd_ACT_SET_TX_AUTO                 0x0000
+#define HostCmd_ACT_SET_TX_FIX_RATE             0x0001
+#define HostCmd_ACT_GET_TX_RATE                 0x0002
+
+#define HostCmd_ACT_SET_RX                      0x0001
+#define HostCmd_ACT_SET_TX                      0x0002
+#define HostCmd_ACT_SET_BOTH                    0x0003
+#define HostCmd_ACT_GET_RX                      0x0004
+#define HostCmd_ACT_GET_TX                      0x0008
+#define HostCmd_ACT_GET_BOTH                    0x000c
+
+/* Define action or option for HostCmd_CMD_802_11_PS_MODE */
+#define HostCmd_TYPE_CAM                        0x0000
+#define HostCmd_TYPE_MAX_PSP                    0x0001
+#define HostCmd_TYPE_FAST_PSP                   0x0002
+
+/* Define action or option for HostCmd_CMD_DFT_ACCESS */
+enum HostCmd_CMD_DFT_ACCESS_OPTS {
+	HostCmd_ACT_DFT_ACCESS_ADD = 1,
+	HostCmd_ACT_DFT_ACCESS_DEL,
+	HostCmd_ACT_DFT_ACCESS_LIST,
+	HostCmd_ACT_DFT_ACCESS_RESET,
+	HostCmd_ACT_BT_ACCESS_ADD,
+	HostCmd_ACT_BT_ACCESS_DEL,
+	HostCmd_ACT_BT_ACCESS_LIST,
+	HostCmd_ACT_BT_ACCESS_RESET
+};
+
+/** Card Event definition */
+#define MACREG_INT_CODE_TX_PPA_FREE             0x00000000
+#define MACREG_INT_CODE_TX_DMA_DONE             0x00000001
+#define MACREG_INT_CODE_LINK_LOSE_W_SCAN        0x00000002
+#define MACREG_INT_CODE_LINK_LOSE_NO_SCAN       0x00000003
+#define MACREG_INT_CODE_LINK_SENSED             0x00000004
+#define MACREG_INT_CODE_CMD_FINISHED            0x00000005
+#define MACREG_INT_CODE_MIB_CHANGED             0x00000006
+#define MACREG_INT_CODE_INIT_DONE               0x00000007
+#define MACREG_INT_CODE_DEAUTHENTICATED         0x00000008
+#define MACREG_INT_CODE_DISASSOCIATED           0x00000009
+#define MACREG_INT_CODE_PS_AWAKE                0x0000000a
+#define MACREG_INT_CODE_PS_SLEEP                0x0000000b
+#define MACREG_INT_CODE_MIC_ERR_MULTICAST       0x0000000d
+#define MACREG_INT_CODE_MIC_ERR_UNICAST         0x0000000e
+#define MACREG_INT_CODE_WM_AWAKE                0x0000000f
+#define MACREG_INT_CODE_ADHOC_BCN_LOST          0x00000011
+#define MACREG_INT_CODE_RSSI_LOW		0x00000019
+#define MACREG_INT_CODE_SNR_LOW			0x0000001a
+#define MACREG_INT_CODE_MAX_FAIL		0x0000001b
+#define MACREG_INT_CODE_RSSI_HIGH		0x0000001c
+#define MACREG_INT_CODE_SNR_HIGH		0x0000001d
+
+#endif				/* _HOST_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/if_usb.c linux-2.6-libertas/drivers/net/wireless/libertas/if_usb.c
--- linux-2.6-orig/drivers/net/wireless/libertas/if_usb.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/if_usb.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,1085 @@
+/** @file if_usb.c
+  * @brief This file contains functions used in USB interface module.
+  *  
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	09/29/05: Add Doxygen format comments
+	02/01/06: Correct the usage of compile flag HELPER_IMAGE
+	02/13/06: Add a FW ready flag for interoperability issue
+	02/22/06: Add support for new VID/PID
+	03/02/06: Add receive exception handling, fix some memory leak issues
+	03/03/06: Add FW download failure handling
+	03/10/06: Fix the rmmod/insmod issue
+	04/07/06: Add Linux kernel 2.6 support
+	04/21/06: Add hotplug firmware loading
+	
+********************************************************/
+
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/netdevice.h>
+#include <linux/usb.h>
+
+#include "if_usb.h"
+#include "host.h"
+#include "sbi.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+
+/* Context definition for Interrupt simulation */
+#define TX_SUCCESS	1
+#define RX_SUCCESS	2
+#define TX_FAILURE	-1
+
+#define MESSAGE_HEADER_LEN	4
+
+static usb_notifier_fn_add wlan_card_add_cb = NULL;
+static usb_notifier_fn_remove wlan_card_remove_cb = NULL;
+static const char usbdriver_name[] = "usb8xxx";
+static u8 usb_int_cause = 0;
+
+/** struct This structure contains the device signature */
+static struct usb_device_id if_usb_table[] = {
+	/* Enter the device signature inside */
+	{
+		USB_DEVICE(USB8388_VID_1, USB8388_PID_1),
+	},
+	{
+		USB_DEVICE(USB8388_VID_2, USB8388_PID_2),
+	},
+	{}	/* Terminating entry */
+};
+
+static int if_prog_firmware(wlan_private * priv);
+static void if_usb_receive(struct urb *urb, struct pt_regs *regs);
+static void if_usb_receive_fwload(struct urb *urb, struct pt_regs *regs);
+static int if_usb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id);
+static void if_usb_disconnect(struct usb_interface *intf);
+#ifdef CONFIG_PM
+static int if_usb_suspend(struct usb_interface *intf, pm_message_t message);
+static int if_usb_resume(struct usb_interface *intf);
+#else
+#define if_usb_suspend NULL
+#define if_usb_resume NULL
+#endif
+
+static int __if_usb_submit_rx_urb(wlan_private * priv,
+				  void (*callbackfn)
+				  (struct urb *urb, struct pt_regs *regs));
+
+/** if_usb_driver */
+static struct usb_driver if_usb_driver = {
+	/* driver name */
+	.name = usbdriver_name,
+	/* probe function name */
+	.probe = if_usb_probe,
+	/* disconnect function  name */
+	.disconnect = if_usb_disconnect,
+	/* device signature table */
+	.id_table = if_usb_table,
+	.suspend = if_usb_suspend,
+	.resume = if_usb_resume,
+};
+
+MODULE_DEVICE_TABLE(usb, if_usb_table);
+
+/** 
+ *  @brief  Interrupt handler
+ *  @param priv         pointer to wlan_private
+ *  @param flag   	flag
+ *  @param context  	context parameter
+ *  @return 	   	N/A
+ */
+static void if_usb_interrupt(wlan_private * priv, u8 flags, int context)
+{
+	libertas_interrupt(priv->wlan_dev.netdev);
+}
+
+/** 
+ *  @brief  call back function to handle the status of the URB
+ *  @param urb 		pointer to urb structure
+ *  @return 	   	N/A
+ */
+static void if_usb_write_bulk_callback(struct urb *urb, struct pt_regs *regs)
+{
+	wlan_private *priv = (wlan_private *) (urb->context);
+	wlan_adapter *adapter = priv->adapter;
+	struct net_device *dev = priv->wlan_dev.netdev;
+
+	ENTER();
+
+	/* handle the transmission complete validations */
+
+	if (urb->status != 0) {
+		/* print the failure status number for debug */
+		PRINTM(FATAL, "URB in failure status\n");
+	} else {
+		PRINTM(INFO, "URB status is successfull\n");
+		PRINTM(INFO, "Actual length transmitted %d\n",
+		       urb->actual_length);
+		priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+		if ((adapter->MediaConnectStatus == WlanMediaStateConnected))
+			netif_wake_queue(dev);
+	}
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief  free tx/rx urb, skb and rx buffer
+ *  @param cardp	pointer usb_card_rec
+ *  @return 	   	N/A
+ */
+static void if_usb_free(struct usb_card_rec *cardp)
+{
+	ENTER();
+
+	/* Unlink tx & rx urb */
+	usb_kill_urb(cardp->tx_urb);
+	usb_kill_urb(cardp->rx_urb);
+
+	usb_free_urb(cardp->tx_urb);
+	cardp->tx_urb = NULL;
+
+	usb_free_urb(cardp->rx_urb);
+	cardp->rx_urb = NULL;
+
+	kfree(cardp->bulk_out_buffer);
+	cardp->bulk_out_buffer = NULL;
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief sets the configuration values
+ *  @param ifnum	interface number
+ *  @param id		pointer to usb_device_id
+ *  @return 	   	0 on success, error code on failure
+ */
+static int if_usb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	struct usb_device *udev;
+	struct usb_host_interface *iface_desc;
+	struct usb_endpoint_descriptor *endpoint;
+	wlan_private *pwlanpriv;
+	struct usb_card_rec *usb_cardp;
+	int i;
+
+	ENTER();
+
+	udev = interface_to_usbdev(intf);
+
+	/* Check probe is for our device */
+	for (i = 0; if_usb_table[i].idVendor; i++) {
+		if (udev->descriptor.idVendor == if_usb_table[i].idVendor &&
+		    udev->descriptor.idProduct == if_usb_table[i].idProduct) {
+			PRINTM(INFO, "VID/PID = %X/%X, matched\n",
+			       udev->descriptor.idVendor,
+			       udev->descriptor.idProduct);
+			break;
+		}
+	}
+
+	if (!if_usb_table[i].idVendor) {
+		PRINTM(INFO, "Discard the Probe request\n");
+		PRINTM(INFO, "VID = 0x%X PID = 0x%X\n",
+		       udev->descriptor.idVendor, udev->descriptor.idProduct);
+		LEAVE();
+		return -ENODEV;
+	}
+
+	usb_cardp = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL);
+	if (!usb_cardp) {
+		PRINTM(FATAL, "Out of memory allocating private data.\n");
+		goto error;
+	}
+
+	usb_cardp->add = wlan_card_add_cb;
+	usb_cardp->remove = wlan_card_remove_cb;
+	usb_cardp->udev = udev;
+	iface_desc = intf->cur_altsetting;
+
+	PRINTM(INFO, "bcdUSB = 0x%X bDeviceClass = 0x%X"
+	       " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n",
+	       udev->descriptor.bcdUSB,
+	       udev->descriptor.bDeviceClass,
+	       udev->descriptor.bDeviceSubClass,
+	       udev->descriptor.bDeviceProtocol);
+
+	for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
+		endpoint = &iface_desc->endpoint[i].desc;
+		if ((endpoint->bEndpointAddress & BULK_ENDPOINT_PRESENT)
+		    && ((endpoint->bmAttributes & BULK_ENDPOINT_MASK) ==
+			BULK_ENDPOINT_FOUND)) {
+			/* we found a bulk in endpoint */
+			PRINTM(INFO, "Bulk in size is %d\n",
+			       endpoint->wMaxPacketSize);
+			if (!
+			    (usb_cardp->rx_urb =
+			     usb_alloc_urb(0, GFP_KERNEL))) {
+				PRINTM(INFO,
+				       "Rx URB allocation failed\n");
+				goto dealloc;
+			}
+			usb_cardp->rx_urb_recall = 0;
+
+			usb_cardp->bulk_in_size =
+			    endpoint->wMaxPacketSize;
+			usb_cardp->bulk_in_endpointAddr =
+			    (endpoint->
+			     bEndpointAddress & ENDPOINT_NUMBER_MASK);
+			PRINTM(INFO, "in_endpoint = %d\n",
+			       endpoint->bEndpointAddress);
+		}
+
+		if (((endpoint->
+		      bEndpointAddress & BULK_ENDPOINT_PRESENT) ==
+		     BULK_OUT_PRESENT)
+		    && ((endpoint->bmAttributes & BULK_ENDPOINT_MASK) ==
+			BULK_ENDPOINT_FOUND)) {
+			/* We found bulk out endpoint */
+			if (!
+			    (usb_cardp->tx_urb =
+			     usb_alloc_urb(0, GFP_KERNEL))) {
+				PRINTM(INFO,
+				       "Tx URB allocation failed\n");
+				goto dealloc;
+			}
+
+			usb_cardp->bulk_out_size =
+			    endpoint->wMaxPacketSize;
+			PRINTM(INFO, "Bulk out size is %d\n",
+			       endpoint->wMaxPacketSize);
+			usb_cardp->bulk_out_endpointAddr =
+			    endpoint->bEndpointAddress;
+			PRINTM(INFO, "out_endpoint = %d\n",
+			       endpoint->bEndpointAddress);
+			usb_cardp->bulk_out_buffer =
+			    kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE,
+				    GFP_DMA);
+
+			if (!usb_cardp->bulk_out_buffer) {
+				PRINTM(INFO,
+				       "Could not allocate buffer\n");
+				goto dealloc;
+			}
+		}
+	}
+
+	/* At this point wlan_add_card() will be called.  Don't worry
+	 * about keeping pwlanpriv around since it will be set on our
+	 * usb device data in -> add() -> libertas_sbi_register_dev().
+	 */
+	if (!(pwlanpriv = usb_cardp->add(usb_cardp))) {
+		goto dealloc;
+	}
+
+	usb_get_dev(udev);
+	usb_set_intfdata(intf, usb_cardp);
+	LEAVE();
+
+	/* 
+	 * return card structure, which can be got back in the 
+	 * diconnect function as the ptr
+	 * argument.
+	 */
+	return 0;
+
+dealloc:
+	if_usb_free(usb_cardp);
+
+error:
+	LEAVE();
+	return (-ENOMEM);
+}
+
+/** 
+ *  @brief free resource and cleanup
+ *  @param udev		pointer to usb_device
+ *  @param ptr		pointer to usb_cardp
+ *  @return 	   	N/A
+ */
+static void if_usb_disconnect(struct usb_interface *intf)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	wlan_private *priv = (wlan_private *) cardp->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* 
+	 * Update Surprie removed to TRUE  
+	 *  Free all the URB's allocated 
+	 */
+	if (!Adapter->SurpriseRemoved) {
+		Adapter->SurpriseRemoved = 1;
+	}
+
+	/* Unlink and free urb */
+	if_usb_free(cardp);
+
+	/* card is removed and we can call wlan_remove_card */
+	PRINTM(INFO, "call remove card\n");
+	cardp->remove(cardp);
+
+	usb_set_intfdata(intf, NULL);
+	usb_put_dev(interface_to_usbdev(intf));
+
+	LEAVE();
+	return;
+}
+
+/**  
+ *  @brief This function transfer the data to the device.
+ *  @param priv 	pointer to wlan_private
+ *  @param payload	pointer to payload data
+ *  @param nb		data length
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int usb_tx_block(wlan_private * priv, u8 * payload, u16 nb)
+{
+	/* pointer to card structure */
+	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	int ret = WLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	/* check if device is removed */
+	if (priv->adapter->SurpriseRemoved) {
+		PRINTM(INFO, "Device removed\n");
+		goto tx_ret;
+	}
+
+	/* use USB API macro FILL_BULK_URB or API function 
+	 * usb_fill_bulk_urb() used to set the 
+	 * configuration information to send the bulk URB
+	 */
+	usb_fill_bulk_urb(cardp->tx_urb, cardp->udev,
+			  usb_sndbulkpipe(cardp->udev,
+					  cardp->bulk_out_endpointAddr),
+			  payload, nb, if_usb_write_bulk_callback, priv);
+
+	cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+	if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) {
+		/*  transfer failed */
+		PRINTM(INFO, "usb_submit_urb Failed\n");
+
+		ret = WLAN_STATUS_FAILURE;
+	} else {
+		PRINTM(INFO, "usb_submit_urb Success\n");
+		ret = WLAN_STATUS_SUCCESS;
+	}
+
+tx_ret:
+	LEAVE();
+	return ret;
+}
+
+/* read callback private data */
+struct read_cb_info {
+	wlan_private *priv;
+	struct sk_buff *skb;
+};
+
+/**  
+ *  @brief This function submit the rx data to OS, used at firmware load time.
+ *  @param priv		pointer to wlan_private structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static inline int if_usb_submit_rx_urb_fwload(wlan_private * priv)
+{
+	return __if_usb_submit_rx_urb(priv, &if_usb_receive_fwload);
+}
+
+/**  
+ *  @brief This function submit the rx data to OS
+ *  @param priv		pointer to wlan_private structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static inline int if_usb_submit_rx_urb(wlan_private * priv)
+{
+	return __if_usb_submit_rx_urb(priv, &if_usb_receive);
+}
+
+
+/**  
+ *  @brief This function submit the rx data to OS
+ *  @param priv		pointer to wlan_private structure
+ *  @callbackfn		pointer to callback function to use
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int __if_usb_submit_rx_urb(wlan_private * priv,
+				  void (*callbackfn)
+				  (struct urb *urb, struct pt_regs *regs))
+{
+	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct sk_buff *skb;
+	struct read_cb_info *rinfo;
+	int ret = WLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	if (!(rinfo = kmalloc(sizeof(struct read_cb_info), GFP_ATOMIC))) {
+		PRINTM(FATAL, "No free read_callback_info\n");
+		goto rx_ret;
+	}
+
+	if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) {
+		PRINTM(FATAL, "No free skb\n");
+		kfree(rinfo);
+		goto rx_ret;
+	}
+
+	rinfo->skb = skb;
+	rinfo->priv = priv;
+
+	/* Fill the receive configuration URB and initialise the Rx call back */
+	usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
+			  usb_rcvbulkpipe(cardp->udev,
+					  cardp->bulk_in_endpointAddr),
+			  skb->tail + IPFIELD_ALIGN_OFFSET,
+			  MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
+			  rinfo);
+
+	cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET;
+
+	PRINTM(INFO, "Pointer for rx_urb %p\n", cardp->rx_urb);
+	if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) {
+		/* handle failure conditions */
+		PRINTM(INFO, "Submit Rx URB failed\n");
+		ret = WLAN_STATUS_FAILURE;
+	} else {
+		PRINTM(INFO, "Submit Rx URB Success\n");
+		ret = WLAN_STATUS_SUCCESS;
+	}
+
+rx_ret:
+	LEAVE();
+	return ret;
+}
+
+
+static void if_usb_receive_fwload(struct urb *urb, struct pt_regs *regs)
+{
+	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
+	wlan_private *priv = rinfo->priv;
+	struct sk_buff *skb = rinfo->skb;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+	struct FWSyncHeader *SyncFWHeader;
+
+	ENTER();
+
+	kfree(rinfo);
+
+	if (urb->status) {
+		PRINTM(INFO, "URB Status is failed during fw load\n");
+		kfree_skb(skb);
+		return;
+	}
+
+	SyncFWHeader = kmalloc(sizeof(struct FWSyncHeader), GFP_ATOMIC);
+	if (!SyncFWHeader) {
+		PRINTM(INFO, "Failure to allocate SyncFWHeader\n");
+		kfree_skb(skb);
+		return;
+	}
+	
+	memcpy(SyncFWHeader, skb->data + IPFIELD_ALIGN_OFFSET,
+			sizeof(struct FWSyncHeader));
+
+	if (!SyncFWHeader->Cmd) {
+		PRINTM(INFO, "FW received Blk with correct CRC\n");
+		PRINTM(INFO, "FW received Blk SeqNum = %d\n",
+		       SyncFWHeader->SeqNum);
+		cardp->CRC_OK = 1;
+	} else {
+		PRINTM(INFO, "FW received Blk with CRC error\n");
+		cardp->CRC_OK = 0;
+	}
+
+	kfree_skb(skb);
+
+	if (cardp->FWFinalBlk) {
+		cardp->FwDnldOver = 1;
+		goto exit;
+	}
+
+	if_prog_firmware(priv);
+
+	if_usb_submit_rx_urb_fwload(priv);
+exit:
+	kfree(SyncFWHeader);
+
+	return;
+
+}
+
+/**  
+ *  @brief This function reads of the packet into the upload buff, 
+ *  wake up the main thread and initialise the Rx callack.
+ *  
+ *  @param urb		pointer to struct urb
+ *  @return 	   	N/A
+ */
+static void if_usb_receive(struct urb *urb, struct pt_regs *regs)
+{
+	struct read_cb_info *rinfo = (struct read_cb_info *)urb->context;
+	wlan_private *priv = rinfo->priv;
+	struct sk_buff *skb = rinfo->skb;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+
+	int RecvLength = urb->actual_length;
+	u8 *RecvBuff = NULL;
+	u32 RecvType;
+	u8 *cmdBuf;
+
+#define MRVDRV_MIN_PKT_LEN	30
+
+	ENTER();
+
+	kfree(rinfo);
+
+	if (RecvLength) {
+		if (urb->status) {
+			PRINTM(INFO, "URB Status is failed\n");
+			kfree_skb(skb);
+			goto setup_for_next;
+		}
+
+		RecvBuff = skb->data + IPFIELD_ALIGN_OFFSET;
+		memcpy(&RecvType, RecvBuff, sizeof(u32));
+		PRINTM(INFO, "Recv length = 0x%x\n", RecvLength);
+		PRINTM(INFO, "Receive type = 0x%X\n", RecvType);
+		RecvType = wlan_le32_to_cpu(RecvType);
+		PRINTM(INFO, "Receive type after = 0x%X\n", RecvType);
+	} else if (urb->status) {
+		if (!cardp->rx_urb_recall) {
+			PRINTM(INFO, "Card Is Removed\n");
+			priv->adapter->SurpriseRemoved = 1;
+			// Wake up main thread to handle card removal.
+			if_usb_interrupt(priv, 0, 0);
+		}
+		goto rx_exit;
+	}
+
+
+	switch (RecvType) {
+	case CMD_TYPE_DATA:
+		if (RecvLength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE +
+		    MESSAGE_HEADER_LEN || RecvLength < MRVDRV_MIN_PKT_LEN) {
+			PRINTM(INFO, "Packet length is Invalid\n");
+
+			kfree_skb(skb);
+
+			break;
+		}
+
+		skb_reserve(skb, IPFIELD_ALIGN_OFFSET);
+		skb_put(skb, RecvLength);
+		skb_pull(skb, MESSAGE_HEADER_LEN);
+		libertas_process_rxed_packet(priv, skb);
+
+		priv->wlan_dev.upld_len = (RecvLength - MESSAGE_HEADER_LEN);
+
+		break;
+
+	case CMD_TYPE_REQUEST:
+		if (RecvLength > MRVDRV_SIZE_OF_CMD_BUFFER) {
+			PRINTM(INFO, "The receive buffer is too large\n");
+			kfree_skb(skb);
+
+			break;
+		}
+
+		/* take care of CurCmd = NULL case by reading the 
+		 * data to clear the interrupt */
+		if (!priv->adapter->CurCmd) {
+			cmdBuf = priv->wlan_dev.upld_buf;
+			priv->adapter->HisRegCpy &= ~HIS_CmdUpLdRdy;
+		} else {
+			cmdBuf = priv->adapter->CurCmd->BufVirtualAddr;
+		}
+
+		usb_int_cause |= HIS_CmdUpLdRdy;
+		priv->wlan_dev.upld_len = (RecvLength - MESSAGE_HEADER_LEN);
+		memcpy(cmdBuf, RecvBuff + MESSAGE_HEADER_LEN,
+		       priv->wlan_dev.upld_len);
+
+		kfree_skb(skb);
+
+		PRINTM(INFO, "Wake up main thread to handle cmd response\n");
+		if_usb_interrupt(priv, HIS_CmdUpLdRdy, RX_SUCCESS);
+		break;
+
+	case CMD_TYPE_INDICATION:
+		/* Event cause handling */
+		cardp->usb_event_cause = *(u32 *) (RecvBuff + MESSAGE_HEADER_LEN);
+
+		PRINTM(INFO, "**EVENT** 0x%X\n", cardp->usb_event_cause);
+		if (cardp->usb_event_cause & 0xffff0000) {
+			libertas_send_tx_feedback(priv);
+			break;
+		}
+		cardp->usb_event_cause = wlan_le32_to_cpu(cardp->usb_event_cause) << 3;
+		usb_int_cause |= HIS_CardEvent;
+		kfree_skb(skb);
+		if_usb_interrupt(priv, HIS_CardEvent, RX_SUCCESS);
+		goto rx_exit;
+
+	default:
+		kfree_skb(skb);
+		break;
+	}
+
+setup_for_next:
+	if_usb_submit_rx_urb(priv);
+rx_exit:
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This function downloads data to FW  
+ *  @param priv		pointer to wlan_private structure
+ *  @param type		type of data
+ *  @param buf		pointer to data buffer
+ *  @param len		number of bytes
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb)
+{
+	int ret = WLAN_STATUS_FAILURE;
+	u32 tmp;
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+
+	ENTER();
+
+	PRINTM(INFO, "*** type = %u\n", type);
+	PRINTM(INFO, "Size after = %d\n", nb);
+
+	if (type == MVMS_CMD) {
+		tmp = wlan_cpu_to_le32(CMD_TYPE_REQUEST);
+		priv->wlan_dev.dnld_sent = DNLD_CMD_SENT;
+		memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
+		       MESSAGE_HEADER_LEN);
+
+	} else {
+		tmp = wlan_cpu_to_le32(CMD_TYPE_DATA);
+		priv->wlan_dev.dnld_sent = DNLD_DATA_SENT;
+		memcpy(cardp->bulk_out_buffer, (u8 *) & tmp,
+		       MESSAGE_HEADER_LEN);
+	}
+
+	memcpy((cardp->bulk_out_buffer + MESSAGE_HEADER_LEN), payload, nb);
+
+	ret =
+	    usb_tx_block(priv, cardp->bulk_out_buffer, nb + MESSAGE_HEADER_LEN);
+
+	return ret;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_reenable_host_interrupt(wlan_private * priv, u8 bits)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/* called with libertas_driver_lock held */
+int libertas_sbi_get_int_status(wlan_private * priv, u8 * ireg)
+{
+	ENTER();
+
+	*ireg = usb_int_cause;
+	usb_int_cause = 0;
+
+	PRINTM(INFO, "Int cause is 0x%X\n", *ireg);
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_read_event_cause(wlan_private * priv)
+{
+	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	priv->adapter->EventCause = cardp->usb_event_cause;
+	/* Re-submit rx urb here to avoid event lost issue */
+	if_usb_submit_rx_urb(priv);
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_get_cis_info(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+static int reset_device(wlan_private *priv)
+{
+	int ret;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RESET,
+			   	    HostCmd_ACT_HALT, 0, 0, NULL);
+	msleep_interruptible(10);
+
+	return ret;
+}
+
+/** 
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_unregister_dev(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+
+	/* Need to send a Reset command to device before USB resources freed
+	 * and wlan_remove_card() called, then device can handle FW download
+	 * again.
+	 */
+	if (priv)
+		reset_device(priv);
+
+	return ret;
+}
+
+/**  
+ *  @brief This function registers driver.
+ *  @param add		pointer to add_card callback function
+ *  @param remove	pointer to remove card callback function
+ *  @param arg		pointer to call back function parameter
+ *  @return 	   	dummy success variable
+ */
+int *libertas_sbi_register(wlan_notifier_fn_add add, wlan_notifier_fn_remove remove,
+		  void *arg)
+{
+	ENTER();
+
+	wlan_card_add_cb = (usb_notifier_fn_add) add;
+	wlan_card_remove_cb = (usb_notifier_fn_remove) remove;
+
+	/* 
+	 * API registers the Marvell USB driver
+	 * to the USB system
+	 */
+	usb_register(&if_usb_driver);
+
+	LEAVE();
+
+	/* Return success to wlan layer */
+	return (int *)0x1;
+}
+
+/**  
+ *  @brief This function removes usb driver.
+ *  @return 	   	N/A
+ */
+void libertas_sbi_unregister(void)
+{
+	ENTER();
+
+	wlan_card_add_cb = NULL;
+	wlan_card_remove_cb = NULL;
+
+	/* API unregisters the driver from USB subsystem */
+	usb_deregister(&if_usb_driver);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_probe_card(void *card_p)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  This function register usb device and initialize parameter
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_sbi_register_dev(wlan_private * priv)
+{
+
+	struct usb_card_rec *cardp = (struct usb_card_rec *)priv->wlan_dev.card;
+	ENTER();
+
+	cardp->priv = priv;
+	cardp->eth_dev = priv->wlan_dev.netdev;
+	priv->hotplug_device = &(cardp->udev->dev);
+
+	SET_NETDEV_DEV(cardp->eth_dev, &(cardp->udev->dev));
+
+	PRINTM(INFO, "udev pointer is at %p\n", cardp->udev);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  stub function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_verify_fw_download(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  This function download FW
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+static int if_prog_firmware(wlan_private * priv)
+{
+	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	struct FWData *fwdata;
+	struct FWHeader *fwheader;
+	u8 *firmware = priv->firmware->data;
+
+	ENTER();
+
+	fwdata = kmalloc(sizeof(struct FWData), GFP_ATOMIC);
+
+	if (!fwdata)
+		return WLAN_STATUS_FAILURE;
+
+	fwheader = &fwdata->fwheader;
+
+	if (!cardp->CRC_OK) {
+		cardp->TotalBytes = cardp->FwLastBlkSent;
+		cardp->FWSeqNum = cardp->LastSeqNum - 1;
+	}
+
+	PRINTM(INFO, "TotalBytes = %d\n", cardp->TotalBytes);
+
+	memcpy(fwheader, &firmware[cardp->TotalBytes],
+	       sizeof(struct FWHeader));
+
+	cardp->FwLastBlkSent = cardp->TotalBytes;
+	cardp->TotalBytes += sizeof(struct FWHeader);
+
+	PRINTM(INFO, "Copy Data\n");
+	memcpy(fwdata->data, &firmware[cardp->TotalBytes],
+	       fwdata->fwheader.DataLength);
+
+	PRINTM(INFO, "Data Length = %d\n", fwdata->fwheader.DataLength);
+
+	cardp->FWSeqNum = cardp->FWSeqNum + 1;
+
+	fwdata->SeqNum = cardp->FWSeqNum;
+	cardp->LastSeqNum = fwdata->SeqNum;
+	cardp->TotalBytes += fwdata->fwheader.DataLength;
+
+	if (fwheader->DnldCmd == FW_HAS_DATA_TO_RECV) {
+		PRINTM(INFO, "There is data to follow\n");
+		PRINTM(INFO, "SeqNum = %d TotalBytes = %d\n", cardp->FWSeqNum,
+		       cardp->TotalBytes);
+		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
+		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
+
+	} else if (fwdata->fwheader.DnldCmd == FW_HAS_LAST_BLOCK) {
+		PRINTM(INFO, "Host has finished FW downloading\n");
+		PRINTM(INFO, "Donwloading FW JUMP BLOCK\n");
+		memcpy(cardp->bulk_out_buffer, fwheader, FW_DATA_XMIT_SIZE);
+		usb_tx_block(priv, cardp->bulk_out_buffer, FW_DATA_XMIT_SIZE);
+		cardp->FWFinalBlk = 1;
+	}
+
+	PRINTM(INFO, "The firmware download is done size is %d\n",
+		cardp->TotalBytes);
+
+	kfree(fwdata);
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function download fw
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_prog_firmware(wlan_private * priv)
+{
+	struct usb_card_rec *cardp = priv->wlan_dev.card;
+	int i = 0;
+
+	ENTER();
+
+	if (if_usb_submit_rx_urb_fwload(priv) < 0) {
+		PRINTM(INFO, "URB submission is failed\n");
+		libertas_sbi_unregister();
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+restart:
+	priv->adapter->fw_ready = 0;
+
+	cardp->TotalBytes = 0;
+	cardp->FwLastBlkSent = 0;
+	cardp->CRC_OK = 1;
+	cardp->FwDnldOver = 0;
+	cardp->FWSeqNum = -1;
+	cardp->TotalBytes = 0;
+	cardp->FWFinalBlk = 0;
+
+	if_prog_firmware(priv);
+
+	do {
+		PRINTM(INFO, "Wlan sched timeout\n");
+		i++;
+		msleep_interruptible(100);
+		if (priv->adapter->SurpriseRemoved || i >= 20)
+			break;
+	} while (!cardp->FwDnldOver);
+
+	if (!cardp->FwDnldOver) {
+		PRINTM(FATAL, "Failed to load fw, resetting device!\n");
+		if (!usb_reset_device(cardp->udev)) {
+			msleep(10);
+			reset_device(priv);
+			msleep(10);
+			goto restart;
+		}
+		PRINTM(FATAL, "FW download failure, time = %d ms\n", i * 100);
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	if_usb_submit_rx_urb(priv);
+
+	/* Delay 200 ms to waiting for the FW ready */
+	msleep_interruptible(200);
+
+	priv->adapter->fw_ready = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_enable_host_int(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_disable_host_int(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+#ifdef ENABLE_PM
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_suspend(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This is a dummy function
+ *  @param priv		pointer to wlan_private
+ *  @return 	   	WLAN_STATUS_SUCCESS
+ */
+int libertas_sbi_resume(wlan_private * priv)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+#endif
+
+#ifdef CONFIG_PM
+static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+	wlan_private *priv = cardp->priv;
+
+	ENTER();
+
+	if (priv->adapter->PSState != PS_STATE_FULL_POWER)
+		return -1;
+
+	netif_device_detach(cardp->eth_dev);
+
+	/* Unlink tx & rx urb */
+	usb_kill_urb(cardp->tx_urb);
+	usb_kill_urb(cardp->rx_urb);
+
+	cardp->rx_urb_recall = 1;
+
+	LEAVE();
+	return 0;
+}
+
+static int if_usb_resume(struct usb_interface *intf)
+{
+	struct usb_card_rec *cardp = usb_get_intfdata(intf);
+
+	ENTER();
+
+	cardp->rx_urb_recall = 0;
+
+	if_usb_submit_rx_urb(cardp->priv);
+
+	netif_device_attach(cardp->eth_dev);
+
+	LEAVE();
+	return 0;
+}
+#endif
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/if_usb.h linux-2.6-libertas/drivers/net/wireless/libertas/if_usb.h
--- linux-2.6-orig/drivers/net/wireless/libertas/if_usb.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/if_usb.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,114 @@
+/** @file if_usb.h
+  * 
+  * @brief This file contains definition for USB interface.
+  *  
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/11/05: Add Doxygen format comments
+	
+********************************************************/
+
+#define CMD_TYPE_REQUEST                0xF00DFACE
+#define CMD_TYPE_DATA                   0xBEADC0DE
+#define CMD_TYPE_INDICATION             0xBEEFFACE
+
+#define BULK_ENDPOINT_PRESENT		USB_ENDPOINT_DIR_MASK
+#define BULK_ENDPOINT_MASK		USB_ENDPOINT_XFERTYPE_MASK
+#define BULK_ENDPOINT_FOUND		USB_ENDPOINT_XFER_BULK
+#define ENDPOINT_NUMBER_MASK		USB_ENDPOINT_NUMBER_MASK
+
+#define BULK_OUT_PRESENT	0x00
+
+#define IPFIELD_ALIGN_OFFSET	2
+
+#define USB8388_VID_1	0x1286
+#define USB8388_PID_1	0x2001
+#define USB8388_VID_2	0x05a3
+#define USB8388_PID_2	0x8388
+
+/** USB card description structure*/
+struct usb_card_rec {
+	struct net_device *eth_dev;
+	struct usb_device *udev;
+	struct urb *rx_urb, *tx_urb;
+	u16 irq;
+	u32 port;
+	u8 flag;
+	u16 host_int_mask;
+	void *(*add) (struct usb_card_rec * card);
+	int (*remove) (struct usb_card_rec * card);
+	void (*user_isr) (int, void *, struct pt_regs *);
+	void *priv;
+
+	int bulk_in_size;
+	u8 bulk_in_endpointAddr;
+
+	u8 *bulk_out_buffer;
+	int bulk_out_size;
+	u8 bulk_out_endpointAddr;
+
+	u8 CRC_OK;
+	u8 SendNextBlk;
+	u32 FWSeqNum;
+	u32 LastSeqNum;
+	u32 TotalBytes;
+	u32 FwLastBlkSent;
+	u8 FwDnldOver;
+	u8 FWFinalBlk;
+
+	u32 usb_event_cause;
+
+	u8 rx_urb_recall;
+};
+
+typedef void *(*usb_notifier_fn_add) (struct usb_card_rec *);
+typedef int (*usb_notifier_fn_remove) (struct usb_card_rec *);
+
+/** FWHeader */
+struct FWHeader {
+	u32 DnldCmd;
+	u32 BaseAddr;
+	u32 DataLength;
+	u32 CRC;
+};
+
+#define FW_MAX_DATA_BLK_SIZE	600
+/** FWData */
+struct FWData {
+	struct FWHeader fwheader;
+	u32 SeqNum;
+	u8 data[FW_MAX_DATA_BLK_SIZE];
+};
+
+/** FWSyncHeader */
+struct FWSyncHeader {
+	u32 Cmd;
+	u32 SeqNum;
+};
+
+#define REQ_TYPE	0	/* for compilation only */
+#define REQ_CTRL	0	/* for compilation only */
+#define TIME_OUT_VALUE	0	/* for compilation only */
+
+#define FW_HAS_DATA_TO_RECV		0x00000001
+#define FW_HAS_LAST_BLOCK		0x00000004
+
+#define FW_DATA_XMIT_SIZE \
+	sizeof(struct FWHeader) + fwdata->fwheader.DataLength + sizeof(u32)
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/Makefile linux-2.6-libertas/drivers/net/wireless/libertas/Makefile
--- linux-2.6-orig/drivers/net/wireless/libertas/Makefile	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/Makefile	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,16 @@
+# EXTRA_CFLAGS += -Wpacked
+
+usb8xxx-objs := wlan_main.o wlan_fw.o wlan_wext.o \
+		wlan_rx.o wlan_tx.o wlan_cmd.o 	  \
+		wlan_cmdresp.o wlan_scan.o	  \
+		wlan_join.o wlan_11d.o 		  \
+		wlan_ioctl.o wlan_debugfs.o
+
+ifeq ($(CONFIG_LIBERTAS_USB_DEBUG), y)
+EXTRA_CFLAGS = -DDEBUG_LEVEL4 -DPROC_DEBUG
+endif
+
+usb8xxx-objs += if_usb.o
+
+obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/Makefile.old linux-2.6-libertas/drivers/net/wireless/libertas/Makefile.old
--- linux-2.6-orig/drivers/net/wireless/libertas/Makefile.old	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/Makefile.old	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,205 @@
+#
+# File: Makefile
+#
+# (c) Copyright © 2003-2006, Marvell International Ltd. 
+# All Rights Reserved
+#
+# This software file (the "File") is distributed by Marvell International 
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+# (the "License").  You may use, redistribute and/or modify this File in 
+# accordance with the terms and conditions of the License, a copy of which 
+# is available along with the File in the license.txt file or by writing to 
+# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+# 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+# this warranty disclaimer.
+#
+
+#############################################################################
+# Directories 
+#############################################################################
+
+# Directory of kernel source
+KERNELVER := $(shell uname -r)
+KERNELDIR = /lib/modules/$(KERNELVER)/build
+
+# Directory of driver binary
+BINDIR = ../bin_usb8388
+INSTALLDIR = /lib/modules/$(KERNELVER)/kernel/drivers/usb
+
+
+#############################################################################
+# Configuration Options
+#############################################################################
+
+# Debug Option
+# DEBUG LEVEL n/1/2/3/4:
+# n: NO DEBUG
+# 1: Only PRINTM(MSG,...)
+# 2: PRINTM(MSG,...) and PRINTM(FATAL,...)
+# 3: PRINTM(MSG,...), PRINTM(FATAL,...) and PRINTM(WARN,...)
+# 4: PRINTM(MSG,...), PRINTM(FATAL,...), PRINTM(WARN,...) and PRINTM(INFO,...)
+CONFIG_DEBUG=1
+
+# Proc in /proc/net/wlan
+CONFIG_PROC_DEBUG=y
+
+# Linux Power Management
+CONFIG_ENABLE_PM=n
+
+# Re-association in driver
+CONFIG_REASSOCIATION=y
+
+
+#############################################################################
+# Compiler Flags
+#############################################################################
+
+CFLAGS += -I$(PWD)/os/linux
+CFLAGS += -I$(PWD)/wlan
+CFLAGS += -I$(PWD)/if/if_usb 
+CFLAGS += -I$(KERNELDIR)/include
+
+CFLAGS += -DFPNUM='"14"'
+
+ifeq ($(CONFIG_DEBUG),1)
+	CFLAGS += -DDEBUG_LEVEL1
+endif
+
+ifeq ($(CONFIG_DEBUG),2)
+	CFLAGS += -DDEBUG_LEVEL1
+	CFLAGS += -DDEBUG_LEVEL2
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_DEBUG),3)
+	CFLAGS += -DDEBUG_LEVEL1
+	CFLAGS += -DDEBUG_LEVEL2
+	CFLAGS += -DDEBUG_LEVEL3
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_DEBUG),4)
+	CFLAGS += -DDEBUG_LEVEL1
+	CFLAGS += -DDEBUG_LEVEL2
+	CFLAGS += -DDEBUG_LEVEL3
+	CFLAGS += -DDEBUG_LEVEL4
+	DBG=	-dbg
+endif
+
+ifeq ($(CONFIG_PROC_DEBUG),y)
+	CFLAGS += -DPROC_DEBUG
+endif
+
+ifeq ($(CONFIG_ENABLE_PM),y)
+	CFLAGS += -DENABLE_PM
+endif
+
+ifeq ($(CONFIG_REASSOCIATION),y)
+	CFLAGS += -DREASSOCIATION
+endif
+
+
+#############################################################################
+# Make Targets
+#############################################################################
+
+# If KERNELRELEASE is defined, we've been invoked from the kernel build 
+# system and can use it's language.
+
+ifneq ($(KERNELRELEASE),)
+
+WLANOBJS =	wlan/wlan_main.o wlan/wlan_fw.o wlan/wlan_wext.o \
+		wlan/wlan_rx.o wlan/wlan_tx.o \
+		wlan/wlan_cmd.o wlan/wlan_cmdresp.o \
+		wlan/wlan_proc.o wlan/wlan_scan.o wlan/wlan_join.o \
+		wlan/wlan_11d.o  
+
+ifeq ($(CONFIG_PROC_DEBUG), y)
+WLANOBJS += wlan/wlan_debug.o
+endif
+
+IFOBJS := if/if_usb/if_usb.o
+obj-m := usb8xxx.o
+usb8xxx-objs := $(WLANOBJS) $(IFOBJS)
+
+# Otherwise we were called directly from the command line; invoke the kernel build system.
+else
+
+default:
+	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
+
+endif
+
+###############################################################
+
+export		CFLAGS KERNELDIR 
+
+.PHONY: app/wlanconfig wlan clean distclean
+
+	@echo "Finished Making Marvell Wlan Linux Driver"
+
+
+wlan app/wlanconfig:
+	$(MAKE) -C $@
+
+echo:
+		@echo "===> Driver will be put to ../bin_usb8388 directory..."
+
+build:		echo default
+
+		@if [ ! -d $(BINDIR) ]; then \
+			mkdir $(BINDIR); \
+		fi 
+
+		mv usb8xxx.ko $(BINDIR)/usb8388$(DBG).ko
+		cp -f README $(BINDIR)
+		$(MAKE) -C app/wlanconfig $@ INSTALLDIR=$(BINDIR)
+		cp -r config $(BINDIR)
+
+install: default
+		cp -f usb8xxx.ko $(INSTALLDIR)/usb8388$(DBG).ko
+		@echo $(INSTALLDIR)
+		@echo "===> USB8388 driver installed"
+
+clean:
+		rm -f *.ko .*.ko.cmd
+		-find . -name "*.o" -exec rm {} \;
+		-find . -name ".*.o.cmd" -exec rm {} \;
+		-find . -name "*.mod.c" -exec rm {} \;
+		$(MAKE) -C app/wlanconfig $@
+
+distclean:
+		-find . -name "*.o" -exec rm {} \;
+		-find . -name ".*.o.cmd" -exec rm {} \;
+		-find . -name "*.orig" -exec rm {} \;
+		-find . -name "*.swp" -exec rm {} \;
+		-find . -name "*.*~" -exec rm {} \;
+		-find . -name "*~" -exec rm {} \;
+		-find . -name "*.d" -exec rm {} \;
+		-find . -name "*.a" -exec rm {} \;
+		-find . -name "tags" -exec rm {} \;
+		-find . -name "*.mod.c" -exec rm {} \;
+		-find . -name "*.ko" -exec rm {} \;
+		-find . -name ".*.ko.cmd" -exec rm {} \;
+		-find . -name ".*" -exec rm -rf 2> /dev/null \;
+		-rm -rf .tmp_versions/
+		$(MAKE) -C app/wlanconfig $@
+
+newlogs:
+		rm -f /var/log/message*
+		sleep 1
+		/etc/rc.d/init.d/syslog restart
+
+rmtags:
+		rm -f tags
+
+tags:		rmtags
+		ctags -R *.[ch] wlan/*.[ch] if/if_usb/*.[ch] os/linux/*.[ch] \
+			$(KERNELDIR)/include/linux \
+			$(KERNELDIR)/include/net $(KERNELDIR)/include/asm 
+
+# End of file
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/radiotap.h linux-2.6-libertas/drivers/net/wireless/libertas/radiotap.h
--- linux-2.6-orig/drivers/net/wireless/libertas/radiotap.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/radiotap.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,96 @@
+/** 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+
+#include <net/ieee80211_radiotap.h>
+
+/* XXX: move to net/ieee_80211_radiotap.h, this are from the new header file */
+/* For IEEE80211_RADIOTAP_RX_FLAGS */
+#define	IEEE80211_RADIOTAP_F_RX_BADFCS	0x0001	/* frame failed crc check */
+
+/* For IEEE80211_RADIOTAP_TX_FLAGS */
+#define	IEEE80211_RADIOTAP_F_TX_FAIL	0x0001	/* failed due to excessive 
+						 * retries */
+#define	IEEE80211_RADIOTAP_F_TX_CTS	0x0002	/* used cts 'protection' */
+#define	IEEE80211_RADIOTAP_F_TX_RTS	0x0004	/* used rts/cts handshake */
+
+struct IEEE80211_Hdr {
+	u16 FrameControl;
+	u16 DurationID;
+	u8 address1[ETH_ALEN];
+	u8 address2[ETH_ALEN];
+	u8 address3[ETH_ALEN];
+	u16 SeqControl;
+	u8 address4[ETH_ALEN];
+} __attribute__ ((packed));
+
+struct TxRadiotapHdr {
+	struct ieee80211_radiotap_header hdr;
+	u8 rate;
+	u8 txpower;
+	u8 rts_retries;
+	u8 data_retries;
+#if 0
+	u8 pad[IEEE80211_RADIOTAP_HDRLEN - 12];
+#endif
+} __attribute__ ((packed));
+
+#define TX_RADIOTAP_PRESENT (				\
+	(1 << IEEE80211_RADIOTAP_RATE) |		\
+	(1 << IEEE80211_RADIOTAP_DBM_TX_POWER) |	\
+	(1 << IEEE80211_RADIOTAP_RTS_RETRIES) |		\
+	(1 << IEEE80211_RADIOTAP_DATA_RETRIES)  |	\
+	0)
+
+#define IEEE80211_FC_VERSION_MASK    0x0003
+#define IEEE80211_FC_TYPE_MASK       0x000c
+#define IEEE80211_FC_TYPE_MGT        0x0000
+#define IEEE80211_FC_TYPE_CTL        0x0004
+#define IEEE80211_FC_TYPE_DATA       0x0008
+#define IEEE80211_FC_SUBTYPE_MASK    0x00f0
+#define IEEE80211_FC_TOFROMDS_MASK   0x0300
+#define IEEE80211_FC_TODS_MASK       0x0100
+#define IEEE80211_FC_FROMDS_MASK     0x0200
+#define IEEE80211_FC_NODS            0x0000
+#define IEEE80211_FC_TODS            0x0100
+#define IEEE80211_FC_FROMDS          0x0200
+#define IEEE80211_FC_DSTODS          0x0300
+
+struct RxRadiotapHdr {
+	struct ieee80211_radiotap_header hdr;
+	u8 flags;
+	u8 rate;
+	u16 chan_freq;
+	u16 chan_flags;
+	u8 antenna;
+	u8 antsignal;
+	u16 rx_flags;
+#if 0
+	u8 pad[IEEE80211_RADIOTAP_HDRLEN - 18];
+#endif
+} __attribute__ ((packed));
+
+#define RX_RADIOTAP_PRESENT (			\
+	(1 << IEEE80211_RADIOTAP_FLAGS) |	\
+	(1 << IEEE80211_RADIOTAP_RATE) |	\
+	(1 << IEEE80211_RADIOTAP_CHANNEL) |	\
+	(1 << IEEE80211_RADIOTAP_ANTENNA) |	\
+	(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\
+	(1 << IEEE80211_RADIOTAP_RX_FLAGS) |	\
+	0)
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/README linux-2.6-libertas/drivers/net/wireless/libertas/README
--- linux-2.6-orig/drivers/net/wireless/libertas/README	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/README	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,831 @@
+================================================================================
+			README for USB8388
+
+ (c) Copyright © 2003-2006, Marvell International Ltd. 
+ All Rights Reserved
+
+ This software file (the "File") is distributed by Marvell International 
+ Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+ (the "License").  You may use, redistribute and/or modify this File in 
+ accordance with the terms and conditions of the License, a copy of which 
+ is available along with the File in the license.txt file or by writing to 
+ the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+ 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+
+ THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+ IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+ ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+ this warranty disclaimer.
+================================================================================
+	
+******************* This driver works in kernel 2.6.x only *********************
+
+===================
+1) FOR DRIVER BUILD
+===================
+
+	o. Untar the source into a directory
+
+		tar xvzf usb8388-xxxx.tgz
+
+	o. Change to the source directory
+		
+		cd usb8388-xxxx/src
+
+	o. Modify Makefile if needed to set correct directory of kernel source
+
+	o. Build the driver
+
+		make distclean
+		make build
+
+	This should create the files including usb8388.ko which is the driver as
+	 a loadable module.
+
+=====================
+2) FOR DRIVER LOADING
+=====================
+	
+	o. Copy the firmware image (e.g. usb8388.bin) to /lib/firmware/
+
+	o. Load driver by using the following command:
+	
+		insmod usb8388.ko [fw_name=usb8388.bin]
+
+=====================
+3) FOR IWPRIV COMMAND
+=====================
+
+NAME
+	This manual describes the usage of private commands used in Marvell WLAN
+	Linux Driver. All the commands available in Wlanconfig will not be available 
+	in the iwpriv.
+
+SYNOPSIS
+	iwpriv <ethX> <command> [sub-command] ...
+
+	iwpriv ethX version
+	iwpriv ethX scantype [sub-command]
+	iwpriv ethX getSNR <n>
+	iwpriv ethX getNF <n>
+	iwpriv ethX getRSSI <n>
+	iwpriv ethX setrxant <n>
+	iwpriv ethX getrxant
+	iwpriv ethX settxant <n>
+	iwpriv ethX gettxant
+	iwpriv ethX authalgs <n>
+	iwpriv ethX pre-TBTT <n>
+	iwpriv ethX 8021xauthalgs <n>
+	iwpriv ethX encryptionmode <n>
+	iwpriv ethX setregioncode <n>
+	iwpriv ethX getregioncode 
+	iwpriv ethX setbcnavg <n>
+	iwpriv ethX getbcnavg
+	iwpriv ethX setdataavg <n>
+	iwpriv ethX setlisteninter <n>
+	iwpriv ethX getlisteninter
+	iwpriv ethX setmultipledtim <n>
+	iwpriv ethX getmultipledtim
+	iwpriv ethX atimwindow <n>
+	iwpriv ethX deauth
+	iwpriv ethX adhocstop
+	iwpriv ethX radioon
+	iwpriv ethX radiooff
+	iwpriv ethX reasso-on
+	iwpriv ethX reasso-off
+	iwpriv ethX scanmode  [sub-command]
+	iwpriv ethX setwpaie <n>
+	iwpriv ethX wlanidle-off
+	iwpriv ethX wlanidle-on
+	iwpriv ethX getcis
+	iwpriv ethX getlog
+	iwpriv ethX getadhocstatus
+	iwpriv ethX adhocgrate <n>
+
+Version 4 Command:
+	iwpriv ethX inactvityto <n>
+	iwpriv ethX sleeppd <n>
+	iwpriv ethX enable11d <n>
+	iwpriv ethX tpccfg <n>
+	iwpriv ethX powercfg <n>	
+	iwpriv ethX setafc <n>
+	iwpriv ethX getafc
+
+Version 5 Command:
+	iwpriv ethX ledgpio <n>
+	iwpriv ethX scanprobes <n>
+	iwpriv ethX lolisteninter <n>
+	iwpriv ethX rateadapt <n> <m>
+	iwpriv ethX txcontrol <n>
+	iwpriv ethX psnullinterval <n>
+	iwpriv ethX prescan <n>
+	iwpriv ethX getrxinfo
+	iwpriv ethX gettxrate
+	iwpriv ethX beaconinterval 
+
+DESCRIPTION
+	Those commands are used to send additional commands to the Marvell WLAN
+	card via the Linux device driver.
+
+	The ethX parameter specifies the network device that is to be used to 
+		perform this command on. it could be eth0, eth1 etc.
+
+version	
+	This is used to get the current version of the driver and the firmware.
+
+scantype	
+	This command is used to set the scan type to be used by the driver in 
+	the scan command. This setting will not be used while performing a scan
+	for a specific SSID, as it is always done with scan type being active. 
+	
+	where the sub-commands are: - 
+			active 	-- to set the scan type to active
+			passive -- to set the scan type to passive
+			get 	-- to get the scan type set in the driver
+
+getSNR  
+	This command gets the average and non average value of Signal to Noise 
+	Ratio of Beacon and Data.
+	
+	where value is:-
+			0 	-- Beacon non-average.
+	        	1 	-- Beacon average.
+	        	2 	-- Data non-average.
+	        	3 	-- Data average.
+
+	If no value is given, all four values are returned in the order mentioned
+	above.
+
+	Note: This command is available only when STA is connected.
+
+getRSSI	
+	This command gets the average and non average value os Receive Signal 
+	Strength of Beacon and Data.
+	
+	where value is:-
+			0 	-- Beacon non-average.
+	        	1 	-- Beacon average.
+	        	2 	-- Data non-average.
+	        	3 	-- Data average.
+
+	Note: This command is available only when STA is connected.
+
+getNF   
+	This command gets the average and non average value of Noise Floor of 
+	Beacon and Data.
+	
+	where value is:-
+			0 	-- Beacon non-average.
+	        	1 	-- Beacon average.
+	        	2 	-- Data non-average.
+	        	3 	-- Data average.
+
+	Note: This command is available only when STA is connected.
+
+setrxant	
+	This command is used to set the mode for Rx antenna. 
+	
+	The options that can be sent are:- 
+			1 	-- Antenna 1. 
+			2 	-- Antenna 2.
+			0xFFFF 	-- Diversity.
+
+	Usage:
+		iwpriv ethX setrxant 0x01: select Antenna 1.
+
+getrxant                    
+	This command is used to get the mode for Rx antenna.
+
+
+settxant	
+	This command is used to set the mode for Tx antenna.
+		The options that can be sent are:- 
+			1 	-- Antenna 1. 
+			2 	-- Antenna 2.
+			0xFFFF 	-- Diversity.
+	Usage:
+		iwpriv ethX settxant 0x01: select Antenna 1.
+
+gettxant                    
+	This command is used to get the mode for Tx antenna.
+
+authalgs	
+	This command is used by the WPA supplicant to set the authentication 
+	algorithms in the station.
+
+8021xauthalgs
+	This command is used by the WPA supplicant to set the 8021.x authentication algorithm type
+	station.
+	
+	where values can be:-
+			1 	-- None
+			2 	-- LEAP
+			4 	-- TLS
+			8 	-- TTLs
+			16	-- MD5	
+
+
+encryptionmode
+	This command is used by the WPA supplicant to set the encryption algorithm.
+		
+	where values can be:-
+			0 	-- NONE
+			1 	-- WEP40
+			2 	-- TKIP
+			3 	-- CCMP
+			4 	-- WEP104
+
+pre-TBTT	
+	This command is used to set pre-TBTT time period where value is in microseconds.
+
+setregioncode           
+	This command is used to set the region code in the station.
+	where value is 'region code' for various regions like
+	USA FCC, Canada IC, Spain, France, Europe ETSI,	Japan ...
+
+	Usage:
+		iwpriv ethX setregioncode 0x10: set region code to USA (0x10).
+
+getregioncode           
+	This command is used to get the region code information set in the 
+	station. 
+
+setbcnavg
+	Set the weighting factor for calculating RSSI.
+
+getbcnavg
+	Get weighting factor for calculating RSSI.
+
+setdataavg
+	Set the weighting factor for calculating SNR.
+
+setlisteninter             
+	This command is used to set the listen interval in the 
+	station.
+	
+	where the value ranges between 1 - 255
+
+getlisteninter            
+	This command is used to get the listen interval value set in the 
+	station.
+
+setmultipledtim         
+	This command is used to set the multiple dtim value in the 
+	station.
+		where the value is 1,2,3,4,5,0xfffe
+		0xfffe means the firmware will use listen interval in association
+		command for waking up
+
+getmultipledtim        
+	This command is used to get the multiple dtim value set in the station.
+
+atimwindow         
+	This command is used to set the atim value in the 
+	station. 
+
+	where the value ranges between 0 - 50
+
+deauth                      
+	This command is used to send the de-authentication to the AP with which 
+	the station is associated. This command is valid only when 
+	station is in Infrastructure mode.
+
+	Note: This command is available only when STA is connected.
+
+reasso-on                  
+	This command is used to enable re-association function in dirver.
+
+reasso-off                  
+	This command is used to disable re-association function in driver
+
+adhocstop                 
+	This command is used to stop beacon transmission from the station and 
+	go into idle state in ad-hoc mode.
+	
+	Note: This command is available only when STA is connected.
+
+radioon                     
+	This command is used to turn on the RF antenna.
+
+radiooff                    
+	This command is sued to turn off the RF antenna.   
+
+scanmode                 
+	This command is used to set the station to scan for either IBSS 
+	networks or BSS networks or both BSS and IBSS networks. This 
+	command can be used with sub commands,
+
+	where the value for 
+			bss 	-- Scan All the BSS networks.
+			ibss 	-- Scan All the IBSS networks.
+			any 	-- Scan both BSS and IBSS networks.
+			
+
+
+setwpaie                      
+	This command is used by WPA supplicant to send the WPA-IE to the driver. 
+	
+wlanidle-off                 
+	This command is used to get into idle state.
+
+	Note: This command is available only when STA is connected.
+
+wlanidle-on                 
+	This command is used to get off the idle state.
+
+	Note: This command is available only when STA is connected.
+
+
+
+getcis
+	This command is used to read the Card Info Structure Table.
+	
+getlog
+	This command is used to get the 802.11 statistics available in the 
+		station.
+	
+	Note: This command is available only when STA is connected.
+
+getadhocstatus
+	This command is used to get the ad-hoc Network Status.
+
+	The various status codes are:
+		AdhocStarted
+		AdhocJoined
+		AdhocIdle
+		InfraMode
+		AutoUnknownMode
+
+	Note: This command is available only when STA is connected.
+
+adhocgrate
+	This command is used to enable(1) g_rate, Disable(0) g_rate 
+	and request(2) the status which g_rate is disabled/enabled,
+	for Ad-hoc creator.
+
+	where value is:-
+		0	-- Disabled
+		1	-- Enabled
+		2	-- Get
+
+ledgpio
+	This command is used to set/get LEDs.
+
+	iwpriv ethX ledgpio <LEDs>
+		will set the corresponding LED for the GPIO Line.
+
+	iwpriv ethX ledgpio
+		will give u which LEDs are Enabled.
+
+	Usage:
+		iwpriv eth1 ledgpio 1 0 2 1 3 4
+			will enable 
+			LED 1 -> GPIO 0
+			LED 2 -> GPIO 1
+			LED 3 -> GPIO 4
+
+		iwpriv eth1 ledgpio 
+			shows LED information in the format as mentioned above.
+
+	Note: LED0 is invalid
+	Note: Maximum Number of LEDs are 16.		
+	
+inactivityto
+	This command is used by the host to set/get the inactivity timeout value, 
+	which specifies when WLAN device is put to sleep.
+	
+	Usage:
+		iwpriv ethX inactivityto [<timeout>]
+
+	where the parameter are:
+		timeout: timeout value in milliseconds.
+
+	Example:
+		iwpriv eth1 inactivityto
+			"get the timeout value"
+
+		iwpriv eth1 inactivityto X 
+			"set timeout value to X ms"
+
+
+sleeppd
+	This command is used to configure the sleep period of the WLAN device.
+
+	Usage:
+		iwpriv ethX sleeppd [<sleep period>]
+
+	where the parameter are:
+		Period: sleep period in milliseconds. Range 10~60.
+
+	Example:
+		iwpriv eth1 sleeppd 10 
+			"set period as 10 ms"
+		iwpriv eth1 sleeppd
+			"get the sleep period configuration"
+
+enable11d
+	This command is used to control 11d
+	where value is:-
+		1	-- Enabled
+		0	-- Disabled
+		2	-- Get
+
+
+	
+
+tpccfg
+	Enables or disables automatic transmit power control.
+
+	The first parameter turns this feature on (1) or off (0).  When turning 
+	on, the user must also supply four more parameters in the following 
+	order:
+		-UseSNR (Use SNR (in addition to PER) for TPC algorithm),
+		-P0 (P0 power level for TPC),
+		-P1 (P1 power level for TPC),
+		-P2 (P2 power level for TPC).
+
+	Usage:
+		iwpriv ethX tpccfg: Get current configuration
+		iwpriv ethX tpccfg 0: disable auto TPC
+		iwpriv ethX tpccfg 0x01 0x00 0x05 0x0a 0x0d: enable auto TPC; do not use SNR;
+							     P0=0x05; P1=0x0a; P2=0x0d;
+		iwpriv ethX tpccfg 0x01 0x01 0x05 0x0a 0x0d: enable auto TPC; use SNR;
+							     P0=0x05; P1=0x0a; P2=0x0d.
+
+powercfg
+	Enables or disables power adaptation.
+
+	The first parameter turns this feature on (1) or off (0).  When turning 
+	on, the user must also supply three more parameters in the following 
+	order:
+		-P0 (P0 power level for Power Adaptation),
+		-P1 (P1 power level for Power Adaptation),
+		-P2 (P2 power level for Power Adaptation).
+
+	Usage:
+		iwpriv ethX powercfg: Get current configuration
+		iwpriv ethX powercfg 0: disable power adaptation
+		iwpriv ethX powercfg 1 0x0d 0x0f 0x12: enable power adaptation;
+						       P0=0x0d; P1=0x0f; P2=0x12.
+
+getafc
+	This command returns automatic frequency control parameters.  It returns
+	three integers:
+		-P0: automatic is on (1), or off (0),
+		-P1: current timing offset in PPM (part per million), and
+		-P2: current frequency offset in PPM.
+
+setafc
+	Set automatic frequency control options.
+
+	The first parameter turns automatic on (1) or off (0).
+	The user must supply two more parameters in either case, in the following
+  order:
+
+  When auto is on:
+
+		-P0 (automatic adjustment frequency threshold in PPM),
+		-P1 (automatic adjustment period in beacon period),
+
+  When auto is off:
+
+		-P0 (manual adjustment timing offset in PPM), and
+		-P1 (manual adjustment frequency offset in PPM).
+
+	Usage:
+		iwpriv ethX setafc 0 10 10: manual adjustment, both timing and frequcncy 
+    offset are 10 PPM.
+
+		iwpriv ethX setafc 1 10 10 enable afc, automatic adjustment,
+    frequency threshold 10 PPM, for every 10 beacon periods.
+
+
+
+scanprobes
+	This command sets number of probe requests per channel.
+
+	Usage:
+		iwpriv ethX scanprobes 3 (set scan probes to 3)
+		iwpriv ethX scanprobes   (get scan probes)
+
+lolisteninter
+	This command sets the value of listen interval.
+
+	Usage:
+	iwpriv ethX lolisteninter 234 (set the lolisteninter to 234)
+	iwpriv ethX lolisteninter     (get the lolisteninter value)
+
+rateadapt
+	This command sets the data rates bitmap.
+	Where <n>
+		0: Disable auto rate adapt
+		1: Enable auto rate adapt
+		
+	      <m>
+		 data rate bitmap
+			Bit	Data rate
+			0	1 Mbps
+			1	2 Mbps
+			2	5.5 Mbps
+			3	11 Mbps
+			4	Reserved
+			5	6 Mbps
+			6	9 Mbps
+			7	12 Mbps
+			8	18 Mbps
+			9	24 Mbps
+			10	36 Mbps
+			11	48 Mbps
+			12	54 Mbps
+			12-15	Reserved
+
+	Usage:
+	iwpriv ethX rateadapt
+			read the currect data rate setting
+	iwpriv ethX rateadapt 1 0x07
+			enable auto data rate adapt and 
+			data rates are 1Mbps, 2Mbsp and 5.5Mbps
+	
+
+txcontrol
+	This command is used to set the Tx rate, ack policy, and retry limit on a per packet basis.
+
+	Where value <n> is:
+	    if bit[4] == 1:
+		bit[3:0]        -- 0   1   2   3   4   5   6   7   8   9   10   11   12   13-16
+		Data Rate(Mbps) -- 1   2   5.5 11  Rsv 6   9   12  18  24  36   48   54   Rsv
+
+	    bit[12:8] 
+		if bit[12] == 1, bit[11:8] specifies the Tx retry limit.
+
+	    bit[14:13] specifies per packet ack policy:
+		bit[14:13]   
+		     1  0	use immediate ack policy for this packet
+		     1  1       use no ack policy for this packet
+		     0  x	use the per-packet ack policy setting
+			
+	Usage:
+	iwpriv ethX txcontrol 0x7513
+			Use no-ack policy, 5 retires for Tx, 11Mbps rate
+
+
+
+psnullinterval
+	This command is used to set/request NULL package interval for Power Save
+	under infrastructure mode.
+
+	where value is:-
+		-1	-- Disabled
+		n>0	-- Set interval as n (seconds)
+
+prescan
+	This command is used to enable (1)/disable(0) auto prescan before assoicate to the ap 
+
+	where value is:-
+		0	-- Disabled
+		1	-- Enabled
+		2       -- Get
+
+getrxinfo
+	This command gets non average value of Signal to Noise Ratio of Data and rate index.
+
+	The following table shows RateIndex and Rate
+
+		     RateIndex	Data rate
+			0	1 Mbps
+			1	2 Mbps
+			2	5.5 Mbps
+			3	11 Mbps
+			4	Reserved
+			5	6 Mbps
+			6	9 Mbps
+			7	12 Mbps
+			8	18 Mbps
+			9	24 Mbps
+			10	36 Mbps
+			11	48 Mbps
+			12	54 Mbps
+			13-15	Reserved
+
+gettxrate	 
+	This command gets current Tx rate index of the first packet associated with Rate Adaptation.
+
+	The following table shows RateIndex and Rate
+
+		     RateIndex	Data rate
+			0	1 Mbps
+			1	2 Mbps
+			2	5.5 Mbps
+			3	11 Mbps
+			4	Reserved
+			5	6 Mbps
+			6	9 Mbps
+			7	12 Mbps
+			8	18 Mbps
+			9	24 Mbps
+			10	36 Mbps
+			11	48 Mbps
+			12	54 Mbps
+			13-15	Reserved
+
+bcninterval 
+	This command is used to sets beacon interval in adhoc mode when an argument is given, and gets current adhoc
+	beacon interval when no argument is given. The valid beacon interval is between 20 - 1000,
+	default beacon interval is 100.
+
+	Usage:
+		iwpriv ethX bcninterval 100  (set adhoc beacon interval to 100)
+		iwpriv ethX bcninterval      (get adhoc beacon interval)
+
+=========================
+4) FOR WLANCONFIG COMMAND
+=========================
+
+NAME
+wlanconfig - configure the additional parameters available for the Marvell 
+		WLAN Linux Driver.
+
+SYNOPSIS
+wlanconfig <ethX> <command> [parameters] ...
+wlanconfig ethX version
+wlanconfig ethX <rdmac|rdbbp|rdrf> <offset>
+wlanconfig ethX <wrmac|wrbbp|wrrf> <offset> <n>
+wlanconfig ethX rdeeprom <offset> <length>
+wlanconfig ethX sleepparams <config values>
+wlanconfig ethX extscan <ssid>
+wlanconfig ethX getscanlist
+
+Version 4 Command:
+
+Version 5 Command:
+wlanconfig ethX hostcmd <hostcmd.conf> <subevent_get>
+wlanconfig ethX hostcmd <hostcmd.conf> <subevent_set>
+
+
+Version 6 Command:
+wlanconfig ethX setuserscan [ARGS]
+wlanconfig ethX getscantable
+
+Version 8
+
+
+
+
+DESCRIPTION
+
+those commands are used in Marvell specic applicaion called wlanconfig.
+
+===========
+rdmac 
+rdbbp
+rdrf	
+	These commands are used to read the MAC, BBP and RF registers from the 
+	card.  These commands take one parameter that specifies the offset 
+	location that is to be read.  This parameter can be specified either in 
+	decimal or in hexadecimal (by preceding the number with a "0x").
+		
+	Usage:	
+		wlanconfig ethX rdmac 0xa123
+		wlanconfig ethX rdbbp 0x0123
+		wlanconfig ethX rdrf 0x0123
+
+wrmac 
+wrbbp
+wrrf	
+	These commands are used to write the MAC, BBP and RF registers in the 
+	card.  These commands take two parameters that specify the offset 
+	location and the value that is to be written. This parameters can be 
+	specified either in decimal or in hexadecimal (by preceding the number 
+	with a "0x").
+	
+	Usage:
+		wlanconfig ethX wrmac 0xa123 0xaa
+		wlanconfig ethX wrbbp 0x0123 0xaa
+		wlanconfig ethX wrrf 0x0123 0xaa
+
+
+
+
+rdeeprom
+	To read the EEPROM contents of the card.
+	
+	Usage:
+	wlanconfig ethX rdeeprom 0x00 0x10
+
+sleepparams       
+	This command is used to set the sleepclock configurations
+	
+	Usage:
+		wlanconfig ethX sleepparams get: reads the current sleepclock configuration
+	
+		wlanconfig ethX sleepparams set p1 p2 p3 p4 p5 p6: writes the sleepclock configuration.
+			
+		where:
+			p1 is Sleep clock error in ppm (0-65535)
+			p2 is Wakeup offset in usec (0-65535)
+			p3 is Clock stabilization time in usec (0-65535)
+			p4 is Control periodic calibration (0-2)
+			p5 is Control the use of external sleep clock (0-2)
+			p6 is reserved for debug (0-65535)
+
+
+
+
+
+hostcmd <hostcmd.conf> <subevent_get>
+hostcmd <hostcmd.conf> <subevent_set>
+	This command is used to set the configurations for 
+		event descriptor interface command.
+	hostcmd.conf is a generic configuration file containing multiple configuration enties
+		for subscrive event API
+	subsvent_get: get subscribed event parameters
+	subsvent_set: set subscribed event parameters
+
+	Usage:
+		wlanconfig ethX hostcmd hostcmd.conf subevent_get
+		wlanconfig ethX hostcmd hostcmd.conf subevent_set
+
+
+extscan
+	This command is used to do a specific scan.
+	
+	Usage: wlanconfig ethX extscan <SSID>
+
+	Example:
+		wlanconfig ethX extscan LINKSYS-AP
+
+	To see the results of use getscanlist command.
+
+getscanlist
+	This command is used to get the scan results.
+
+	Usage: wlanconfig ethX getscanlist
+		
+	Example:
+		wlanconfig ethX getscanlist
+
+
+
+
+setuserscan
+    Initiate a customized scan and retrieve the results
+
+    Usage:
+       wlanconfig ethX setuserscan [ARGS]
+
+         where [ARGS]: 
+
+      chan=[chan#][band][mode] where band is [a,b,g] and mode is 
+                               blank for active or 'p' for passive
+      bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+      ssid="[SSID]"            specify a SSID filter for the scan
+      keep=[0 or 1]            keep the previous scan results (1), discard (0)
+      dur=[scan time]          time to scan for each channel in milliseconds
+      probes=[#]               number of probe requests to send on each chan
+      type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+ 
+    Any combination of the above arguments can be supplied on the command line.
+      If the chan token is absent, a full channel scan will be completed by 
+      the driver.  If the dur or probes tokens are absent, the driver default
+      setting will be used.  The bssid and ssid fields, if blank, 
+      will produce an unfiltered scan. The type field will default to 3 (Any)
+      and the keep field will default to 0 (Discard).
+
+    Examples:
+    1) Perform an active scan on channels 1, 6, and 11 in the 'g' band:
+            setuserscan chan=1g,6g,11g
+
+    2) Perform a passive scan on channel 11 for 20 ms:
+            setuserscan chan=11gp dur=20
+
+    3) Perform an active scan on channels 1, 6, and 11; and a passive scan on
+       channel 36 in the 'a' band:
+            setuserscan chan=1g,6g,11g,36ap
+
+    4) Perform an active scan on channel 6 and 36 for a specific SSID:
+            setuserscan chan=6g,36a ssid="TestAP"
+
+    5) Scan all available channels (B/G, A bands) for a specific BSSID, keep
+       the current scan table intact, update existing or append new scan data:
+            setuserscan bssid=00:50:43:20:12:82 keep=1
+
+    6) Scan channel 6, for all infrastructure networks, sending two probe 
+       requests.  Keep the previous scan table intact. Update any duplicate
+       BSSID/SSID matches with the new scan data:
+            setuserscan chan=6g type=1 probes=2 keep=1
+
+    All entries in the scan table (not just the new scan data when keep=1) 
+    will be displayed upon completion by use of the getscantable ioctl.
+
+
+getscantable
+    Display the current contents of the driver scan table
+
+    Usage:
+       wlanconfig ethX getscantable
+
+
+
+
+
+==============================================================================
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/sbi.h linux-2.6-libertas/drivers/net/wireless/libertas/sbi.h
--- linux-2.6-orig/drivers/net/wireless/libertas/sbi.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/sbi.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,125 @@
+/** @file sbi.h
+  * 
+  * @brief This file contains IF layer definitions.
+  *  
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/11/05: Add Doxygen format comments
+	01/05/06: Add kernel 2.6.x support	
+	
+********************************************************/
+
+#ifndef	_SBI_H_
+#define	_SBI_H_
+
+#include <linux/interrupt.h>
+
+#include "wlan_defs.h"
+
+/**Bit Definition*/
+#define B_BIT_0		0x01
+#define B_BIT_1		0x02
+#define B_BIT_2		0x04
+#define B_BIT_3		0x08
+#define B_BIT_4		0x10
+#define B_BIT_5		0x20
+#define B_BIT_6		0x40
+#define B_BIT_7		0x80
+#define B_BIT_8		0x100
+#define B_BIT_9		0X200
+#define B_BIT_10	0x400
+
+/** INT Status Bit Definition*/
+#define HIS_CmdDnLdRdy			B_BIT_2
+#define HIS_CardEvent			B_BIT_3
+#define HIS_CmdUpLdRdy			B_BIT_4
+#define HIS_WrFifoOvrflow		B_BIT_5
+#define HIS_RdFifoUndrflow		B_BIT_6
+#define HIS_WlanReady			B_BIT_7
+
+#define	HIM_DISABLE			0xff
+#define HIM_ENABLE			0x03
+
+#define FIRMWARE_READY			0xfedc
+#ifndef DEV_NAME_LEN
+#define DEV_NAME_LEN			32
+#endif
+#define MAXKEYLEN			13
+
+/* The number of times to try when polling for status bits */
+#define MAX_POLL_TRIES			100
+
+/* The number of times to try when waiting for downloaded firmware to 
+     become active. (polling the scratch register). */
+
+#define MAX_FIRMWARE_POLL_TRIES		100
+
+#define FIRMWARE_TRANSFER_NBLOCK	2
+#define SBI_EVENT_CAUSE_SHIFT		3
+
+enum mv_sd_type {
+	MVSD_DAT,
+	MVSD_CMD,
+	MVSD_TXDONE,
+	MVSD_EVENT,
+};
+
+/** Function Prototype Declaration */
+typedef wlan_private *(*wlan_notifier_fn_add) (void *dev_id);
+typedef int (*wlan_notifier_fn_remove) (void *dev_id);
+
+typedef irqreturn_t(*isr_notifier_fn_t) (s32 irq, void *dev_id,
+					 struct pt_regs * reg);
+typedef irqreturn_t(*handler_fn_t) (s32 irq, void *dev_id, struct pt_regs *);
+
+/* Probe and Check if the card is present*/
+int libertas_sbi_probe_card(void *card);
+int libertas_sbi_register_dev(wlan_private * priv);
+int libertas_sbi_unregister_dev(wlan_private *);
+int libertas_sbi_disable_host_int(wlan_private * priv);
+int libertas_sbi_get_int_status(wlan_private * priv, u8 *);
+int *libertas_sbi_register(wlan_notifier_fn_add, wlan_notifier_fn_remove, void *);
+void libertas_sbi_unregister(void);
+int libertas_sbi_prog_firmware(wlan_private *);
+int libertas_sbi_verify_fw_download(wlan_private *);
+
+int libertas_sbi_read_event_cause(wlan_private *);
+int libertas_sbi_reenable_host_interrupt(wlan_private *, u8);
+int libertas_sbi_host_to_card(wlan_private * priv, u8 type, u8 * payload, u16 nb);
+int libertas_sbi_enable_host_int(wlan_private *);
+
+#ifdef ENABLE_PM
+int libertas_sbi_suspend(wlan_private *);
+int libertas_sbi_resume(wlan_private *);
+#endif
+
+int libertas_sbi_get_cis_info(wlan_private * priv);
+
+static inline u32 libertas_get_utimeofday(void)
+{
+	struct timeval t;
+	u32 ut;
+
+	do_gettimeofday(&t);
+	ut = (u32) t.tv_sec * 1000000 + ((u32) t.tv_usec);
+	return ut;
+}
+
+#endif				/* _SBI_H */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_11d.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_11d.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_11d.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_11d.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,872 @@
+/** @file wlan_11d.c
+  * @brief This file contains functions for 802.11D.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+#include <linux/ctype.h>
+#include <linux/kernel.h>
+#include <linux/wireless.h>
+
+#include "host.h"
+#include "wlan_decl.h"
+#include "wlan_11d.h"
+#include "wlan_dev.h"
+#include "wlan_wext.h"
+
+#define TX_PWR_DEFAULT	10
+
+static struct region_code_mapping region_code_mapping[] = {
+	{"US ", 0x10},		/* US FCC      */
+	{"CA ", 0x10},		/* IC Canada   */
+	{"SG ", 0x10},		/* Singapore   */
+	{"EU ", 0x30},		/* ETSI        */
+	{"AU ", 0x30},		/* Australia   */
+	{"KR ", 0x30},		/* Republic Of Korea */
+	{"ES ", 0x31},		/* Spain       */
+	{"FR ", 0x32},		/* France      */
+	{"JP ", 0x40},		/* Japan       */
+};
+
+/* Following 2 structure defines the supported channels */
+static struct chan_freq_power channel_freq_power_UN_BG[] = {
+	{1, 2412, TX_PWR_DEFAULT},
+	{2, 2417, TX_PWR_DEFAULT},
+	{3, 2422, TX_PWR_DEFAULT},
+	{4, 2427, TX_PWR_DEFAULT},
+	{5, 2432, TX_PWR_DEFAULT},
+	{6, 2437, TX_PWR_DEFAULT},
+	{7, 2442, TX_PWR_DEFAULT},
+	{8, 2447, TX_PWR_DEFAULT},
+	{9, 2452, TX_PWR_DEFAULT},
+	{10, 2457, TX_PWR_DEFAULT},
+	{11, 2462, TX_PWR_DEFAULT},
+	{12, 2467, TX_PWR_DEFAULT},
+	{13, 2472, TX_PWR_DEFAULT},
+	{14, 2484, TX_PWR_DEFAULT}
+};
+
+extern struct chan_freq_power *libertas_get_region_cfp_table(u8 region,
+						     u8 band, int *cfp_no);
+
+/** 
+ *  @brief This function convert Region string to code integer
+ *  @param region     region string
+ *  @return 	      region id
+*/
+static u8 wlan_region_2_code(s8 * region)
+{
+	u8 i;
+	u8 size = sizeof(region_code_mapping)/
+		  sizeof(struct region_code_mapping);
+
+	for (i = 0; region[i] && i < COUNTRY_CODE_LEN; i++)
+		region[i] = toupper(region[i]);
+
+	for (i = 0; i < size; i++) {
+		if (!memcmp(region, region_code_mapping[i].region,
+			    COUNTRY_CODE_LEN))
+			return (region_code_mapping[i].code);
+	}
+
+	/* default is US */
+	return (region_code_mapping[0].code);
+}
+
+/** 
+ *  @brief This function converts interger code to region string
+ *  @param code       region code
+ *  @return 	      region string
+*/
+static u8 *wlan_code_2_region(u8 code)
+{
+	u8 i;
+	u8 size = sizeof(region_code_mapping)
+		  / sizeof(struct region_code_mapping);
+	for (i = 0; i < size; i++) {
+		if (region_code_mapping[i].code == code)
+			return (region_code_mapping[i].region);
+	}
+	/* default is US */
+	return (region_code_mapping[0].region);
+}
+
+/** 
+ *  @brief This function finds the NoOfChan-th chan after the firstChan
+ *  @param band       band
+ *  @param firstChan  first channel number
+ *  @param NoOfChan   number of channels
+ *  @return 	      the NoOfChan-th chan number
+*/
+static u8 wlan_get_chan_11d(u8 band, u8 firstChan, u8 NoOfChan, u8 * chan)
+/*find the NoOfChan-th chan after the firstChan*/
+{
+	u8 i;
+	struct chan_freq_power *cfp;
+	u8 cfp_no;
+
+	ENTER();
+
+	{
+		cfp = channel_freq_power_UN_BG;
+		cfp_no = sizeof(channel_freq_power_UN_BG) /
+		    sizeof(struct chan_freq_power);
+	}
+
+	for (i = 0; i < cfp_no; i++) {
+		if ((cfp + i)->Channel == firstChan) {
+			PRINTM(INFO, "firstChan found\n");
+			break;
+		}
+	}
+
+	if (i < cfp_no) {
+		/*if beyond the boundary */
+		if (i + NoOfChan < cfp_no) {
+			*chan = (cfp + i + NoOfChan)->Channel;
+			return 1;
+		}
+	}
+
+	LEAVE();
+	return 0;
+}
+
+/** 
+ *  @brief This function Checks if chan txpwr is learned from AP/IBSS
+ *  @param chan                 chan number
+ *  @param parsed_region_chan   pointer to parsed_region_chan_11d
+ *  @return 	                TRUE; FALSE
+*/
+static u8 wlan_channel_known_11d(u8 chan,
+			  struct parsed_region_chan_11d * parsed_region_chan)
+{
+	struct chan_power_11d *chanPwr = parsed_region_chan->chanPwr;
+	u8 NoOfChan = parsed_region_chan->NoOfChan;
+	u8 i = 0;
+
+	ENTER();
+	HEXDUMP("11D:parsed_region_chan:", (char *)chanPwr,
+		sizeof(struct chan_power_11d) * NoOfChan);
+
+	for (i = 0; i < NoOfChan; i++) {
+		if (chan == chanPwr[i].chan) {
+			PRINTM(INFO, "11D: Found Chan:%d\n", chan);
+			LEAVE();
+			return 1;
+		}
+	}
+
+	PRINTM(INFO, "11D: Not Find Chan:%d\n", chan);
+	LEAVE();
+	return 0;
+}
+
+/** 
+ *  @brief This function Converts chan to frequency
+ *  @param chan                 channel number
+ *  @param band                 band
+ *  @return 	                channel frequency
+*/
+u32 libertas_chan_2_freq(u8 chan, u8 band)
+{
+	struct chan_freq_power *cf;
+	u16 cnt;
+	u16 i;
+	u32 freq = 0;
+
+	ENTER();
+
+	{
+		cf = channel_freq_power_UN_BG;
+		cnt =
+		    sizeof(channel_freq_power_UN_BG) /
+		    sizeof(struct chan_freq_power);
+	}
+
+	for (i = 0; i < cnt; i++) {
+		if (chan == cf[i].Channel)
+			freq = cf[i].Freq;
+	}
+
+	LEAVE();
+	return freq;
+}
+
+/** 
+ *  @brief This function generates domaininfo from parsed_region_chan
+ *  @param parsed_region_chan   pointer to parsed_region_chan_11d
+ *  @param domaininfo           pointer to wlan_802_11d_domain_reg
+ *  @return 	                WLAN_STATUS_SUCCESS
+*/
+static int wlan_generate_domain_info_11d(struct parsed_region_chan_11d
+				  *parsed_region_chan,
+				  struct wlan_802_11d_domain_reg * domaininfo)
+{
+	u8 NoOfSubband = 0;
+
+	u8 NoOfChan = parsed_region_chan->NoOfChan;
+	u8 NoOfParsedChan = 0;
+
+	u8 firstChan = 0, nextChan = 0, maxPwr = 0;
+
+	u8 i, flag = 0;
+
+	ENTER();
+
+	memcpy(domaininfo->CountryCode, parsed_region_chan->CountryCode,
+	       COUNTRY_CODE_LEN);
+
+	PRINTM(INFO, "11D:NoOfChan=%d\n", NoOfChan);
+	HEXDUMP("11D:parsed_region_chan:", (char *)parsed_region_chan,
+		sizeof(struct parsed_region_chan_11d));
+
+	for (i = 0; i < NoOfChan; i++) {
+		if (!flag) {
+			flag = 1;
+			nextChan = firstChan =
+			    parsed_region_chan->chanPwr[i].chan;
+			maxPwr = parsed_region_chan->chanPwr[i].pwr;
+			NoOfParsedChan = 1;
+			continue;
+		}
+
+		if (parsed_region_chan->chanPwr[i].chan == nextChan + 1 &&
+		    parsed_region_chan->chanPwr[i].pwr == maxPwr) {
+			nextChan++;
+			NoOfParsedChan++;
+		} else {
+			domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
+			domaininfo->Subband[NoOfSubband].NoOfChan =
+			    NoOfParsedChan;
+			domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
+			NoOfSubband++;
+			nextChan = firstChan =
+			    parsed_region_chan->chanPwr[i].chan;
+			maxPwr = parsed_region_chan->chanPwr[i].pwr;
+		}
+	}
+
+	if (flag) {
+		domaininfo->Subband[NoOfSubband].FirstChan = firstChan;
+		domaininfo->Subband[NoOfSubband].NoOfChan = NoOfParsedChan;
+		domaininfo->Subband[NoOfSubband].MaxTxPwr = maxPwr;
+		NoOfSubband++;
+	}
+	domaininfo->NoOfSubband = NoOfSubband;
+
+	PRINTM(INFO, "NoOfSubband=%x\n", domaininfo->NoOfSubband);
+	HEXDUMP("11D:domaininfo:", (char *)domaininfo,
+		COUNTRY_CODE_LEN + 1 +
+		sizeof(struct IEEEtypes_SubbandSet) * NoOfSubband);
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS
+ *  @param region_chan          pointer to struct region_channel
+ *  @param *parsed_region_chan  pointer to parsed_region_chan_11d
+ *  @return 	                N/A
+*/
+static void wlan_generate_parsed_region_chan_11d(struct region_channel * region_chan,
+					  struct parsed_region_chan_11d *
+					  parsed_region_chan)
+{
+	u8 i;
+	struct chan_freq_power *cfp;
+
+	ENTER();
+
+	if (region_chan == NULL) {
+		PRINTM(INFO, "11D: region_chan is NULL\n");
+		return;
+	}
+
+	cfp = region_chan->CFP;
+	if (cfp == NULL) {
+		PRINTM(INFO, "11D: cfp equal NULL \n");
+		return;
+	}
+
+	parsed_region_chan->band = region_chan->Band;
+	parsed_region_chan->region = region_chan->Region;
+	memcpy(parsed_region_chan->CountryCode,
+	       wlan_code_2_region(region_chan->Region), COUNTRY_CODE_LEN);
+
+	PRINTM(INFO, "11D: region[0x%x] band[%d]\n", parsed_region_chan->region,
+	       parsed_region_chan->band);
+
+	for (i = 0; i < region_chan->NrCFP; i++, cfp++) {
+		parsed_region_chan->chanPwr[i].chan = cfp->Channel;
+		parsed_region_chan->chanPwr[i].pwr = cfp->MaxTxPower;
+		PRINTM(INFO, "11D: Chan[%d] Pwr[%d]\n",
+		       parsed_region_chan->chanPwr[i].chan,
+		       parsed_region_chan->chanPwr[i].pwr);
+	}
+	parsed_region_chan->NoOfChan = region_chan->NrCFP;
+
+	PRINTM(INFO, "11D: NoOfChan[%d]\n", parsed_region_chan->NoOfChan);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief generate parsed_region_chan from Domain Info learned from AP/IBSS
+ *  @param region               region ID
+ *  @param band                 band
+ *  @param chan                 chan
+ *  @return 	                TRUE;FALSE
+*/
+static u8 wlan_region_chan_supported_11d(u8 region, u8 band, u8 chan)
+{
+	struct chan_freq_power *cfp;
+	int cfp_no;
+	u8 idx;
+
+	ENTER();
+
+	if ((cfp = libertas_get_region_cfp_table(region, band, &cfp_no)) == NULL) {
+		return 0;
+	}
+
+	for (idx = 0; idx < cfp_no; idx++) {
+		if (chan == (cfp + idx)->Channel) {
+			/* If Mrvl Chip Supported? */
+			if ((cfp + idx)->Unsupported) {
+				return 0;
+			} else {
+				return 1;
+			}
+		}
+	}
+
+	/*chan is not in the region table */
+	LEAVE();
+	return 0;
+}
+
+/** 
+ *  @brief This function checks if chan txpwr is learned from AP/IBSS
+ *  @param chan                 chan number
+ *  @param parsed_region_chan   pointer to parsed_region_chan_11d
+ *  @return 	                WLAN_STATUS_SUCCESS       
+*/
+static int wlan_parse_domain_info_11d(struct IEEEtypes_CountryInfoFullSet* CountryInfo,
+			       u8 band,
+			       struct parsed_region_chan_11d *
+			       parsed_region_chan)
+{
+	u8 NoOfSubband, NoOfChan;
+	u8 lastChan, firstChan;
+	u8 region;
+	u8 curChan = 0;
+
+	u8 idx = 0;		/*chan index in parsed_region_chan */
+
+	u8 j, i;
+
+	ENTER();
+
+	/*Validation Rules:
+	   1. Valid Region Code
+	   2. First Chan increment
+	   3. Channel range no overlap
+	   4. Channel is valid?
+	   5. Channel is supported by Region?
+	   6. Others
+	 */
+
+	HEXDUMP("CountryInfo:", (s8 *) CountryInfo, 30);
+
+	if ((*(CountryInfo->CountryCode)) == 0
+	    || (CountryInfo->Len <= COUNTRY_CODE_LEN)) {
+		/* No region Info or Wrong region info: treat as No 11D info */
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	/*Step1: check region_code */
+	parsed_region_chan->region = region =
+	    wlan_region_2_code(CountryInfo->CountryCode);
+
+	PRINTM(INFO, "regioncode=%x\n", (u8) parsed_region_chan->region);
+	HEXDUMP("CountryCode:", (char *)CountryInfo->CountryCode,
+		COUNTRY_CODE_LEN);
+
+	parsed_region_chan->band = band;
+
+	memcpy(parsed_region_chan->CountryCode, CountryInfo->CountryCode,
+	       COUNTRY_CODE_LEN);
+
+	NoOfSubband = (CountryInfo->Len - COUNTRY_CODE_LEN) /
+	    sizeof(struct IEEEtypes_SubbandSet);
+
+	for (j = 0, lastChan = 0; j < NoOfSubband; j++) {
+
+		if (CountryInfo->Subband[j].FirstChan <= lastChan) {
+			/*Step2&3. Check First Chan Num increment and no overlap */
+			PRINTM(INFO, "11D: Chan[%d>%d] Overlap\n",
+			       CountryInfo->Subband[j].FirstChan, lastChan);
+			continue;
+		}
+
+		firstChan = CountryInfo->Subband[j].FirstChan;
+		NoOfChan = CountryInfo->Subband[j].NoOfChan;
+
+		for (i = 0; idx < MAX_NO_OF_CHAN && i < NoOfChan; i++) {
+			/*step4: channel is supported? */
+
+			if (!wlan_get_chan_11d(band, firstChan, i, &curChan)) {
+				/* Chan is not found in UN table */
+				PRINTM(INFO, "chan is not supported: %d \n", i);
+				break;
+			}
+
+			lastChan = curChan;
+
+			if (wlan_region_chan_supported_11d
+			    (region, band, curChan)) {
+				/*step5: Check if curChan is supported by mrvl in region */
+				parsed_region_chan->chanPwr[idx].chan = curChan;
+				parsed_region_chan->chanPwr[idx].pwr =
+				    CountryInfo->Subband[j].MaxTxPwr;
+				idx++;
+			} else {
+				/*not supported and ignore the chan */
+				PRINTM(INFO,
+				       "11D:i[%d] chan[%d] unsupported in region[%x] band[%d]\n",
+				       i, curChan, region, band);
+			}
+		}
+
+		/*Step6: Add other checking if any */
+
+	}
+
+	parsed_region_chan->NoOfChan = idx;
+
+	PRINTM(INFO, "NoOfChan=%x\n", parsed_region_chan->NoOfChan);
+	HEXDUMP("11D:parsed_region_chan:", (s8 *) parsed_region_chan,
+		2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function calculates the scan type for channels
+ *  @param chan                 chan number
+ *  @param parsed_region_chan   pointer to parsed_region_chan_11d
+ *  @return 	                PASSIVE if chan is unknown; ACTIVE if chan is known
+*/
+u8 libertas_get_scan_type_11d(u8 chan,
+			  struct parsed_region_chan_11d * parsed_region_chan)
+{
+	u8 scan_type = HostCmd_SCAN_TYPE_PASSIVE;
+
+	ENTER();
+
+	if (wlan_channel_known_11d(chan, parsed_region_chan)) {
+		PRINTM(INFO, "11D: Found and do Active Scan\n");
+		scan_type = HostCmd_SCAN_TYPE_ACTIVE;
+	} else {
+		PRINTM(INFO, "11D: Not Find and do Passive Scan\n");
+	}
+
+	LEAVE();
+	return scan_type;
+
+}
+
+/** 
+ *  @brief This function gets if 11D is enabled
+ *  @param priv       pointer to wlan_private
+ *  @return 	      ENABLE_11D;DISABLE_11D
+*/
+enum state_11d libertas_get_state_11d(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct wlan_802_11d_state *state = &Adapter->State11D;
+	return (state->Enable11D);
+}
+
+/** 
+ *  @brief initialize internal variable for 11D
+ *  @param priv       pointer to wlan_private
+ *  @return 	      N/A
+*/
+void libertas_init_11d(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct wlan_802_11d_state *state = &Adapter->State11D;
+
+	state->Enable11D = DISABLE_11D;
+
+	memset(&(priv->adapter->parsed_region_chan), 0,
+	       sizeof(struct parsed_region_chan_11d));
+
+	return;
+}
+
+/** 
+ *  @brief This function enable/disable 11D
+ *  @param priv       pointer to wlan_private
+ *  @param flag       enable/disable flag
+ *  @return 	      WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
+*/
+static int wlan_enable_11d(wlan_private * priv, enum state_11d flag)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct wlan_802_11d_state *state = &Adapter->State11D;
+	int ret;
+	enum state_11d enable = flag;
+
+	ENTER();
+
+	state->Enable11D = flag;
+
+	/* send cmd to FW to enable/disable 11D fucntion in FW */
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_SET,
+				    HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11D_ENABLE, &enable);
+	if (ret) {
+		PRINTM(INFO, "11D: Fail to enable 11D \n");
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function sets DOMAIN INFO to FW
+ *  @param priv       pointer to wlan_private
+ *  @return 	      WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
+*/
+static int wlan_set_domain_info_11d(wlan_private * priv)
+{
+	int ret;
+
+	if (!libertas_get_state_11d(priv)) {
+		PRINTM(INFO, "11D: dnld domain Info with 11d disabled\n");
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11D_DOMAIN_INFO,
+				    HostCmd_ACT_GEN_SET,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	if (ret) {
+		PRINTM(INFO, "11D: Fail to dnld domain Info\n");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function setups scan channels
+ *  @param priv       pointer to wlan_private
+ *  @param band       band
+ *  @return 	      WLAN_STATUS_SUCCESS
+*/
+int libertas_set_universaltable(wlan_private * priv, u8 band)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	u16 size = sizeof(struct chan_freq_power);
+	u16 i = 0;
+
+	ENTER();
+
+	memset(Adapter->universal_channel, 0,
+	       sizeof(Adapter->universal_channel));
+
+	{
+		Adapter->universal_channel[i].NrCFP =
+		    sizeof(channel_freq_power_UN_BG) / size;
+		PRINTM(INFO, "11D: BG-band NrCFP=%d\n",
+		       Adapter->universal_channel[i].NrCFP);
+
+		Adapter->universal_channel[i].CFP = channel_freq_power_UN_BG;
+		Adapter->universal_channel[i].Valid = 1;
+		Adapter->universal_channel[i].Region = UNIVERSAL_REGION_CODE;
+		Adapter->universal_channel[i].Band = band;
+		i++;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function implements command CMD_802_11D_DOMAIN_INFO
+ *  @param priv       pointer to wlan_private
+ *  @param cmd        pointer to cmd buffer
+ *  @param cmdno      cmd ID
+ *  @param CmdOption  cmd action 
+ *  @return 	      WLAN_STATUS_SUCCESS
+*/
+int libertas_cmd_802_11d_domain_info(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *cmd, u16 cmdno,
+				 u16 CmdOption)
+{
+	struct HostCmd_DS_802_11D_DOMAIN_INFO *pDomainInfo =
+	    &cmd->params.domaininfo;
+	struct MrvlIEtypes_DomainParamSet *domain = &pDomainInfo->Domain;
+	wlan_adapter *Adapter = priv->adapter;
+	u8 NoOfSubband = Adapter->DomainReg.NoOfSubband;
+
+	ENTER();
+
+	PRINTM(INFO, "NoOfSubband=%x\n", NoOfSubband);
+
+	cmd->Command = wlan_cpu_to_le16(cmdno);
+	pDomainInfo->Action = wlan_cpu_to_le16(CmdOption);
+	if (CmdOption == HostCmd_ACT_GET) {
+		cmd->Size =
+		    wlan_cpu_to_le16(sizeof(pDomainInfo->Action) + S_DS_GEN);
+		HEXDUMP("11D: 802_11D_DOMAIN_INFO:", (u8 *) cmd,
+			(int)(cmd->Size));
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	domain->Header.Type = wlan_cpu_to_le16(TLV_TYPE_DOMAIN);
+	memcpy(domain->CountryCode, Adapter->DomainReg.CountryCode,
+	       sizeof(domain->CountryCode));
+
+	domain->Header.Len =
+	    wlan_cpu_to_le16(NoOfSubband * sizeof(struct IEEEtypes_SubbandSet) +
+			     sizeof(domain->CountryCode));
+
+	if (NoOfSubband) {
+		memcpy(domain->Subband, Adapter->DomainReg.Subband,
+		       NoOfSubband * sizeof(struct IEEEtypes_SubbandSet));
+
+		cmd->Size = wlan_cpu_to_le16(sizeof(pDomainInfo->Action) +
+					     domain->Header.Len +
+					     sizeof(struct MrvlIEtypesHeader) +
+					     S_DS_GEN);
+	} else {
+		cmd->Size =
+		    wlan_cpu_to_le16(sizeof(pDomainInfo->Action) + S_DS_GEN);
+	}
+
+	HEXDUMP("11D:802_11D_DOMAIN_INFO:", (u8 *) cmd, (int)(cmd->Size));
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function implements private cmd: enable/disable 11D
+ *  @param priv    pointer to wlan_private
+ *  @param wrq     pointer to user data 
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq)
+{
+	int data = 0;
+	int *val;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	data = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+
+	PRINTM(INFO, "Enable 11D: %s\n",
+	       (data == CMD_ENABLED) ? "Enable" : "Disable");
+	switch (data) {
+	case CMD_ENABLED:
+		wlan_enable_11d(priv, ENABLE_11D);
+		break;
+	case CMD_DISABLED:
+		wlan_enable_11d(priv, DISABLE_11D);
+		break;
+	default:
+		break;
+	}
+
+	data =
+	    (Adapter->State11D.Enable11D ==
+	     ENABLE_11D) ? CMD_ENABLED : CMD_DISABLED;
+	val = (int *)wrq->u.name;
+	*val = data;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function parses countryinfo from AP and download country info to FW
+ *  @param priv    pointer to wlan_private
+ *  @param resp    pointer to command response buffer
+ *  @return 	   WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
+ */
+int libertas_ret_802_11d_domain_info(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11D_DOMAIN_INFO_RSP
+	*domaininfo = &resp->params.domaininforesp;
+	struct MrvlIEtypes_DomainParamSet *domain = &domaininfo->Domain;
+	u16 Action = wlan_le16_to_cpu(domaininfo->Action);
+	s16 ret = WLAN_STATUS_SUCCESS;
+	u8 NoOfSubband = 0;
+
+	ENTER();
+
+	HEXDUMP("11D DOMAIN Info Rsp Data:", (u8 *) resp,
+		(int)wlan_le16_to_cpu(resp->Size));
+
+	NoOfSubband = (domain->Header.Len - 3) / sizeof(struct IEEEtypes_SubbandSet);
+	/* countrycode 3 bytes */
+
+	PRINTM(INFO, "11D Domain Info Resp: NoOfSubband=%d\n", NoOfSubband);
+
+	if (NoOfSubband > MRVDRV_MAX_SUBBAND_802_11D) {
+		PRINTM(INFO, "Invalid Numrer of Subband returned!!\n");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	switch (Action) {
+	case HostCmd_ACT_SET:	/*Proc Set Action */
+		break;
+
+	case HostCmd_ACT_GET:
+		break;
+	default:
+		PRINTM(INFO, "Invalid Action:%d\n", domaininfo->Action);
+		ret = WLAN_STATUS_FAILURE;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function parses countryinfo from AP and download country info to FW
+ *  @param priv    pointer to wlan_private
+ *  @return 	   WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
+ */
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv)
+{
+	int ret;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+	if (libertas_get_state_11d(priv) == ENABLE_11D) {
+
+		memset(&Adapter->parsed_region_chan, 0,
+		       sizeof(struct parsed_region_chan_11d));
+
+		ret =
+		    wlan_parse_domain_info_11d(&Adapter->pAttemptedBSSDesc->
+					       CountryInfo, 0,
+					       &Adapter->parsed_region_chan);
+
+		if (ret == WLAN_STATUS_FAILURE) {
+			PRINTM(INFO, "11D: Err Parse domain_info from AP..\n");
+			LEAVE();
+			return ret;
+		}
+
+		memset(&Adapter->DomainReg, 0,
+		       sizeof(struct wlan_802_11d_domain_reg));
+		wlan_generate_domain_info_11d(&Adapter->parsed_region_chan,
+					      &Adapter->DomainReg);
+
+		ret = wlan_set_domain_info_11d(priv);
+
+		if (ret) {
+			PRINTM(INFO, "11D: Err set domainInfo to FW\n");
+			LEAVE();
+			return ret;
+		}
+	}
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function generates 11D info from user specified regioncode and download to FW
+ *  @param priv    pointer to wlan_private
+ *  @return 	   WLAN_STATUS_SUCCESS; WLAN_STATUS_FAILURE
+ */
+int libertas_create_dnld_countryinfo_11d(wlan_private * priv)
+{
+	int ret;
+	wlan_adapter *Adapter = priv->adapter;
+	struct region_channel *region_chan;
+	u8 j;
+
+	ENTER();
+	PRINTM(INFO, "11D:CurBssParams.Band[%d]\n", Adapter->CurBssParams.band);
+
+	if (libertas_get_state_11d(priv) == ENABLE_11D) {
+		/* update parsed_region_chan_11; dnld domaininf to FW */
+
+		for (j = 0; j < sizeof(Adapter->region_channel) /
+		     sizeof(Adapter->region_channel[0]); j++) {
+			region_chan = &Adapter->region_channel[j];
+
+			PRINTM(INFO, "11D:[%d] region_chan->Band[%d]\n", j,
+			       region_chan->Band);
+
+			if (!region_chan || !region_chan->Valid
+			    || !region_chan->CFP)
+				continue;
+			if (region_chan->Band != Adapter->CurBssParams.band)
+				continue;
+			break;
+		}
+
+		if (j >= sizeof(Adapter->region_channel) /
+		    sizeof(Adapter->region_channel[0])) {
+			PRINTM(INFO, "11D:region_chan not found. Band[%d]\n",
+			       Adapter->CurBssParams.band);
+			LEAVE();
+			return WLAN_STATUS_FAILURE;
+		}
+
+		memset(&Adapter->parsed_region_chan, 0,
+		       sizeof(struct parsed_region_chan_11d));
+		wlan_generate_parsed_region_chan_11d(region_chan,
+						     &Adapter->
+						     parsed_region_chan);
+
+		memset(&Adapter->DomainReg, 0,
+		       sizeof(struct wlan_802_11d_domain_reg));
+		wlan_generate_domain_info_11d(&Adapter->parsed_region_chan,
+					      &Adapter->DomainReg);
+
+		ret = wlan_set_domain_info_11d(priv);
+
+		if (ret) {
+			PRINTM(INFO, "11D: Err set domainInfo to FW\n");
+			LEAVE();
+			return ret;
+		}
+
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_11d.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_11d.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_11d.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_11d.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,160 @@
+/** @file wlan_11d.h
+  * @brief This header file contains data structures and 
+  * function declarations of 802.11d   
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change log:
+	09/26/05: add Doxygen format comments 
+ ************************************************************/
+
+#ifndef _WLAN_11D_
+#define _WLAN_11D_
+
+#include "wlan_types.h"
+#include "wlan_defs.h"
+
+#define MAX_CHAN_NUM				255
+
+#define UNIVERSAL_REGION_CODE			0xff
+
+/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) 
+ */
+#define MRVDRV_MAX_SUBBAND_802_11D		83
+
+#define COUNTRY_CODE_LEN			3
+#define MAX_NO_OF_CHAN 				40
+
+struct HostCmd_DS_COMMAND;
+
+enum state_11d {
+	DISABLE_11D,
+	ENABLE_11D,
+};
+
+/** Data structure for Country IE*/
+struct IEEEtypes_SubbandSet {
+	u8 FirstChan;
+	u8 NoOfChan;
+	u8 MaxTxPwr;
+} __attribute__ ((packed));
+
+struct IEEEtypes_CountryInfoSet {
+	u8 ElementId;
+	u8 Len;
+	u8 CountryCode[COUNTRY_CODE_LEN];
+	struct IEEEtypes_SubbandSet Subband[1];
+};
+
+struct IEEEtypes_CountryInfoFullSet {
+	u8 ElementId;
+	u8 Len;
+	u8 CountryCode[COUNTRY_CODE_LEN];
+	struct IEEEtypes_SubbandSet Subband[MRVDRV_MAX_SUBBAND_802_11D];
+} __attribute__ ((packed));
+
+struct MrvlIEtypes_DomainParamSet {
+	struct MrvlIEtypesHeader Header;
+	u8 CountryCode[COUNTRY_CODE_LEN];
+	struct IEEEtypes_SubbandSet Subband[1];
+} __attribute__ ((packed));
+
+/** Define data structure for HostCmd_CMD_802_11D_DOMAIN_INFO */
+struct HostCmd_DS_802_11D_DOMAIN_INFO {
+	u16 Action;
+	struct MrvlIEtypes_DomainParamSet Domain;
+} __attribute__ ((packed));
+
+/** Define data structure for HostCmd_RET_802_11D_DOMAIN_INFO */
+struct HostCmd_DS_802_11D_DOMAIN_INFO_RSP {
+	u16 Action;
+	struct MrvlIEtypes_DomainParamSet Domain;
+} __attribute__ ((packed));
+
+/** domain regulatory information */
+struct wlan_802_11d_domain_reg {
+	/** country Code*/
+	u8 CountryCode[COUNTRY_CODE_LEN];
+	/** No. of subband*/
+	u8 NoOfSubband;
+	struct IEEEtypes_SubbandSet Subband[MRVDRV_MAX_SUBBAND_802_11D];
+};
+
+struct chan_power_11d {
+	u8 chan;
+	u8 pwr;
+} __attribute__ ((packed));
+
+struct parsed_region_chan_11d {
+	u8 band;
+	u8 region;
+	s8 CountryCode[COUNTRY_CODE_LEN];
+	struct chan_power_11d chanPwr[MAX_NO_OF_CHAN];
+	u8 NoOfChan;
+} __attribute__ ((packed));
+
+/** Data for state machine */
+struct wlan_802_11d_state {
+	/** True for Enabling  11D*/
+	u8 Enable11D;
+};
+
+struct region_code_mapping {
+	s8 region[COUNTRY_CODE_LEN];
+	u8 code;
+};
+
+#if 0
+/* function prototypes*/
+int wlan_generate_domain_info_11d(struct parsed_region_chan_11d
+				  *parsed_region_chan,
+				  struct wlan_802_11d_domain_reg * domaininfo);
+
+int wlan_parse_domain_info_11d(struct IEEEtypes_CountryInfoFullSet* CountryInfo,
+			       u8 band,
+			       struct parsed_region_chan_11d 
+				*parsed_region_chan);
+#endif
+
+u8 libertas_get_scan_type_11d(u8 chan,
+			  struct parsed_region_chan_11d *parsed_region_chan);
+
+u32 libertas_chan_2_freq(u8 chan, u8 band);
+
+enum state_11d libertas_get_state_11d(wlan_private * priv);
+
+void libertas_init_11d(wlan_private * priv);
+
+int libertas_set_universaltable(wlan_private * priv, u8 band);
+
+int libertas_cmd_802_11d_domain_info(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *cmd, u16 cmdno,
+				 u16 CmdOption);
+
+struct iwreq;
+int libertas_cmd_enable_11d(wlan_private * priv, struct iwreq *wrq);
+
+int libertas_ret_802_11d_domain_info(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp);
+
+int libertas_parse_dnld_countryinfo_11d(wlan_private * priv);
+
+int libertas_create_dnld_countryinfo_11d(wlan_private * priv);
+
+#endif				/* _WLAN_11D_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_cmd.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_cmd.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_cmd.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_cmd.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,2282 @@
+/** @file wlan_cmd.c
+  *  
+  * @brief This file contains the handling of command.
+  * it prepares command and sends it to firmware when
+  * it is ready.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+    10/04/05: Add Doxygen format comments
+    01/05/06: Add kernel 2.6.x support  
+    01/11/06: Change compile flag BULVERDE_SDIO to SD to support
+              Monahans/Zylonite
+    01/11/06: Conditionalize new scan/join structures
+    01/31/06: Add support to selectively enabe the FW Scan channel filter
+    02/16/06: Clear scan in progress flag when scan command failed and dropped
+    04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+    04/18/06: Remove old Subscrive Event and add new Subscribe Event
+	      implementation through generic hostcmd API
+********************************************************/
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "hostcmd.h"
+#include "sbi.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+#include "wlan_join.h"
+#include "wlan_wext.h"
+
+static void CleanUpCmdCtrlNode(struct CmdCtrlNode *pTempNode);
+
+static u16 Commands_Allowed_In_PS[] = {
+	HostCmd_CMD_802_11_RSSI,
+};
+
+/** 
+ *  @brief This function checks if the commans is allowed
+ *  in PS mode not.
+ *  
+ *  @param Command the command ID
+ *  @return 	   TRUE or FALSE
+ */
+static u8 Is_Command_Allowed_In_PS(u16 Command)
+{
+	int count = sizeof(Commands_Allowed_In_PS)
+	    / sizeof(Commands_Allowed_In_PS[0]);
+	int i;
+
+	for (i = 0; i < count; i++) {
+		if (Command == wlan_cpu_to_le16(Commands_Allowed_In_PS[i]))
+			return 1;
+	}
+
+	return 0;
+}
+
+/** 
+ *  @brief This function prepares command of get_hw_spec.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param cmd	   A pointer to HostCmd_DS_COMMAND structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_hw_spec(wlan_private * priv, struct HostCmd_DS_COMMAND *cmd)
+{
+	struct HostCmd_DS_GET_HW_SPEC *hwspec = &cmd->params.hwspec;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_HW_SPEC);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_GET_HW_SPEC) + S_DS_GEN);
+	memcpy(hwspec->PermanentAddr, priv->adapter->CurrentAddr, ETH_ALEN);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of ps_mode.
+ *  
+ *  @param priv    	A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 	the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_ps_mode(wlan_private * priv,
+				   struct HostCmd_DS_COMMAND *cmd,
+				   u16 cmd_action)
+{
+	struct HostCmd_DS_802_11_PS_MODE *psm = &cmd->params.psmode;
+	u16 Action = cmd_action;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_PS_MODE) +
+			     S_DS_GEN);
+	psm->Action = wlan_cpu_to_le16(cmd_action);
+	psm->MultipleDtim = 0;
+	switch (Action) {
+	case HostCmd_SubCmd_Enter_PS:
+		PRINTM(INFO, "PS Command:" "SubCode- Enter PS\n");
+		PRINTM(INFO, "LocalListenInterval = %d\n",
+		       Adapter->LocalListenInterval);
+
+		psm->LocalListenInterval =
+		    wlan_cpu_to_le16(Adapter->LocalListenInterval);
+		psm->NullPktInterval =
+		    wlan_cpu_to_le16(Adapter->NullPktInterval);
+		psm->MultipleDtim =
+		    wlan_cpu_to_le16(priv->adapter->MultipleDtim);
+		break;
+
+	case HostCmd_SubCmd_Exit_PS:
+		PRINTM(INFO, "PS Command:" "SubCode- Exit PS\n");
+		break;
+
+	case HostCmd_SubCmd_Sleep_Confirmed:
+		PRINTM(INFO, "PS Command: SubCode- sleep confirm\n");
+		break;
+
+	default:
+		break;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of inactivity_timeout.
+ *  
+ *  @param priv    	A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   Action: GET SET
+ *  @param pdata_buf 	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_inactivity_timeout(wlan_private * priv,
+					      struct HostCmd_DS_COMMAND *cmd,
+					      u16 cmd_action, void *pdata_buf)
+{
+	u16 *timeout = (u16 *) pdata_buf;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_INACTIVITY_TIMEOUT);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_INACTIVITY_TIMEOUT)
+			     + S_DS_GEN);
+
+	cmd->params.inactivity_timeout.Action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action)
+		cmd->params.inactivity_timeout.Timeout =
+		    wlan_cpu_to_le16(*timeout);
+	else
+		cmd->params.inactivity_timeout.Timeout = 0;
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of sleep_period.
+ *  
+ *  @param priv    		A pointer to wlan_private structure
+ *  @param cmd	   		A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 		the action: GET or SET
+ *  @param pdata_buf		A pointer to data buffer
+ *  @return 	   		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_sleep_period(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *cmd,
+					u16 cmd_action, void *pdata_buf)
+{
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PERIOD);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_SLEEP_PERIOD) +
+			     S_DS_GEN);
+	memmove(&cmd->params.ps_sleeppd, pdata_buf,
+		sizeof(struct HostCmd_DS_802_11_SLEEP_PERIOD));
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of sleep_params.
+ *  
+ *  @param priv    		A pointer to wlan_private structure
+ *  @param cmd	   		A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 		the action: GET or SET
+ *  @return 	   		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_sleep_params(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *cmd,
+					u16 cmd_action)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_SLEEP_PARAMS *sp = &cmd->params.sleep_params;
+
+	ENTER();
+
+	cmd->Size =
+	    wlan_cpu_to_le16((sizeof(struct HostCmd_DS_802_11_SLEEP_PARAMS)) +
+			     S_DS_GEN);
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SLEEP_PARAMS);
+
+	if (cmd_action == HostCmd_ACT_GEN_GET) {
+		memset(&Adapter->sp, 0, sizeof(struct sleep_params));
+		memset(sp, 0, sizeof(struct HostCmd_DS_802_11_SLEEP_PARAMS));
+		sp->Action = wlan_cpu_to_le16(cmd_action);
+	} else if (cmd_action == HostCmd_ACT_GEN_SET) {
+		sp->Action = wlan_cpu_to_le16(cmd_action);
+		sp->Error = wlan_cpu_to_le16(Adapter->sp.sp_error);
+		sp->Offset = wlan_cpu_to_le16(Adapter->sp.sp_offset);
+		sp->StableTime = wlan_cpu_to_le16(Adapter->sp.sp_stabletime);
+		sp->CalControl = (u8) Adapter->sp.sp_calcontrol;
+		sp->ExternalSleepClk = (u8) Adapter->sp.sp_extsleepclk;
+		sp->Reserved = wlan_cpu_to_le16(Adapter->sp.sp_reserved);
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+#define WEP_40_BIT_LEN	5
+#define WEP_104_BIT_LEN	13
+
+/** 
+ *  @brief This function prepares command of set_wep.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_oid   OID: ADD_WEP KEY or REMOVE_WEP KEY
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_set_wep(wlan_private * priv,
+				   struct HostCmd_DS_COMMAND *cmd, u32 cmd_oid)
+{
+	struct HostCmd_DS_802_11_SET_WEP *wep = &cmd->params.wep;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (cmd_oid == OID_802_11_ADD_WEP) {
+		cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP);
+		cmd->Size =
+		    wlan_cpu_to_le16((sizeof(struct HostCmd_DS_802_11_SET_WEP))
+				     + S_DS_GEN);
+		wep->Action = wlan_cpu_to_le16(HostCmd_ACT_ADD);
+
+		/* default tx key index */
+		wep->KeyIndex = wlan_cpu_to_le16(Adapter->CurrentWepKeyIndex &
+						 HostCmd_WEP_KEY_INDEX_MASK);
+
+		PRINTM(INFO, "Tx Key Index: %u\n", wep->KeyIndex);
+
+		switch (Adapter->WepKey[0].KeyLength) {
+		case WEP_40_BIT_LEN:
+			wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_40_BIT;
+			memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial,
+				Adapter->WepKey[0].KeyLength);
+			break;
+		case WEP_104_BIT_LEN:
+			wep->WEPTypeForKey1 = HostCmd_TYPE_WEP_104_BIT;
+			memmove(wep->WEP1, Adapter->WepKey[0].KeyMaterial,
+				Adapter->WepKey[0].KeyLength);
+			break;
+		case 0:
+			break;
+		default:
+			PRINTM(INFO, "Key1 Length = %d is incorrect\n",
+			       Adapter->WepKey[0].KeyLength);
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		switch (Adapter->WepKey[1].KeyLength) {
+		case WEP_40_BIT_LEN:
+			wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_40_BIT;
+			memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial,
+				Adapter->WepKey[1].KeyLength);
+			break;
+		case WEP_104_BIT_LEN:
+			wep->WEPTypeForKey2 = HostCmd_TYPE_WEP_104_BIT;
+			memmove(wep->WEP2, Adapter->WepKey[1].KeyMaterial,
+				Adapter->WepKey[1].KeyLength);
+			break;
+		case 0:
+			break;
+		default:
+			PRINTM(INFO, "Key2 Length = %d is incorrect\n",
+			       Adapter->WepKey[1].KeyLength);
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		switch (Adapter->WepKey[2].KeyLength) {
+		case WEP_40_BIT_LEN:
+			wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_40_BIT;
+			memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial,
+				Adapter->WepKey[2].KeyLength);
+			break;
+		case WEP_104_BIT_LEN:
+			wep->WEPTypeForKey3 = HostCmd_TYPE_WEP_104_BIT;
+			memmove(wep->WEP3, Adapter->WepKey[2].KeyMaterial,
+				Adapter->WepKey[2].KeyLength);
+			break;
+		case 0:
+			break;
+		default:
+			PRINTM(INFO, "Key3 Length = %d is incorrect\n",
+			       Adapter->WepKey[2].KeyLength);
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		switch (Adapter->WepKey[3].KeyLength) {
+		case WEP_40_BIT_LEN:
+			wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_40_BIT;
+			memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial,
+				Adapter->WepKey[3].KeyLength);
+			break;
+		case WEP_104_BIT_LEN:
+			wep->WEPTypeForKey4 = HostCmd_TYPE_WEP_104_BIT;
+			memmove(wep->WEP4, Adapter->WepKey[3].KeyMaterial,
+				Adapter->WepKey[3].KeyLength);
+			break;
+		case 0:
+			break;
+		default:
+			PRINTM(INFO, "Key4 Length = %d is incorrect\n",
+			       Adapter->WepKey[3].KeyLength);
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+	} else if (cmd_oid == OID_802_11_REMOVE_WEP) {
+		cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SET_WEP);
+		cmd->Size =
+		    wlan_cpu_to_le16((sizeof(struct HostCmd_DS_802_11_SET_WEP))
+				     + S_DS_GEN);
+		wep->Action = wlan_cpu_to_le16(HostCmd_ACT_REMOVE);
+
+		/* default tx key index */
+		wep->KeyIndex =
+		    wlan_cpu_to_le16((u16)
+				     (Adapter->
+				      CurrentWepKeyIndex & (u32)
+				      HostCmd_WEP_KEY_INDEX_MASK));
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function prepares command of enable_rsn.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 	the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_enable_rsn(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *cmd,
+				      u16 cmd_action)
+{
+	struct HostCmd_DS_802_11_ENABLE_RSN *pEnableRSN = &cmd->params.enbrsn;
+	wlan_adapter *Adapter = priv->adapter;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ENABLE_RSN);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_ENABLE_RSN) +
+			     S_DS_GEN);
+	pEnableRSN->Action = wlan_cpu_to_le16(cmd_action);
+	if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled) {
+		pEnableRSN->Enable = wlan_cpu_to_le16(HostCmd_ENABLE_RSN);
+	} else {
+		pEnableRSN->Enable = wlan_cpu_to_le16(HostCmd_DISABLE_RSN);
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of key_material.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 	the action: GET or SET
+ *  @param cmd_oid	OID: ENABLE or DISABLE
+ *  @param pdata_buf    A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_key_material(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *cmd,
+					u16 cmd_action,
+					u32 cmd_oid, void *pdata_buf)
+{
+	struct HostCmd_DS_802_11_KEY_MATERIAL *pKeyMaterial =
+	    &cmd->params.keymaterial;
+	struct WLAN_802_11_KEY *pKey = (struct WLAN_802_11_KEY *)pdata_buf;
+	u16 KeyParamSet_len;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL);
+	pKeyMaterial->Action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_GET) {
+		cmd->Size = wlan_cpu_to_le16(2 + S_DS_GEN);
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	memset(&pKeyMaterial->KeyParamSet, 0,
+	       sizeof(struct MrvlIEtype_KeyParamSet));
+
+	if (pKey->KeyLength == WPA_AES_KEY_LEN) {
+		PRINTM(INFO, "WPA_AES\n");
+		pKeyMaterial->KeyParamSet.KeyTypeId =
+		    wlan_cpu_to_le16(KEY_TYPE_ID_AES);
+
+		if (cmd_oid == (u32) KEY_INFO_ENABLED)
+			pKeyMaterial->KeyParamSet.KeyInfo =
+			    wlan_cpu_to_le16(KEY_INFO_AES_ENABLED);
+		else
+			pKeyMaterial->KeyParamSet.KeyInfo =
+			    !(wlan_cpu_to_le16(KEY_INFO_AES_ENABLED));
+
+		if (pKey->KeyIndex & 0x40000000)	//AES pairwise key: unicast
+			pKeyMaterial->KeyParamSet.KeyInfo |=
+			    wlan_cpu_to_le16(KEY_INFO_AES_UNICAST);
+		else		//AES group key: multicast
+			pKeyMaterial->KeyParamSet.KeyInfo |=
+			    wlan_cpu_to_le16(KEY_INFO_AES_MCAST);
+	} else if (pKey->KeyLength == WPA_TKIP_KEY_LEN) {
+		PRINTM(INFO, "WPA_TKIP\n");
+		pKeyMaterial->KeyParamSet.KeyTypeId =
+		    wlan_cpu_to_le16(KEY_TYPE_ID_TKIP);
+		pKeyMaterial->KeyParamSet.KeyInfo =
+		    wlan_cpu_to_le16(KEY_INFO_TKIP_ENABLED);
+
+		if (pKey->KeyIndex & 0x40000000)	//TKIP pairwise key: unicast
+			pKeyMaterial->KeyParamSet.KeyInfo |=
+			    wlan_cpu_to_le16(KEY_INFO_TKIP_UNICAST);
+		else		//TKIP group key: multicast
+			pKeyMaterial->KeyParamSet.KeyInfo |=
+			    wlan_cpu_to_le16(KEY_INFO_TKIP_MCAST);
+	}
+
+	if (pKeyMaterial->KeyParamSet.KeyTypeId) {
+		pKeyMaterial->KeyParamSet.Type =
+		    wlan_cpu_to_le16(TLV_TYPE_KEY_MATERIAL);
+		pKeyMaterial->KeyParamSet.KeyLen =
+		    wlan_cpu_to_le16(pKey->KeyLength);
+		memcpy(pKeyMaterial->KeyParamSet.Key, pKey->KeyMaterial,
+		       pKey->KeyLength);
+		pKeyMaterial->KeyParamSet.Length =
+		    wlan_cpu_to_le16(pKey->KeyLength + 6);
+
+#define TYPE_LEN_FIELDS_LEN 4
+		KeyParamSet_len =
+		    pKeyMaterial->KeyParamSet.Length + TYPE_LEN_FIELDS_LEN;
+#define ACTION_FIELD_LEN 2
+		cmd->Size =
+		    wlan_cpu_to_le16(KeyParamSet_len + ACTION_FIELD_LEN +
+				     S_DS_GEN);
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function prepares command of reset.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action 	the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_reset(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *cmd, int cmd_action)
+{
+	struct HostCmd_DS_802_11_RESET *reset = &cmd->params.reset;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RESET);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_RESET) + S_DS_GEN);
+	reset->Action = wlan_cpu_to_le16(cmd_action);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of get_log.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_get_log(wlan_private * priv,
+				   struct HostCmd_DS_COMMAND *cmd)
+{
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_LOG);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_GET_LOG) +
+			     S_DS_GEN);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of get_stat.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_get_stat(wlan_private * priv,
+				    struct HostCmd_DS_COMMAND *cmd)
+{
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_GET_STAT);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_GET_STAT) +
+			     S_DS_GEN);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of snmp_mib.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param cmd_oid   	the OID of SNMP MIB
+ *  @param pdata_buf	the pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_snmp_mib(wlan_private * priv,
+				    struct HostCmd_DS_COMMAND *cmd,
+				    int cmd_action,
+				    int cmd_oid, void *pdata_buf)
+{
+	struct HostCmd_DS_802_11_SNMP_MIB *pSNMPMIB = &cmd->params.smib;
+	wlan_adapter *Adapter = priv->adapter;
+	u8 ucTemp;
+
+	ENTER();
+
+	PRINTM(INFO, "SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid);
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_SNMP_MIB) +
+			     S_DS_GEN);
+
+	switch (cmd_oid) {
+	case OID_802_11_INFRASTRUCTURE_MODE:
+		pSNMPMIB->QueryType = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+		pSNMPMIB->OID = wlan_cpu_to_le16((u16) DesiredBssType_i);
+		pSNMPMIB->BufSize = sizeof(u8);
+		if (Adapter->InfrastructureMode == Wlan802_11Infrastructure)
+			ucTemp = SNMP_MIB_VALUE_INFRA;
+		else
+			ucTemp = SNMP_MIB_VALUE_ADHOC;
+
+		memmove(pSNMPMIB->Value, &ucTemp, sizeof(u8));
+
+		break;
+
+	case OID_802_11D_ENABLE:
+		{
+			u32 ulTemp;
+
+			pSNMPMIB->OID = wlan_cpu_to_le16((u16) Dot11D_i);
+
+			if (cmd_action == HostCmd_ACT_SET) {
+				pSNMPMIB->QueryType = HostCmd_ACT_GEN_SET;
+				pSNMPMIB->BufSize = sizeof(u16);
+				ulTemp = *(u32 *) pdata_buf;
+				*((unsigned short *)(pSNMPMIB->Value)) =
+				    wlan_cpu_to_le16((u16) ulTemp);
+			}
+			break;
+		}
+
+	case OID_802_11_FRAGMENTATION_THRESHOLD:
+		{
+			u32 ulTemp;
+
+			pSNMPMIB->OID = wlan_cpu_to_le16((u16) FragThresh_i);
+
+			if (cmd_action == HostCmd_ACT_GET) {
+				pSNMPMIB->QueryType =
+				    wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+			} else if (cmd_action == HostCmd_ACT_SET) {
+				pSNMPMIB->QueryType =
+				    wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+				pSNMPMIB->BufSize =
+				    wlan_cpu_to_le16(sizeof(u16));
+				ulTemp = *((u32 *) pdata_buf);
+				*((unsigned short *)(pSNMPMIB->Value)) =
+				    wlan_cpu_to_le16((u16) ulTemp);
+
+			}
+
+			break;
+		}
+
+	case OID_802_11_RTS_THRESHOLD:
+		{
+
+			u32 ulTemp;
+			pSNMPMIB->OID = wlan_le16_to_cpu((u16) RtsThresh_i);
+
+			if (cmd_action == HostCmd_ACT_GET) {
+				pSNMPMIB->QueryType =
+				    wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+			} else if (cmd_action == HostCmd_ACT_SET) {
+				pSNMPMIB->QueryType =
+				    wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+				pSNMPMIB->BufSize =
+				    wlan_cpu_to_le16(sizeof(u16));
+				ulTemp = *((u32 *)
+					   pdata_buf);
+				*(unsigned short *)(pSNMPMIB->Value) =
+				    wlan_cpu_to_le16((u16) ulTemp);
+
+			}
+			break;
+		}
+	case OID_802_11_TX_RETRYCOUNT:
+		pSNMPMIB->OID = wlan_cpu_to_le16((u16) ShortRetryLim_i);
+
+		if (cmd_action == HostCmd_ACT_GET) {
+			pSNMPMIB->QueryType =
+			    wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+		} else if (cmd_action == HostCmd_ACT_SET) {
+			pSNMPMIB->QueryType =
+			    wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			pSNMPMIB->BufSize = wlan_cpu_to_le16(sizeof(u16));
+			*((unsigned short *)(pSNMPMIB->Value)) =
+			    wlan_cpu_to_le16((u16) Adapter->TxRetryCount);
+		}
+
+		break;
+	default:
+		break;
+	}
+
+	PRINTM(INFO,
+	       "SNMP_CMD: Command=0x%x, Size=0x%x, SeqNum=0x%x, Result=0x%x\n",
+	       cmd->Command, cmd->Size, cmd->SeqNum, cmd->Result);
+
+	PRINTM(INFO,
+	       "SNMP_CMD: Action=0x%x, OID=0x%x, OIDSize=0x%x, Value=0x%x\n",
+	       pSNMPMIB->QueryType, pSNMPMIB->OID, pSNMPMIB->BufSize,
+	       *(u16 *) pSNMPMIB->Value);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of radio_control.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_radio_control(wlan_private * priv,
+					 struct HostCmd_DS_COMMAND *cmd,
+					 int cmd_action)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_RADIO_CONTROL *pRadioControl =
+	    &cmd->params.radio;
+
+	ENTER();
+
+	cmd->Size =
+	    wlan_cpu_to_le16((sizeof(struct HostCmd_DS_802_11_RADIO_CONTROL)) +
+			     S_DS_GEN);
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RADIO_CONTROL);
+
+	pRadioControl->Action = wlan_cpu_to_le16(cmd_action);
+
+	switch (Adapter->Preamble) {
+	case HostCmd_TYPE_SHORT_PREAMBLE:
+		pRadioControl->Control = wlan_cpu_to_le16(SET_SHORT_PREAMBLE);
+		break;
+
+	case HostCmd_TYPE_LONG_PREAMBLE:
+		pRadioControl->Control = wlan_cpu_to_le16(SET_LONG_PREAMBLE);
+		break;
+
+	case HostCmd_TYPE_AUTO_PREAMBLE:
+	default:
+		pRadioControl->Control = wlan_cpu_to_le16(SET_AUTO_PREAMBLE);
+		break;
+	}
+
+	if (Adapter->RadioOn)
+		pRadioControl->Control |= wlan_cpu_to_le16(TURN_ON_RF);
+	else
+		pRadioControl->Control &= wlan_cpu_to_le16(~TURN_ON_RF);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rf_tx_power.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_rf_tx_power(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *cmd,
+				       u16 cmd_action, void *pdata_buf)
+{
+
+	struct HostCmd_DS_802_11_RF_TX_POWER *pRTP = &cmd->params.txp;
+
+	ENTER();
+
+	cmd->Size =
+	    wlan_cpu_to_le16((sizeof(struct HostCmd_DS_802_11_RF_TX_POWER)) +
+			     S_DS_GEN);
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_TX_POWER);
+	pRTP->Action = cmd_action;
+
+	PRINTM(INFO, "RF_TX_POWER_CMD: Size:%d Cmd:0x%x Act:%d\n", cmd->Size,
+	       cmd->Command, pRTP->Action);
+
+	switch (cmd_action) {
+	case HostCmd_ACT_TX_POWER_OPT_GET:
+		pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+		pRTP->CurrentLevel = 0;
+		break;
+
+	case HostCmd_ACT_TX_POWER_OPT_SET_HIGH:
+		pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+		pRTP->CurrentLevel =
+		    wlan_cpu_to_le16(HostCmd_ACT_TX_POWER_INDEX_HIGH);
+		break;
+
+	case HostCmd_ACT_TX_POWER_OPT_SET_MID:
+		pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+		pRTP->CurrentLevel =
+		    wlan_cpu_to_le16(HostCmd_ACT_TX_POWER_INDEX_MID);
+		break;
+
+	case HostCmd_ACT_TX_POWER_OPT_SET_LOW:
+		pRTP->Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+		pRTP->CurrentLevel = wlan_cpu_to_le16(*((u16 *) pdata_buf));
+		break;
+	}
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rf_antenna.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_rf_antenna(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *cmd,
+				      u16 cmd_action, void *pdata_buf)
+{
+	struct HostCmd_DS_802_11_RF_ANTENNA *rant = &cmd->params.rant;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_ANTENNA);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_RF_ANTENNA) +
+			     S_DS_GEN);
+
+	rant->Action = wlan_cpu_to_le16(cmd_action);
+	if ((cmd_action == HostCmd_ACT_SET_RX) ||
+	    (cmd_action == HostCmd_ACT_SET_TX)) {
+		rant->AntennaMode =
+		    wlan_cpu_to_le16((u16) (*(u32 *) pdata_buf));
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rate_adapt_rateset.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_rate_adapt_rateset(wlan_private * priv,
+					      struct HostCmd_DS_COMMAND *cmd,
+					      u16 cmd_action)
+{
+	struct HostCmd_DS_802_11_RATE_ADAPT_RATESET
+	*rateadapt = &cmd->params.rateset;
+	wlan_adapter *Adapter = priv->adapter;
+
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_RATE_ADAPT_RATESET)
+			     + S_DS_GEN);
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RATE_ADAPT_RATESET);
+
+	ENTER();
+
+	rateadapt->Action = cmd_action;
+	rateadapt->EnableHwAuto = Adapter->EnableHwAuto;
+	rateadapt->Bitmap = Adapter->RateBitmap;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rate_adapt_rateset.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_data_rate(wlan_private * priv,
+				     struct HostCmd_DS_COMMAND *cmd,
+				     u16 cmd_action)
+{
+	struct HostCmd_DS_802_11_DATA_RATE *pDataRate = &cmd->params.drate;
+	wlan_adapter *Adapter = priv->adapter;
+	u16 Action = cmd_action;
+
+	ENTER();
+
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_DATA_RATE) +
+			     S_DS_GEN);
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_DATA_RATE);
+
+	memset(pDataRate, 0, sizeof(struct HostCmd_DS_802_11_DATA_RATE));
+
+	pDataRate->Action = wlan_cpu_to_le16(cmd_action);
+
+	if (Action == HostCmd_ACT_SET_TX_FIX_RATE) {
+		pDataRate->DataRate[0] = libertas_data_rate_to_index(Adapter->DataRate);
+		PRINTM(INFO, "Setting FW for fixed rate 0x%02X\n",
+		       Adapter->DataRate);
+	} else if (Action == HostCmd_ACT_SET_TX_AUTO) {
+		PRINTM(INFO, "Setting FW for AUTO rate\n");
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of mac_multicast_adr.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_mac_multicast_adr(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *cmd,
+				      u16 cmd_action)
+{
+	struct HostCmd_DS_MAC_MULTICAST_ADR *pMCastAdr = &cmd->params.madr;
+	wlan_adapter *Adapter = priv->adapter;
+
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_MAC_MULTICAST_ADR) +
+			     S_DS_GEN);
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR);
+
+	pMCastAdr->Action = wlan_cpu_to_le16(cmd_action);
+	pMCastAdr->NumOfAdrs =
+	    wlan_cpu_to_le16((u16) Adapter->NumOfMulticastMACAddr);
+	memcpy(pMCastAdr->MACList, Adapter->MulticastList,
+	       Adapter->NumOfMulticastMACAddr * ETH_ALEN);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rf_channel.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_rf_channel(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *cmd,
+				      int option, void *pdata_buf)
+{
+	struct HostCmd_DS_802_11_RF_CHANNEL *rfchan = &cmd->params.rfchannel;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RF_CHANNEL);
+	cmd->Size = wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_RF_CHANNEL)
+				     + S_DS_GEN);
+
+	if (option == HostCmd_OPT_802_11_RF_CHANNEL_SET) {
+		rfchan->CurrentChannel = wlan_cpu_to_le16(*((u16 *) pdata_buf));
+	}
+
+	rfchan->Action = wlan_cpu_to_le16(option);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of rssi.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_rssi(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *cmd)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_RSSI);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_RSSI) + S_DS_GEN);
+	cmd->params.rssi.N = priv->adapter->bcn_avg_factor;
+
+	/* reset Beacon SNR/NF/RSSI values */
+	Adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = 0;
+	Adapter->SNR[TYPE_BEACON][TYPE_AVG] = 0;
+	Adapter->NF[TYPE_BEACON][TYPE_NOAVG] = 0;
+	Adapter->NF[TYPE_BEACON][TYPE_AVG] = 0;
+	Adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0;
+	Adapter->RSSI[TYPE_BEACON][TYPE_AVG] = 0;
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of reg_access.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_reg_access(wlan_private * priv,
+			       struct HostCmd_DS_COMMAND *CmdPtr,
+			       u8 cmd_action, void *pdata_buf)
+{
+	struct wlan_offset_value *offval;
+
+	ENTER();
+
+	offval = (struct wlan_offset_value *)pdata_buf;
+
+	switch (CmdPtr->Command) {
+	case HostCmd_CMD_MAC_REG_ACCESS:
+		{
+			struct HostCmd_DS_MAC_REG_ACCESS *macreg;
+
+			CmdPtr->Size =
+			    wlan_cpu_to_le16(sizeof
+					     (struct HostCmd_DS_MAC_REG_ACCESS)
+					     + S_DS_GEN);
+			macreg =
+			    (struct HostCmd_DS_MAC_REG_ACCESS *)&CmdPtr->params.
+			    macreg;
+
+			macreg->Action = wlan_cpu_to_le16(cmd_action);
+			macreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
+			macreg->Value = wlan_cpu_to_le32(offval->value);
+
+			break;
+		}
+
+	case HostCmd_CMD_BBP_REG_ACCESS:
+		{
+			struct HostCmd_DS_BBP_REG_ACCESS *bbpreg;
+
+			CmdPtr->Size =
+			    wlan_cpu_to_le16(sizeof
+					     (struct HostCmd_DS_BBP_REG_ACCESS)
+					     + S_DS_GEN);
+			bbpreg =
+			    (struct HostCmd_DS_BBP_REG_ACCESS *)&CmdPtr->params.
+			    bbpreg;
+
+			bbpreg->Action = wlan_cpu_to_le16(cmd_action);
+			bbpreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
+			bbpreg->Value = (u8) offval->value;
+
+			break;
+		}
+
+	case HostCmd_CMD_RF_REG_ACCESS:
+		{
+			struct HostCmd_DS_RF_REG_ACCESS *rfreg;
+
+			CmdPtr->Size =
+			    wlan_cpu_to_le16(sizeof
+					     (struct HostCmd_DS_RF_REG_ACCESS) +
+					     S_DS_GEN);
+			rfreg =
+			    (struct HostCmd_DS_RF_REG_ACCESS *)&CmdPtr->params.
+			    rfreg;
+
+			rfreg->Action = wlan_cpu_to_le16(cmd_action);
+			rfreg->Offset = wlan_cpu_to_le16((u16) offval->offset);
+			rfreg->Value = (u8) offval->value;
+
+			break;
+		}
+
+	default:
+		break;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of mac_address.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_mac_address(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *cmd,
+				       u16 cmd_action)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_MAC_ADDRESS) +
+			     S_DS_GEN);
+	cmd->Result = 0;
+
+	cmd->params.macadd.Action = wlan_cpu_to_le16(cmd_action);
+
+	if (cmd_action == HostCmd_ACT_SET) {
+		memcpy(cmd->params.macadd.MacAdd,
+		       Adapter->CurrentAddr, ETH_ALEN);
+		HEXDUMP("SET_CMD: MAC ADDRESS-", Adapter->CurrentAddr, 6);
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of eeprom_access.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: GET or SET
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_802_11_eeprom_access(wlan_private * priv,
+					 struct HostCmd_DS_COMMAND *cmd,
+					 int cmd_action, void *pdata_buf)
+{
+	wlan_ioctl_regrdwr *ea = pdata_buf;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_EEPROM_ACCESS);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_EEPROM_ACCESS) +
+			     S_DS_GEN);
+	cmd->Result = 0;
+
+	cmd->params.rdeeprom.Action = wlan_cpu_to_le16(ea->Action);
+	cmd->params.rdeeprom.Offset = wlan_cpu_to_le16(ea->Offset);
+	cmd->params.rdeeprom.ByteCount = wlan_cpu_to_le16(ea->NOB);
+	cmd->params.rdeeprom.Value = 0;
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function prepares command of DFT access.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd	   	A pointer to HostCmd_DS_COMMAND structure
+ *  @param cmd_action   the action: ADD, DEL, RESET, or LIST
+ *  @param pdata_buf	A pointer to data buffer
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_dft_access(wlan_private * priv,
+			       struct HostCmd_DS_COMMAND *cmd,
+			       u16 cmd_action, void *pdata_buf)
+{
+	struct HostCmd_DS_DFT_ACCESS *dft_access = &cmd->params.dft;
+	PRINTM(INFO, "DFT CMD(%d)\n", cmd_action);
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_DFT_ACCESS);
+	cmd->Size = wlan_cpu_to_le16(sizeof(struct HostCmd_DS_DFT_ACCESS)
+				     + S_DS_GEN);
+	cmd->Result = 0;
+	dft_access->action = wlan_cpu_to_le16(cmd_action);
+
+	switch (cmd_action) {
+	case HostCmd_ACT_DFT_ACCESS_ADD:
+		memcpy(dft_access->addr1, pdata_buf, 2 * ETH_ALEN);
+		HEXDUMP("DFT_ADD: index mac address-", dft_access->addr1, 6);
+		HEXDUMP("DFT_ADD: yield mac address-", dft_access->addr2, 6);
+		break;
+	case HostCmd_ACT_DFT_ACCESS_DEL:
+		memcpy(dft_access->addr1, pdata_buf, 1 * ETH_ALEN);
+		HEXDUMP("DFT_DEL: index mac address-", dft_access->addr1, 6);
+		break;
+	case HostCmd_ACT_DFT_ACCESS_LIST:
+		dft_access->id = wlan_cpu_to_le32(*(u32 *) pdata_buf);
+		break;
+	case HostCmd_ACT_DFT_ACCESS_RESET:
+		break;
+	case HostCmd_ACT_BT_ACCESS_ADD:
+		memcpy(dft_access->addr1, pdata_buf, 2 * ETH_ALEN);
+		HEXDUMP("BT_ADD: blinded mac address-", dft_access->addr1, 6);
+		break;
+	case HostCmd_ACT_BT_ACCESS_DEL:
+		memcpy(dft_access->addr1, pdata_buf, 1 * ETH_ALEN);
+		HEXDUMP("BT_DEL: blinded mac address-", dft_access->addr1, 6);
+		break;
+	case HostCmd_ACT_BT_ACCESS_LIST:
+		dft_access->id = wlan_cpu_to_le32(*(u32 *) pdata_buf);
+		break;
+	case HostCmd_ACT_BT_ACCESS_RESET:
+		break;
+	default:
+		break;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function queues the command to cmd list.
+ *  
+ *  @param Adapter	A pointer to wlan_adapter structure
+ *  @param CmdNode   	A pointer to CmdCtrlNode structure
+ *  @param addtail	specify if the cmd needs to be queued in the header or tail
+ *  @return 	   	n/a
+ */
+void libertas_queue_cmd(wlan_adapter * Adapter, struct CmdCtrlNode *CmdNode, u8 addtail)
+{
+	ulong flags;
+	struct HostCmd_DS_COMMAND *CmdPtr;
+
+	ENTER();
+
+	if (!CmdNode) {
+		PRINTM(INFO, "QUEUE_CMD: CmdNode is NULL\n");
+		goto done;
+	}
+
+	CmdPtr = (struct HostCmd_DS_COMMAND *)CmdNode->BufVirtualAddr;
+	if (!CmdPtr) {
+		PRINTM(INFO, "QUEUE_CMD: CmdPtr is NULL\n");
+		goto done;
+	}
+
+	/* Exit_PS command needs to be queued in the header always. */
+	if (CmdPtr->Command == HostCmd_CMD_802_11_PS_MODE) {
+		struct HostCmd_DS_802_11_PS_MODE *psm = &CmdPtr->params.psmode;
+		if (psm->Action == HostCmd_SubCmd_Exit_PS) {
+			if (Adapter->PSState != PS_STATE_FULL_POWER)
+				addtail = 0;
+		}
+	}
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+
+	if (addtail)
+		list_add_tail((struct list_head *)CmdNode,
+			      &Adapter->CmdPendingQ);
+	else
+		list_add((struct list_head *)CmdNode, &Adapter->CmdPendingQ);
+
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+	PRINTM(INFO, "QUEUE_CMD: Inserted node=0x%x, cmd=0x%x in CmdPendingQ\n",
+	       (u32) CmdNode,
+	       ((struct HostCmd_DS_GEN *)CmdNode->BufVirtualAddr)->Command);
+
+      done:
+	LEAVE();
+	return;
+}
+
+/*
+ * TODO: Fix the issue when DownloadCommandToStation is being called the
+ * second time when the command timesout. All the CmdPtr->xxx are in little
+ * endian and therefore all the comparissions will fail.
+ * For now - we are not performing the endian conversion the second time - but
+ * for PS and DEEP_SLEEP we need to worry
+ */
+
+/** 
+ *  @brief This function downloads the command to firmware.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param CmdNode   	A pointer to CmdCtrlNode structure
+ *  @return 	   	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int DownloadCommandToStation(wlan_private * priv,
+				    struct CmdCtrlNode *CmdNode)
+{
+	ulong flags;
+	struct HostCmd_DS_COMMAND *CmdPtr;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	u16 CmdSize;
+	u16 Command;
+
+	ENTER();
+
+	if (!Adapter || !CmdNode) {
+		PRINTM(INFO, "DNLD_CMD: Adapter = %#x, CmdNode = %#x\n",
+		       (int)Adapter, (int)CmdNode);
+		if (CmdNode)
+			libertas_cleanup_and_insert_cmd(priv, CmdNode);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	CmdPtr = (struct HostCmd_DS_COMMAND *)CmdNode->BufVirtualAddr;
+
+	if (!CmdPtr || !CmdPtr->Size) {
+		PRINTM(INFO, "DNLD_CMD: CmdPtr is Null or Cmd Size is Zero, "
+		       "Not sending\n");
+		libertas_cleanup_and_insert_cmd(priv, CmdNode);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+	Adapter->CurCmd = CmdNode;
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+	Adapter->CurCmdRetCode = 0;
+	PRINTM(INFO, "DNLD_CMD:: Before download, Size of Cmd = %d\n",
+	       CmdPtr->Size);
+
+	CmdSize = CmdPtr->Size;
+
+	Command = wlan_cpu_to_le16(CmdPtr->Command);
+
+	CmdNode->CmdWaitQWoken = 0;
+	CmdSize = wlan_cpu_to_le16(CmdSize);
+
+	ret = libertas_sbi_host_to_card(priv, MVMS_CMD, (u8 *) CmdPtr, CmdSize);
+
+	if (ret != 0) {
+		PRINTM(INFO, "DNLD_CMD: Host to Card Failed\n");
+		libertas_cleanup_and_insert_cmd(priv, Adapter->CurCmd);
+		spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+		Adapter->CurCmd = NULL;
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	PRINTM(INFO, "DNLD_CMD: Sent command 0x%x @ %lu\n", Command, jiffies);
+	HEXDUMP("DNLD_CMD: Command", CmdNode->BufVirtualAddr, CmdSize);
+
+	/* Setup the timer after transmit command */
+	if (Command == HostCmd_CMD_802_11_SCAN
+	    || Command == HostCmd_CMD_802_11_AUTHENTICATE
+	    || Command == HostCmd_CMD_802_11_ASSOCIATE)
+		mod_timer(&Adapter->command_timer, jiffies + (10*HZ));
+	else
+		mod_timer(&Adapter->command_timer, jiffies + (5*HZ));
+
+	ret = WLAN_STATUS_SUCCESS;
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function prepares command of mac_control.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd		A pointer to HostCmd_DS_COMMAND structure
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_cmd_mac_control(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *cmd)
+{
+	struct HostCmd_DS_MAC_CONTROL *mac = &cmd->params.macctrl;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_MAC_CONTROL);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_MAC_CONTROL) + S_DS_GEN);
+	mac->Action = wlan_cpu_to_le16(priv->adapter->CurrentPacketFilter);
+
+	PRINTM(INFO, "wlan_cmd_mac_control(): Action=0x%X Size=%d\n",
+	       mac->Action, cmd->Size);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function inserts command node to CmdFreeQ
+ *  after cleans it.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param pTempCmd	A pointer to CmdCtrlNode structure
+ *  @return 		n/a
+ */
+void libertas_cleanup_and_insert_cmd(wlan_private * priv, struct CmdCtrlNode *pTempCmd)
+{
+	ulong flags;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (!pTempCmd)
+		goto done;
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+	CleanUpCmdCtrlNode(pTempCmd);
+	list_add_tail((struct list_head *)pTempCmd, &Adapter->CmdFreeQ);
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+      done:
+	LEAVE();
+}
+
+/** 
+ *  @brief This function sets radio control.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_set_radio_control(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_RADIO_CONTROL,
+				    HostCmd_ACT_GEN_SET,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	PRINTM(INFO, "RADIO_SET: on or off: 0x%X, Preamble = 0x%X\n",
+	       priv->adapter->RadioOn, priv->adapter->Preamble);
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function sets packet filter.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_set_mac_packet_filter(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(INFO, "libertas_set_mac_packet_filter Value = %x\n",
+	       priv->adapter->CurrentPacketFilter);
+
+	/* Send MAC control command to station */
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_MAC_CONTROL, 0, 0, 0, NULL);
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function prepare the command before send to firmware.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param cmd_no	command number
+ *  @param cmd_action	command action: GET or SET
+ *  @param wait_option	wait option: wait response or not
+ *  @param cmd_oid	cmd oid: treated as sub command
+ *  @param pdata_buf	A pointer to informaion buffer
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_prepare_and_send_command(wlan_private * priv,
+			  u16 cmd_no,
+			  u16 cmd_action,
+			  u16 wait_option, u32 cmd_oid, void *pdata_buf)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+	struct CmdCtrlNode *CmdNode;
+	struct HostCmd_DS_COMMAND *CmdPtr;
+
+	ENTER();
+
+	if (!Adapter) {
+		PRINTM(INFO, "PREP_CMD: Adapter is Null\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (Adapter->SurpriseRemoved) {
+		PRINTM(INFO, "PREP_CMD: Card is Removed\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	CmdNode = libertas_get_free_cmd_ctrl_node(priv);
+
+	if (CmdNode == NULL) {
+		PRINTM(MSG, "PREP_CMD: No free CmdNode\n");
+
+		/* Wake up main thread to execute next command */
+		wake_up_interruptible(&priv->MainThread.waitQ);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	libertas_set_cmd_ctrl_node(priv, CmdNode, cmd_oid, wait_option, pdata_buf);
+
+	CmdPtr = (struct HostCmd_DS_COMMAND *)CmdNode->BufVirtualAddr;
+
+	PRINTM(INFO, "PREP_CMD: Val of Cmd ptr =0x%x, command=0x%X\n",
+	       (u32) CmdPtr, cmd_no);
+
+	if (!CmdPtr) {
+		PRINTM(MSG, "PREP_CMD: BufVirtualAddr of CmdNode is NULL\n");
+		libertas_cleanup_and_insert_cmd(priv, CmdNode);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Set sequence number, command and INT option */
+	Adapter->SeqNum++;
+	CmdPtr->SeqNum = wlan_cpu_to_le16(Adapter->SeqNum);
+
+	CmdPtr->Command = cmd_no;
+	CmdPtr->Result = 0;
+
+	switch (cmd_no) {
+	case HostCmd_CMD_GET_HW_SPEC:
+		ret = wlan_cmd_hw_spec(priv, CmdPtr);
+		break;
+	case HostCmd_CMD_802_11_PS_MODE:
+		ret = wlan_cmd_802_11_ps_mode(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_SCAN:
+		ret = libertas_cmd_80211_scan(priv, CmdPtr, pdata_buf);
+		break;
+
+	case HostCmd_CMD_MAC_CONTROL:
+		ret = wlan_cmd_mac_control(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_ASSOCIATE:
+	case HostCmd_CMD_802_11_REASSOCIATE:
+		ret = libertas_cmd_80211_associate(priv, CmdPtr, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_DEAUTHENTICATE:
+		ret = libertas_cmd_80211_deauthenticate(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_SET_WEP:
+		ret = wlan_cmd_802_11_set_wep(priv, CmdPtr, cmd_oid);
+		break;
+
+	case HostCmd_CMD_802_11_AD_HOC_START:
+		ret = libertas_cmd_80211_ad_hoc_start(priv, CmdPtr, pdata_buf);
+		break;
+	case HostCmd_CMD_CODE_DNLD:
+		break;
+
+	case HostCmd_CMD_802_11_RESET:
+		ret = wlan_cmd_802_11_reset(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_GET_LOG:
+		ret = wlan_cmd_802_11_get_log(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_AUTHENTICATE:
+		ret = libertas_cmd_80211_authenticate(priv, CmdPtr, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_GET_STAT:
+		ret = wlan_cmd_802_11_get_stat(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_SNMP_MIB:
+		ret = wlan_cmd_802_11_snmp_mib(priv, CmdPtr,
+					       cmd_action, cmd_oid, pdata_buf);
+		break;
+
+	case HostCmd_CMD_MAC_REG_ACCESS:
+	case HostCmd_CMD_BBP_REG_ACCESS:
+	case HostCmd_CMD_RF_REG_ACCESS:
+		ret = wlan_cmd_reg_access(priv, CmdPtr, cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_RF_CHANNEL:
+		ret = wlan_cmd_802_11_rf_channel(priv, CmdPtr,
+						 cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_RF_TX_POWER:
+		ret = wlan_cmd_802_11_rf_tx_power(priv, CmdPtr,
+						  cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_RADIO_CONTROL:
+		ret = wlan_cmd_802_11_radio_control(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_RF_ANTENNA:
+		ret = wlan_cmd_802_11_rf_antenna(priv, CmdPtr,
+						 cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_DATA_RATE:
+		ret = wlan_cmd_802_11_data_rate(priv, CmdPtr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11_RATE_ADAPT_RATESET:
+		ret = wlan_cmd_802_11_rate_adapt_rateset(priv,
+							 CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_MAC_MULTICAST_ADR:
+		ret = wlan_cmd_mac_multicast_adr(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_AD_HOC_JOIN:
+		ret = libertas_cmd_80211_ad_hoc_join(priv, CmdPtr, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_RSSI:
+		ret = wlan_cmd_802_11_rssi(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_AD_HOC_STOP:
+		ret = libertas_cmd_80211_ad_hoc_stop(priv, CmdPtr);
+		break;
+
+	case HostCmd_CMD_802_11_ENABLE_RSN:
+		ret = wlan_cmd_802_11_enable_rsn(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_KEY_MATERIAL:
+		ret = wlan_cmd_802_11_key_material(priv, CmdPtr,
+						   cmd_action, cmd_oid,
+						   pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_PAIRWISE_TSC:
+		break;
+	case HostCmd_CMD_802_11_GROUP_TSC:
+		break;
+
+	case HostCmd_CMD_802_11_MAC_ADDRESS:
+		ret = wlan_cmd_802_11_mac_address(priv, CmdPtr, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_EEPROM_ACCESS:
+		ret = wlan_cmd_802_11_eeprom_access(priv, CmdPtr,
+						    cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_SET_AFC:
+	case HostCmd_CMD_802_11_GET_AFC:
+
+		CmdPtr->Command = wlan_cpu_to_le16(cmd_no);
+		CmdPtr->Size =
+		    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_AFC) +
+				     S_DS_GEN);
+
+		memmove(&CmdPtr->params.afc,
+			pdata_buf, sizeof(struct HostCmd_DS_802_11_AFC));
+
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+
+	case HostCmd_CMD_802_11D_DOMAIN_INFO:
+		ret = libertas_cmd_802_11d_domain_info(priv, CmdPtr,
+						   cmd_no, cmd_action);
+		break;
+
+	case HostCmd_CMD_802_11_SLEEP_PARAMS:
+		ret = wlan_cmd_802_11_sleep_params(priv, CmdPtr, cmd_action);
+		break;
+	case HostCmd_CMD_802_11_INACTIVITY_TIMEOUT:
+		ret = wlan_cmd_802_11_inactivity_timeout(priv, CmdPtr,
+							 cmd_action, pdata_buf);
+		libertas_set_cmd_ctrl_node(priv, CmdNode, 0, 0, pdata_buf);
+		break;
+
+	case HostCmd_CMD_802_11_TPC_CFG:
+		CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_TPC_CFG);
+		CmdPtr->Size =
+		    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_TPC_CFG) +
+				     S_DS_GEN);
+
+		memmove(&CmdPtr->params.tpccfg,
+			pdata_buf, sizeof(struct HostCmd_DS_802_11_TPC_CFG));
+
+		ret = WLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_LED_GPIO_CTRL:
+		{
+			struct MrvlIEtypes_LedGpio *gpio =
+			    (struct MrvlIEtypes_LedGpio*)
+			    CmdPtr->params.ledgpio.data;
+
+			memmove(&CmdPtr->params.ledgpio,
+				pdata_buf,
+				sizeof(struct HostCmd_DS_802_11_LED_CTRL));
+
+			CmdPtr->Command =
+			    wlan_cpu_to_le16(HostCmd_CMD_802_11_LED_GPIO_CTRL);
+
+#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8
+			CmdPtr->Size =
+			    wlan_cpu_to_le16(gpio->Header.Len + S_DS_GEN +
+					     ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN);
+			gpio->Header.Len = wlan_cpu_to_le16(gpio->Header.Len);
+
+			ret = WLAN_STATUS_SUCCESS;
+			break;
+		}
+	case HostCmd_CMD_802_11_PWR_CFG:
+		CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_PWR_CFG);
+		CmdPtr->Size =
+		    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_PWR_CFG) +
+				     S_DS_GEN);
+		memmove(&CmdPtr->params.pwrcfg, pdata_buf,
+			sizeof(struct HostCmd_DS_802_11_PWR_CFG));
+
+		ret = WLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_SLEEP_PERIOD:
+		ret = wlan_cmd_802_11_sleep_period(priv, CmdPtr,
+						   cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_DFT_ACCESS:
+		ret = wlan_cmd_dft_access(priv, CmdPtr, cmd_action, pdata_buf);
+		break;
+
+	case HostCmd_CMD_GET_TSF:
+		CmdPtr->Command = wlan_cpu_to_le16(HostCmd_CMD_GET_TSF);
+		CmdPtr->Size =
+		    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_GET_TSF)
+				     + S_DS_GEN);
+		ret = WLAN_STATUS_SUCCESS;
+		break;
+	case HostCmd_CMD_802_11_TX_RATE_QUERY:
+		CmdPtr->Command =
+		    wlan_cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY);
+		CmdPtr->Size =
+		    wlan_cpu_to_le16(sizeof(struct HostCmd_TX_RATE_QUERY) +
+				     S_DS_GEN);
+		Adapter->TxRate = 0;
+		ret = WLAN_STATUS_SUCCESS;
+		break;
+	default:
+		PRINTM(INFO, "PREP_CMD: unknown command- %#x\n", cmd_no);
+		ret = WLAN_STATUS_FAILURE;
+		break;
+	}
+
+	/* return error, since the command preparation failed */
+	if (ret != WLAN_STATUS_SUCCESS) {
+		PRINTM(INFO, "PREP_CMD: Command preparation failed\n");
+		libertas_cleanup_and_insert_cmd(priv, CmdNode);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	CmdNode->CmdWaitQWoken = 0;
+
+	libertas_queue_cmd(Adapter, CmdNode, 1);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	libertas_sbi_reenable_host_interrupt(priv, 0x00);
+
+	if (wait_option & HostCmd_OPTION_WAITFORRSP) {
+		PRINTM(INFO, "PREP_CMD: Wait for CMD response\n");
+		wait_event_interruptible(CmdNode->cmdwait_q,
+					 CmdNode->CmdWaitQWoken);
+	}
+
+	if (Adapter->CurCmdRetCode) {
+		PRINTM(INFO, "PREP_CMD: Command failed with return code=%d\n",
+		       Adapter->CurCmdRetCode);
+		Adapter->CurCmdRetCode = 0;
+		ret = WLAN_STATUS_FAILURE;
+	}
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function allocates the command buffer and link
+ *  it to command free queue.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_allocate_cmd_buffer(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	u32 ulBufSize;
+	u32 i;
+	struct CmdCtrlNode *TempCmdArray;
+	u8 *pTempVirtualAddr;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* Allocate and initialize CmdCtrlNode */
+	ulBufSize = sizeof(struct CmdCtrlNode) * MRVDRV_NUM_OF_CMD_BUFFER;
+
+	if (!(TempCmdArray = kmalloc(ulBufSize, GFP_KERNEL))) {
+		PRINTM(INFO,
+		       "ALLOC_CMD_BUF: Failed to allocate TempCmdArray\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	Adapter->CmdArray = TempCmdArray;
+	memset(Adapter->CmdArray, 0, ulBufSize);
+
+	/* Allocate and initialize command buffers */
+	ulBufSize = MRVDRV_SIZE_OF_CMD_BUFFER;
+	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+		if (!(pTempVirtualAddr = kmalloc(ulBufSize, GFP_KERNEL))) {
+			PRINTM(INFO,
+			       "ALLOC_CMD_BUF: pTempVirtualAddr: out of memory\n");
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+
+		memset(pTempVirtualAddr, 0, ulBufSize);
+
+		/* Update command buffer virtual */
+		TempCmdArray[i].BufVirtualAddr = pTempVirtualAddr;
+	}
+
+	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+		init_waitqueue_head(&TempCmdArray[i].cmdwait_q);
+		libertas_cleanup_and_insert_cmd(priv, &TempCmdArray[i]);
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function frees the command buffer.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_free_cmd_buffer(wlan_private * priv)
+{
+	u32 ulBufSize;
+	unsigned int i;
+	struct CmdCtrlNode *TempCmdArray;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* need to check if cmd array is allocated or not */
+	if (Adapter->CmdArray == NULL) {
+		PRINTM(INFO, "FREE_CMD_BUF: CmdArray is Null\n");
+		goto done;
+	}
+
+	TempCmdArray = Adapter->CmdArray;
+
+	/* Release shared memory buffers */
+	ulBufSize = MRVDRV_SIZE_OF_CMD_BUFFER;
+	for (i = 0; i < MRVDRV_NUM_OF_CMD_BUFFER; i++) {
+		if (TempCmdArray[i].BufVirtualAddr) {
+			PRINTM(INFO, "Free all the array\n");
+			kfree(TempCmdArray[i].BufVirtualAddr);
+			TempCmdArray[i].BufVirtualAddr = NULL;
+		}
+	}
+
+	/* Release CmdCtrlNode */
+	if (Adapter->CmdArray) {
+		PRINTM(INFO, "Free CmdArray\n");
+		kfree(Adapter->CmdArray);
+		Adapter->CmdArray = NULL;
+	}
+
+      done:
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function gets a free command node if available in
+ *  command free queue.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @return CmdCtrlNode A pointer to CmdCtrlNode structure or NULL
+ */
+struct CmdCtrlNode *libertas_get_free_cmd_ctrl_node(wlan_private * priv)
+{
+	struct CmdCtrlNode *TempNode;
+	wlan_adapter *Adapter = priv->adapter;
+	ulong flags;
+
+	ENTER();
+
+	if (!Adapter)
+		return NULL;
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+
+	if (!list_empty(&Adapter->CmdFreeQ)) {
+		TempNode = (struct CmdCtrlNode *)Adapter->CmdFreeQ.next;
+		list_del((struct list_head *)TempNode);
+	} else {
+		PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode is not available\n");
+		TempNode = NULL;
+	}
+
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+	if (TempNode) {
+		PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode available\n");
+		PRINTM(INFO, "GET_CMD_NODE: CmdCtrlNode Address = %p\n",
+		       TempNode);
+		CleanUpCmdCtrlNode(TempNode);
+	}
+
+	LEAVE();
+	return TempNode;
+}
+
+/** 
+ *  @brief This function cleans command node.
+ *  
+ *  @param pTempNode	A pointer to CmdCtrlNode structure
+ *  @return 		n/a
+ */
+static void CleanUpCmdCtrlNode(struct CmdCtrlNode *pTempNode)
+{
+	ENTER();
+
+	if (!pTempNode)
+		return;
+	pTempNode->CmdWaitQWoken = 1;
+	wake_up_interruptible(&pTempNode->cmdwait_q);
+	pTempNode->Status = 0;
+	pTempNode->cmd_oid = (u32) 0;
+	pTempNode->wait_option = 0;
+	pTempNode->pdata_buf = NULL;
+
+	if (pTempNode->BufVirtualAddr != NULL)
+		memset(pTempNode->BufVirtualAddr, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This function initializes the command node.
+ *  
+ *  @param priv		A pointer to wlan_private structure
+ *  @param pTempNode	A pointer to CmdCtrlNode structure
+ *  @param cmd_oid	cmd oid: treated as sub command
+ *  @param wait_option	wait option: wait response or not
+ *  @param pdata_buf	A pointer to informaion buffer
+ *  @return 		WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+void libertas_set_cmd_ctrl_node(wlan_private * priv,
+		    struct CmdCtrlNode *pTempNode,
+		    u32 cmd_oid, u16 wait_option, void *pdata_buf)
+{
+	ENTER();
+
+	if (!pTempNode)
+		return;
+
+	pTempNode->cmd_oid = cmd_oid;
+	pTempNode->wait_option = wait_option;
+	pTempNode->pdata_buf = pdata_buf;
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function executes next command in command
+ *  pending queue. It will put fimware back to PS mode
+ *  if applicable.
+ *  
+ *  @param priv     A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_execute_next_command(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct CmdCtrlNode *CmdNode = NULL;
+	struct HostCmd_DS_COMMAND *CmdPtr;
+	ulong flags;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (!Adapter) {
+		PRINTM(MSG, "EXEC_NEXT_CMD: Adapter is NULL\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+
+	if (Adapter->CurCmd) {
+		PRINTM(MSG, "EXEC_NEXT_CMD: there is command in processing!\n");
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (!list_empty(&Adapter->CmdPendingQ)) {
+		CmdNode = (struct CmdCtrlNode *)
+		    Adapter->CmdPendingQ.next;
+	}
+
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+	if (CmdNode) {
+		PRINTM(INFO,
+		       "EXEC_NEXT_CMD: Got next command from CmdPendingQ\n");
+		CmdPtr = (struct HostCmd_DS_COMMAND *)CmdNode->BufVirtualAddr;
+
+		if (Is_Command_Allowed_In_PS(CmdPtr->Command)) {
+			if ((Adapter->PSState == PS_STATE_SLEEP)
+			    || (Adapter->PSState == PS_STATE_PRE_SLEEP)
+			    ) {
+				PRINTM(INFO,
+				       "EXEC_NEXT_CMD: Cannot send cmd 0x%x in PSState %d\n",
+				       CmdPtr->Command, Adapter->PSState);
+				ret = WLAN_STATUS_FAILURE;
+				goto done;
+			}
+			PRINTM(INFO, "EXEC_NEXT_CMD: OK to send command "
+			       "0x%x in PSState %d\n",
+			       CmdPtr->Command, Adapter->PSState);
+		} else if (Adapter->PSState != PS_STATE_FULL_POWER) {
+			/*
+			 * 1. Non-PS command: 
+			 * Queue it. set NeedToWakeup to TRUE if current state 
+			 * is SLEEP, otherwise call libertas_ps_wakeup to send Exit_PS.
+			 * 2. PS command but not Exit_PS: 
+			 * Ignore it.
+			 * 3. PS command Exit_PS:
+			 * Set NeedToWakeup to TRUE if current state is SLEEP, 
+			 * otherwise send this command down to firmware
+			 * immediately.
+			 */
+			if (CmdPtr->Command !=
+			    wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE)) {
+				/*  Prepare to send Exit PS,
+				 *  this non PS command will be sent later */
+				if ((Adapter->PSState == PS_STATE_SLEEP)
+				    || (Adapter->PSState == PS_STATE_PRE_SLEEP)
+				    ) {
+					/* w/ new scheme, it will not reach here.
+					   since it is blocked in main_thread. */
+					Adapter->NeedToWakeup = 1;
+				} else
+					libertas_ps_wakeup(priv, 0);
+
+				ret = WLAN_STATUS_SUCCESS;
+				goto done;
+			} else {
+				/*
+				 * PS command. Ignore it if it is not Exit_PS. 
+				 * otherwise send it down immediately.
+				 */
+				struct HostCmd_DS_802_11_PS_MODE *psm =
+				    &CmdPtr->params.psmode;
+
+				PRINTM(INFO,
+				       "EXEC_NEXT_CMD: PS cmd- Action=0x%x\n",
+				       psm->Action);
+				if (psm->Action !=
+				    wlan_cpu_to_le16(HostCmd_SubCmd_Exit_PS)) {
+					PRINTM(INFO,
+					       "EXEC_NEXT_CMD: Ignore Enter PS cmd\n");
+					list_del((struct list_head *)CmdNode);
+					libertas_cleanup_and_insert_cmd(priv, CmdNode);
+
+					ret = WLAN_STATUS_SUCCESS;
+					goto done;
+				}
+
+				if ((Adapter->PSState == PS_STATE_SLEEP)
+				    || (Adapter->PSState == PS_STATE_PRE_SLEEP)
+				    ) {
+					PRINTM(INFO,
+					       "EXEC_NEXT_CMD: Ignore ExitPS cmd in sleep\n");
+					list_del((struct list_head *)CmdNode);
+					libertas_cleanup_and_insert_cmd(priv, CmdNode);
+					Adapter->NeedToWakeup = 1;
+
+					ret = WLAN_STATUS_SUCCESS;
+					goto done;
+				}
+
+				PRINTM(INFO,
+				       "EXEC_NEXT_CMD: Sending Exit_PS down...\n");
+			}
+		}
+		list_del((struct list_head *)CmdNode);
+		PRINTM(INFO, "EXEC_NEXT_CMD: Sending 0x%04X Command\n",
+		       CmdPtr->Command);
+		DownloadCommandToStation(priv, CmdNode);
+	} else {
+		/*
+		 * check if in power save mode, if yes, put the device back
+		 * to PS mode
+		 */
+		if ((Adapter->PSMode != Wlan802_11PowerModeCAM) &&
+		    (Adapter->PSState == PS_STATE_FULL_POWER) &&
+		    (Adapter->MediaConnectStatus == WlanMediaStateConnected)) {
+			if (Adapter->SecInfo.WPAEnabled
+			    || Adapter->SecInfo.WPA2Enabled) {
+				if (Adapter->IsGTK_SET) {
+					PRINTM(INFO,
+					       "EXEC_NEXT_CMD: WPA enabled and GTK_SET"
+					       " go back to PS_SLEEP");
+					libertas_ps_sleep(priv, 0);
+				}
+			} else {
+				PRINTM(INFO,
+				       "EXEC_NEXT_CMD: Command PendQ is empty,"
+				       " go back to PS_SLEEP");
+				libertas_ps_sleep(priv, 0);
+			}
+		}
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function sends customized event to application.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @para str	   A pointer to event string
+ *  @return 	   n/a
+ */
+void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str)
+{
+	union iwreq_data iwrq;
+	u8 buf[50];
+
+	ENTER();
+
+	memset(&iwrq, 0, sizeof(union iwreq_data));
+	memset(buf, 0, sizeof(buf));
+
+	snprintf(buf, sizeof(buf) - 1, "%s", str);
+
+	iwrq.data.pointer = buf;
+	iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN;
+
+	/* Send Event to upper layer */
+	PRINTM(INFO, "Event Indication string = %s\n",
+	       (char *)iwrq.data.pointer);
+	PRINTM(INFO, "Event Indication String Length = %d\n", iwrq.data.length);
+
+	PRINTM(INFO, "Sending wireless event IWEVCUSTOM for %s\n", str);
+	wireless_send_event(priv->wlan_dev.netdev, IWEVCUSTOM, &iwrq, buf);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This function sends sleep confirm command to firmware.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param cmdptr  A pointer to the command
+ *  @param size	   the size of command
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int SendConfirmSleep(wlan_private * priv, u8 * CmdPtr, u16 size)
+{
+	unsigned long flags;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(INFO, "SEND_SLEEPC_CMD: Before download, Size of cmd = %d\n",
+	       size);
+
+	HEXDUMP("SEND_SLEEPC_CMD: Sleep confirm Command", CmdPtr, size);
+
+	ret = libertas_sbi_host_to_card(priv, MVMS_CMD, CmdPtr, size);
+	priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+	if (Adapter->IntCounter || Adapter->CurrentTxSkb)
+		PRINTM(INFO, "SEND_SLEEPC_CMD: IntCounter=%d CurrentTxSkb=%p\n",
+		       Adapter->IntCounter, Adapter->CurrentTxSkb);
+
+	if (ret) {
+		PRINTM(MSG,
+		       "SEND_SLEEPC_CMD: Host to Card Failed for Confirm Sleep\n");
+	} else {
+		spin_lock_irqsave(&libertas_driver_lock, flags);
+		if (!Adapter->IntCounter) {
+			Adapter->PSState = PS_STATE_SLEEP;
+		} else {
+			PRINTM(INFO, "SEND_SLEEPC_CMD: After sent,IntC=%d\n",
+			       Adapter->IntCounter);
+		}
+		spin_unlock_irqrestore(&libertas_driver_lock, flags);
+
+		PRINTM(INFO, "SEND_SLEEPC_CMD: Sent Confirm Sleep command\n");
+		PRINTM(INFO, "+");
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function sends Enter_PS command to firmware.
+ *  
+ *  @param priv    	A pointer to wlan_private structure
+ *  @param wait_option	wait response or not
+ *  @return 	   	n/a 
+ */
+void libertas_ps_sleep(wlan_private * priv, int wait_option)
+{
+
+	ENTER();
+
+	/* 
+	 * PS is currently supported only in Infrastructure Mode 
+	 * Remove this check if it is to be supported in IBSS mode also 
+	 */
+
+	libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_PS_MODE,
+			      HostCmd_SubCmd_Enter_PS, wait_option, 0, NULL);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This function sends Eixt_PS command to firmware.
+ *  
+ *  @param priv    	A pointer to wlan_private structure
+ *  @param wait_option	wait response or not
+ *  @return 	   	n/a 
+ */
+void libertas_ps_wakeup(wlan_private * priv, int wait_option)
+{
+	enum WLAN_802_11_POWER_MODE LocalPSMode;
+
+	ENTER();
+
+	LocalPSMode = Wlan802_11PowerModeCAM;
+
+	PRINTM(INFO, "Exit_PS: LocalPSMode = %d\n", LocalPSMode);
+
+	libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_PS_MODE,
+			      HostCmd_SubCmd_Exit_PS,
+			      wait_option, 0, &LocalPSMode);
+
+	LEAVE();
+	return;
+}
+
+/** 
+ *  @brief This function checks condition and prepares to
+ *  send sleep confirm command to firmware if ok.
+ *  
+ *  @param priv    	A pointer to wlan_private structure
+ *  @param PSMode  	Power Saving mode
+ *  @return 	   	n/a 
+ */
+void libertas_ps_confirm_sleep(wlan_private * priv, u16 PSMode)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	u8 allowed = 1;
+
+	ENTER();
+
+	if (priv->wlan_dev.dnld_sent) {
+		allowed = 0;
+		PRINTM(INFO, "D");
+	} else if (Adapter->CurCmd) {
+		allowed = 0;
+		PRINTM(INFO, "C");
+	} else if (Adapter->IntCounter > 0) {
+		allowed = 0;
+		PRINTM(INFO, "I%d", Adapter->IntCounter);
+	}
+
+	if (allowed) {
+		PRINTM(INFO, "Sending libertas_ps_confirm_sleep\n");
+		SendConfirmSleep(priv, (u8 *) & Adapter->libertas_ps_confirm_sleep,
+				 sizeof(struct PS_CMD_ConfirmSleep));
+	} else {
+		PRINTM(INFO, "Sleep Confirm has been delayed\n");
+	}
+
+	LEAVE();
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_cmdresp.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_cmdresp.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_cmdresp.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_cmdresp.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,1243 @@
+/** @file wlan_cmdresp.c
+  * @brief This file contains the handling of command
+  * responses as well as events generated by firmware.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/10/05: Add Doxygen format comments
+	11/11/05: Add support for WMM Status change event
+	12/13/05: Add Proprietary periodic sleep support
+	12/23/05: Fix bug in adhoc start where the current index was
+	          not properly being assigned before it was used.
+	01/05/06: Add kernel 2.6.x support	
+	01/11/06: Conditionalize new scan/join structures.
+	          Update assoc response handling; entire IEEE response returned
+	04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+	04/10/06: Add hostcmd generic API
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+	05/08/06: Remove Adapter->PermanentAddr memcpy
+********************************************************/
+
+#include <linux/delay.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "sbi.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+#include "wlan_join.h"
+#include "wlan_wext.h"
+
+/** 
+ *  @brief This function handles disconnect event. it
+ *  reports disconnect to upper layer, clean tx/rx packets,
+ *  reset link state etc.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   n/a
+ */
+void libertas_mac_event_disconnected(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	union iwreq_data wrqu;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
+		return;
+
+	PRINTM(INFO, "Handles disconnect event.\n");
+
+	memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+
+	/* 
+	 * Cisco AP sends EAP failure and de-auth in less than 0.5 ms.
+	 * It causes problem in the Supplicant
+	 */
+
+	msleep_interruptible(1000);
+	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+
+	/* Free Tx and Rx packets */
+	kfree_skb(priv->adapter->CurrentTxSkb);
+	priv->adapter->CurrentTxSkb = NULL;
+
+	/* report disconnect to upper layer */
+	netif_stop_queue(priv->wlan_dev.netdev);
+	netif_carrier_off(priv->wlan_dev.netdev);
+
+	/* reset SNR/NF/RSSI values */
+	memset(Adapter->SNR, 0x00, sizeof(Adapter->SNR));
+	memset(Adapter->NF, 0x00, sizeof(Adapter->NF));
+	memset(Adapter->RSSI, 0x00, sizeof(Adapter->RSSI));
+	memset(Adapter->rawSNR, 0x00, sizeof(Adapter->rawSNR));
+	memset(Adapter->rawNF, 0x00, sizeof(Adapter->rawNF));
+	Adapter->nextSNRNF = 0;
+	Adapter->numSNRNF = 0;
+	Adapter->RxPDRate = 0;
+	PRINTM(INFO, "Current SSID=%s, Ssid Length=%u\n",
+	       Adapter->CurBssParams.ssid.Ssid,
+	       Adapter->CurBssParams.ssid.SsidLength);
+	PRINTM(INFO, "Previous SSID=%s, Ssid Length=%u\n",
+	       Adapter->PreviousSSID.Ssid, Adapter->PreviousSSID.SsidLength);
+
+	/* reset internal flags */
+	Adapter->AdHocCreated = 0;
+
+	Adapter->SecInfo.WPAEnabled = 0;
+	Adapter->SecInfo.WPA2Enabled = 0;
+	Adapter->Wpa_ie_len = 0;
+	Adapter->SecInfo.Auth1XAlg = WLAN_1X_AUTH_ALG_NONE;
+	Adapter->SecInfo.EncryptionMode = CIPHER_NONE;
+
+	Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
+	Adapter->LinkSpeed = MRVDRV_LINK_SPEED_1mbps;
+
+	/* 
+	 * memorize the previous SSID and BSSID
+	 * it could be used for re-assoc
+	 */
+	memcpy(&Adapter->PreviousSSID,
+	       &Adapter->CurBssParams.ssid, sizeof(struct WLAN_802_11_SSID));
+	memcpy(Adapter->PreviousBSSID,
+	       Adapter->CurBssParams.bssid, ETH_ALEN);
+
+	/* need to erase the current SSID and BSSID info */
+	Adapter->pAttemptedBSSDesc = 0;
+	memset(&Adapter->CurBssParams, 0, sizeof(Adapter->CurBssParams));
+
+	if (Adapter->PSState != PS_STATE_FULL_POWER) {
+		/* make firmware to exit PS mode */
+		PRINTM(INFO, "Disconnected, so exit PS mode.\n");
+		libertas_ps_wakeup(priv, 0);
+	}
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function handles link lost, deauth and
+ *  disassoc events.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   n/a
+ */
+static void HandleDisconnectEvent(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		libertas_mac_event_disconnected(priv);
+#ifdef REASSOCIATION
+		if (Adapter->Reassoc_on) {
+			PRINTM(INFO, "RE-ASSOC: trigger the timer\n");
+			mod_timer(&Adapter->reassoc_timer, 0);
+		}
+#endif				/* REASSOCIATION */
+	}
+}
+
+/** 
+ *  @brief This function handles MIC failure event.
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @para  event   the event id
+ *  @return 	   n/a
+ */
+static void HandleMICFailureEvent(wlan_private * priv, u32 event)
+{
+	u8 buf[50];
+
+	ENTER();
+
+	memset(buf, 0, sizeof(buf));
+
+	sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication ");
+
+	if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) {
+		strcat(buf, "unicast ");
+	} else {
+		strcat(buf, "multicast ");
+	}
+
+	libertas_send_iwevcustom_event(priv, buf);
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function handles the command response of reg_access
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param type	   the type of reg access (MAC, BBP or RF)
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_reg_access(wlan_private * priv,
+			       u16 type, struct HostCmd_DS_COMMAND *resp)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	switch (type) {
+	case HostCmd_RET_MAC_REG_ACCESS:
+		{
+			struct HostCmd_DS_MAC_REG_ACCESS *reg;
+
+			reg =
+			    (struct HostCmd_DS_MAC_REG_ACCESS *)&resp->params.
+			    macreg;
+
+			Adapter->OffsetValue.offset = reg->Offset;
+			Adapter->OffsetValue.value = reg->Value;
+			break;
+		}
+
+	case HostCmd_RET_BBP_REG_ACCESS:
+		{
+			struct HostCmd_DS_BBP_REG_ACCESS *reg;
+			reg =
+			    (struct HostCmd_DS_BBP_REG_ACCESS *)&resp->params.
+			    bbpreg;
+
+			Adapter->OffsetValue.offset = reg->Offset;
+			Adapter->OffsetValue.value = reg->Value;
+			break;
+		}
+
+	case HostCmd_RET_RF_REG_ACCESS:
+		{
+			struct HostCmd_DS_RF_REG_ACCESS *reg;
+			reg =
+			    (struct HostCmd_DS_RF_REG_ACCESS *)&resp->params.
+			    rfreg;
+
+			Adapter->OffsetValue.offset = reg->Offset;
+			Adapter->OffsetValue.value = reg->Value;
+			break;
+		}
+
+	default:
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of get_hw_spec
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_get_hw_spec(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp)
+{
+	u32 i;
+	struct HostCmd_DS_GET_HW_SPEC *hwspec = &resp->params.hwspec;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	Adapter->HardwareStatus = WlanHardwareStatusReady;
+	Adapter->fwCapInfo = wlan_le32_to_cpu(hwspec->fwCapInfo);
+
+	Adapter->FWReleaseNumber = hwspec->FWReleaseNumber;
+
+	PRINTM(INFO, "GET_HW_SPEC: FWReleaseVersion- 0x%X\n",
+	       Adapter->FWReleaseNumber);
+	PRINTM(INFO, "GET_HW_SPEC: Permanent addr- %2x:%2x:%2x:%2x:%2x:%2x\n",
+	       hwspec->PermanentAddr[0], hwspec->PermanentAddr[1],
+	       hwspec->PermanentAddr[2], hwspec->PermanentAddr[3],
+	       hwspec->PermanentAddr[4], hwspec->PermanentAddr[5]);
+	PRINTM(INFO, "GET_HW_SPEC: HWIfVersion=0x%X  Version=0x%X\n",
+	       hwspec->HWIfVersion, hwspec->Version);
+
+	Adapter->RegionCode = wlan_le16_to_cpu(hwspec->RegionCode);
+
+	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+		/* use the region code to search for the index */
+		if (Adapter->RegionCode == libertas_region_code_to_index[i]) {
+			Adapter->RegionTableIndex = (u16) i;
+			break;
+		}
+	}
+
+	/* if it's unidentified region code, use the default (USA) */
+	if (i >= MRVDRV_MAX_REGION_CODE) {
+		Adapter->RegionCode = 0x10;
+		Adapter->RegionTableIndex = 0;
+		PRINTM(WARN,
+		       "unidentified region code, use the default (USA)\n");
+	}
+
+	if (Adapter->CurrentAddr[0] == 0xff) {
+		memmove(Adapter->CurrentAddr, hwspec->PermanentAddr,
+			ETH_ALEN);
+	}
+
+	memcpy(priv->wlan_dev.netdev->dev_addr, Adapter->CurrentAddr, ETH_ALEN);
+
+	if (libertas_set_regiontable(priv, Adapter->RegionCode, 0)) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (libertas_set_universaltable(priv, 0)) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function handles the command response of sleep_params
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_sleep_params(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_SLEEP_PARAMS *sp = &resp->params.sleep_params;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	PRINTM(INFO, "error=%x offset=%x stabletime=%x calcontrol=%x\n"
+	       " extsleepclk=%x\n", sp->Error, sp->Offset,
+	       sp->StableTime, sp->CalControl, sp->ExternalSleepClk);
+	Adapter->sp.sp_error = wlan_le16_to_cpu(sp->Error);
+	Adapter->sp.sp_offset = wlan_le16_to_cpu(sp->Offset);
+	Adapter->sp.sp_stabletime = wlan_le16_to_cpu(sp->StableTime);
+	Adapter->sp.sp_calcontrol = wlan_le16_to_cpu(sp->CalControl);
+	Adapter->sp.sp_extsleepclk = wlan_le16_to_cpu(sp->ExternalSleepClk);
+	Adapter->sp.sp_reserved = wlan_le16_to_cpu(sp->Reserved);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of sleep_params
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_sleep_period(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_SLEEP_PERIOD *sp_period =
+	    &resp->params.ps_sleeppd;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	Adapter->sleep_period.period = wlan_le16_to_cpu(sp_period->Period);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of mac_control
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_mac_control(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of set_wep
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_set_wep(wlan_private * priv,
+				   struct HostCmd_DS_COMMAND *resp)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of reset
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_reset(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp)
+{
+	ENTER();
+	PRINTM(INFO, "HWAC - Reset command successful\n");
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of statistics
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_stat(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_GET_STAT *p11Stat = &resp->params.gstat;
+	wlan_adapter *Adapter = priv->adapter;
+
+	/* TODO Convert it to Big endian befor copy */
+	memcpy(&Adapter->wlan802_11Stat,
+	       p11Stat, sizeof(struct HostCmd_DS_802_11_GET_STAT));
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of snmp_mib
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_snmp_mib(wlan_private * priv,
+				    struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_SNMP_MIB *smib = &resp->params.smib;
+	u16 OID = wlan_le16_to_cpu(smib->OID);
+	u16 QueryType = wlan_le16_to_cpu(smib->QueryType);
+
+	ENTER();
+
+	PRINTM(INFO, "SNMP_RESP: value of the OID = %x, QueryType=%x\n", OID,
+	       QueryType);
+	PRINTM(INFO, "SNMP_RESP: Buf size  = %x\n",
+	       wlan_le16_to_cpu(smib->BufSize));
+
+	if (QueryType == HostCmd_ACT_GEN_GET) {
+		switch (OID) {
+		case FragThresh_i:
+			priv->adapter->FragThsd =
+			    wlan_le16_to_cpu(*
+					     ((unsigned short *)(smib->Value)));
+			PRINTM(INFO, "SNMP_RESP: FragThsd =%u\n",
+			       priv->adapter->FragThsd);
+			break;
+		case RtsThresh_i:
+			priv->adapter->RTSThsd =
+			    wlan_le16_to_cpu(*
+					     ((unsigned short *)(smib->Value)));
+			PRINTM(INFO, "SNMP_RESP: RTSThsd =%u\n",
+			       priv->adapter->RTSThsd);
+			break;
+		case ShortRetryLim_i:
+			priv->adapter->TxRetryCount =
+			    wlan_le16_to_cpu(*
+					     ((unsigned short *)(smib->Value)));
+			PRINTM(INFO, "SNMP_RESP: TxRetryCount =%u\n",
+			       priv->adapter->RTSThsd);
+			break;
+		default:
+			break;
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of radio_control
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_radio_control(wlan_private * priv,
+					 struct HostCmd_DS_COMMAND *resp)
+{
+	ENTER();
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of key_material
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_key_material(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_KEY_MATERIAL *pKey = &resp->params.keymaterial;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (pKey->Action == HostCmd_ACT_SET)
+		Adapter->IsGTK_SET = 1;
+
+	memcpy(Adapter->aeskey.KeyParamSet.Key, pKey->KeyParamSet.Key,
+	       sizeof(pKey->KeyParamSet.Key));
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of mac_address
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_mac_address(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_MAC_ADDRESS *MacAdd = &resp->params.macadd;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	memcpy(Adapter->CurrentAddr, MacAdd->MacAdd, ETH_ALEN);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of rf_tx_power
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_rf_tx_power(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_RF_TX_POWER *rtp = &resp->params.txp;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	Adapter->TxPowerLevel = wlan_le16_to_cpu(rtp->CurrentLevel);
+
+	PRINTM(INFO, "Current TxPower Level = %d\n", Adapter->TxPowerLevel);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of rf_antenna
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_rf_antenna(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_RF_ANTENNA *pAntenna = &resp->params.rant;
+	wlan_adapter *Adapter = priv->adapter;
+	u16 Action = wlan_le16_to_cpu(pAntenna->Action);
+
+	if (Action == HostCmd_ACT_GET_RX)
+		Adapter->RxAntennaMode =
+		    wlan_le16_to_cpu(pAntenna->AntennaMode);
+
+	if (Action == HostCmd_ACT_GET_TX)
+		Adapter->TxAntennaMode =
+		    wlan_le16_to_cpu(pAntenna->AntennaMode);
+
+	PRINTM(INFO, "RF_ANT_RESP: Action = 0x%x, Mode = 0x%04x\n",
+	       Action, wlan_le16_to_cpu(pAntenna->AntennaMode));
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of multicast_address
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_mac_multicast_adr(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *resp)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of rate_adapt_rateset
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_rate_adapt_rateset(wlan_private * priv,
+					      struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_RATE_ADAPT_RATESET *rates =
+	    &resp->params.rateset;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (rates->Action == HostCmd_ACT_GET) {
+		Adapter->EnableHwAuto = rates->EnableHwAuto;
+		Adapter->RateBitmap = rates->Bitmap;
+	}
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of data_rate
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_data_rate(wlan_private * priv,
+				     struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_DATA_RATE *pDataRate = &resp->params.drate;
+	wlan_adapter *Adapter = priv->adapter;
+	u8 Dot11DataRate;
+
+	ENTER();
+
+	HEXDUMP("DATA_RATE_RESP: data_rate- ",
+		(u8 *) pDataRate, sizeof(struct HostCmd_DS_802_11_DATA_RATE));
+
+	Dot11DataRate = pDataRate->DataRate[0];
+	if (pDataRate->Action == HostCmd_ACT_GET_TX_RATE) {
+		memcpy(Adapter->libertas_supported_rates, pDataRate->DataRate,
+		       sizeof(Adapter->libertas_supported_rates));
+	}
+	Adapter->DataRate = libertas_index_to_data_rate(Dot11DataRate);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of rf_channel
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_rf_channel(wlan_private * priv,
+				      struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_RF_CHANNEL *rfchannel =
+	    &resp->params.rfchannel;
+	wlan_adapter *Adapter = priv->adapter;
+	u16 Action = wlan_le16_to_cpu(rfchannel->Action);
+	u16 newChannel = wlan_le16_to_cpu(rfchannel->CurrentChannel);
+
+	ENTER();
+
+	if (Action == HostCmd_OPT_802_11_RF_CHANNEL_GET
+	    && Adapter->CurBssParams.channel != newChannel) {
+		PRINTM(INFO, "Channel Switch: %d to %d\n",
+		       Adapter->CurBssParams.channel, newChannel);
+
+		/* Update the channel again */
+		Adapter->CurBssParams.channel = newChannel;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of rssi
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_rssi(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_RSSI_RSP *rssirsp = &resp->params.rssirsp;
+	wlan_adapter *Adapter = priv->adapter;
+
+	/* store the non average value */
+	Adapter->SNR[TYPE_BEACON][TYPE_NOAVG] = wlan_le16_to_cpu(rssirsp->SNR);
+	Adapter->NF[TYPE_BEACON][TYPE_NOAVG] =
+	    wlan_le16_to_cpu(rssirsp->NoiseFloor);
+
+	Adapter->SNR[TYPE_BEACON][TYPE_AVG] = wlan_le16_to_cpu(rssirsp->AvgSNR);
+	Adapter->NF[TYPE_BEACON][TYPE_AVG] =
+	    wlan_le16_to_cpu(rssirsp->AvgNoiseFloor);
+
+	Adapter->RSSI[TYPE_BEACON][TYPE_NOAVG] =
+	    CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
+		     Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+
+	Adapter->RSSI[TYPE_BEACON][TYPE_AVG] =
+	    CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE,
+		     Adapter->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE);
+
+	PRINTM(INFO, "Beacon RSSI value = 0x%x\n",
+	       Adapter->RSSI[TYPE_BEACON][TYPE_AVG]);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of eeprom_access
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_802_11_eeprom_access(wlan_private * priv,
+				  struct HostCmd_DS_COMMAND *resp)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	wlan_ioctl_regrdwr *pBuf = (wlan_ioctl_regrdwr *) Adapter->pRdeeprom;
+	PRINTM(INFO, "eeprom read len=%x\n",
+	       wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount));
+	if (pBuf->NOB < wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount)) {
+		pBuf->NOB = 0;
+		PRINTM(INFO, "eeprom read return length is too big\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	pBuf->NOB = wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount);
+	if (pBuf->NOB > 0) {
+
+		memcpy(&pBuf->Value, (u8 *) & resp->params.rdeeprom.Value,
+		       wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount));
+		HEXDUMP("Adapter", (char *)&pBuf->Value,
+			wlan_le16_to_cpu(resp->params.rdeeprom.ByteCount));
+	}
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response of get_log
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp	   A pointer to HostCmd_DS_COMMAND
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_ret_get_log(wlan_private * priv,
+			    struct HostCmd_DS_COMMAND *resp)
+{
+	struct HostCmd_DS_802_11_GET_LOG *LogMessage =
+	    (struct HostCmd_DS_802_11_GET_LOG *)&resp->params.glog;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* TODO Convert it to Big Endian before copy */
+	memcpy(&Adapter->LogMsg, LogMessage,
+	       sizeof(struct HostCmd_DS_802_11_GET_LOG));
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the command response
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_process_rx_command(wlan_private * priv)
+{
+	u16 RespCmd;
+	struct HostCmd_DS_COMMAND *resp;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	ulong flags;
+	u16 Result;
+
+	ENTER();
+
+	PRINTM(INFO, "CMD_RESP: @ %lu\n", jiffies);
+
+	/* Now we got response from FW, cancel the command timer */
+	del_timer(&Adapter->command_timer);
+
+	if (!Adapter->CurCmd) {
+		PRINTM(INFO, "CMD_RESP: NULL CurCmd=%p\n", Adapter->CurCmd);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+	resp = (struct HostCmd_DS_COMMAND *)(Adapter->CurCmd->BufVirtualAddr);
+
+	HEXDUMP("CMD_RESP:", Adapter->CurCmd->BufVirtualAddr,
+		priv->wlan_dev.upld_len);
+
+	RespCmd = wlan_le16_to_cpu(resp->Command);
+
+	Result = wlan_le16_to_cpu(resp->Result);
+
+	PRINTM(INFO, "CMD_RESP: %x Result: %d Length: %d\n", RespCmd,
+	       Result, priv->wlan_dev.upld_len);
+
+	if (!(RespCmd & 0x8000)) {
+		PRINTM(INFO, "Invalid response to command!");
+		Adapter->CurCmdRetCode = WLAN_STATUS_FAILURE;
+		libertas_cleanup_and_insert_cmd(priv, Adapter->CurCmd);
+		spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+		Adapter->CurCmd = NULL;
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Store the response code to CurCmdRetCode. */
+	Adapter->CurCmdRetCode = wlan_le16_to_cpu(resp->Result);
+
+	if (RespCmd == HostCmd_RET_802_11_PS_MODE) {
+		struct HostCmd_DS_802_11_PS_MODE *psmode;
+
+		psmode = &resp->params.psmode;
+		PRINTM(INFO,
+		       "CMD_RESP: PS_MODE cmd reply result=%#x action=0x%X\n",
+		       resp->Result, psmode->Action);
+		psmode->Action = wlan_cpu_to_le16(psmode->Action);
+
+		if (Result) {
+			PRINTM(INFO, "CMD_RESP: PS command failed- %#x \n",
+			       resp->Result);
+			if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
+				/* 
+				 * We should not re-try enter-ps command in 
+				 * ad-hoc mode. It takes place in 
+				 * libertas_execute_next_command().
+				 */
+				if (psmode->Action == HostCmd_SubCmd_Enter_PS)
+					Adapter->PSMode =
+					    Wlan802_11PowerModeCAM;
+			}
+		} else if (psmode->Action == HostCmd_SubCmd_Enter_PS) {
+			Adapter->NeedToWakeup = 0;
+			Adapter->PSState = PS_STATE_AWAKE;
+
+			PRINTM(INFO, "CMD_RESP: Enter_PS command response\n");
+			if (Adapter->MediaConnectStatus !=
+			    WlanMediaStateConnected) {
+				/*
+				 * When Deauth Event received before Enter_PS command
+				 * response, We need to wake up the firmware.
+				 */
+				PRINTM(INFO,
+				       "Disconnected, Going to invoke libertas_ps_wakeup\n");
+				libertas_ps_wakeup(priv, 0);
+			}
+		} else if (psmode->Action == HostCmd_SubCmd_Exit_PS) {
+			Adapter->NeedToWakeup = 0;
+			Adapter->PSState = PS_STATE_FULL_POWER;
+			PRINTM(INFO, "CMD_RESP: Exit_PS command response\n");
+		} else {
+			PRINTM(INFO, "CMD_RESP: PS- Action=0x%X\n",
+			       psmode->Action);
+		}
+
+		libertas_cleanup_and_insert_cmd(priv, Adapter->CurCmd);
+		spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+		Adapter->CurCmd = NULL;
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	if (Adapter->CurCmd->CmdFlags & CMD_F_HOSTCMD) {
+		/* Copy the response back to response buffer */
+		memcpy(Adapter->CurCmd->pdata_buf, resp, resp->Size);
+
+		Adapter->CurCmd->CmdFlags &= ~CMD_F_HOSTCMD;
+	}
+
+	/* If the command is not successful, cleanup and return failure */
+	if ((Result != HostCmd_RESULT_OK || !(RespCmd & 0x8000))) {
+		PRINTM(INFO, "CMD_RESP: command reply %#x result=%#x\n",
+		       resp->Command, resp->Result);
+		/*
+		 * Handling errors here
+		 */
+		switch (RespCmd) {
+		case HostCmd_RET_HW_SPEC_INFO:
+		case HostCmd_RET_802_11_RESET:
+			PRINTM(INFO, "CMD_RESP: Reset command Failed\n");
+			Adapter->HardwareStatus = WlanHardwareStatusNotReady;
+			break;
+
+		}
+
+		libertas_cleanup_and_insert_cmd(priv, Adapter->CurCmd);
+		spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+		Adapter->CurCmd = NULL;
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+		return WLAN_STATUS_FAILURE;
+	}
+
+	switch (RespCmd) {
+	case HostCmd_RET_MAC_REG_ACCESS:
+	case HostCmd_RET_BBP_REG_ACCESS:
+	case HostCmd_RET_RF_REG_ACCESS:
+		ret = wlan_ret_reg_access(priv, RespCmd, resp);
+		break;
+
+	case HostCmd_RET_HW_SPEC_INFO:
+		ret = wlan_ret_get_hw_spec(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_SCAN:
+		ret = libertas_ret_80211_scan(priv, resp);
+		break;
+
+	case HostCmd_RET_MAC_CONTROL:
+		ret = wlan_ret_mac_control(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_GET_LOG:
+		ret = wlan_ret_get_log(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_ASSOCIATE:
+	case HostCmd_RET_802_11_REASSOCIATE:
+		ret = libertas_ret_80211_associate(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_DISASSOCIATE:
+	case HostCmd_RET_802_11_DEAUTHENTICATE:
+		ret = libertas_ret_80211_disassociate(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_SET_WEP:
+		ret = wlan_ret_802_11_set_wep(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_AD_HOC_START:
+	case HostCmd_RET_802_11_AD_HOC_JOIN:
+		ret = libertas_ret_80211_ad_hoc_start(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_RESET:
+		ret = wlan_ret_802_11_reset(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_AUTHENTICATE:
+		ret = libertas_ret_80211_authenticate(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_STAT:
+		ret = wlan_ret_802_11_stat(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_SNMP_MIB:
+		ret = wlan_ret_802_11_snmp_mib(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_RF_TX_POWER:
+		ret = wlan_ret_802_11_rf_tx_power(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_RADIO_CONTROL:
+		ret = wlan_ret_802_11_radio_control(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_SET_AFC:
+	case HostCmd_RET_802_11_GET_AFC:
+		memmove(Adapter->CurCmd->pdata_buf,
+			&resp->params.afc,
+			sizeof(struct HostCmd_DS_802_11_AFC));
+
+		break;
+	case HostCmd_RET_802_11_RF_ANTENNA:
+		ret = wlan_ret_802_11_rf_antenna(priv, resp);
+		break;
+
+	case HostCmd_RET_MAC_MULTICAST_ADR:
+		ret = wlan_ret_mac_multicast_adr(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_DATA_RATE:
+		ret = wlan_ret_802_11_data_rate(priv, resp);
+		break;
+	case HostCmd_RET_802_11_RATE_ADAPT_RATESET:
+		ret = wlan_ret_802_11_rate_adapt_rateset(priv, resp);
+		break;
+	case HostCmd_RET_802_11_RF_CHANNEL:
+		ret = wlan_ret_802_11_rf_channel(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_RSSI:
+		ret = wlan_ret_802_11_rssi(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_MAC_ADDRESS:
+		ret = wlan_ret_802_11_mac_address(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_AD_HOC_STOP:
+		ret = libertas_ret_80211_ad_hoc_stop(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_BEACON_STOP:
+		break;
+
+	case HostCmd_RET_802_11_ENABLE_RSN:
+		break;
+	case HostCmd_RET_802_11_KEY_MATERIAL:
+		PRINTM(INFO, "CMD_RESP: KEY_MATERIAL command response\n");
+		ret = wlan_ret_802_11_key_material(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_EEPROM_ACCESS:
+		ret = wlan_ret_802_11_eeprom_access(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11D_DOMAIN_INFO:
+		ret = libertas_ret_802_11d_domain_info(priv, resp);
+		break;
+
+	case HostCmd_RET_802_11_SLEEP_PARAMS:
+		ret = wlan_ret_802_11_sleep_params(priv, resp);
+		break;
+	case HostCmd_RET_802_11_INACTIVITY_TIMEOUT:
+		*((u16 *) Adapter->CurCmd->pdata_buf) =
+		    wlan_le16_to_cpu(resp->params.inactivity_timeout.Timeout);
+		break;
+
+	case HostCmd_RET_802_11_SLEEP_PERIOD:
+		ret = wlan_ret_802_11_sleep_period(priv, resp);
+		break;
+	case HostCmd_RET_802_11_TPC_CFG:
+		memmove(Adapter->CurCmd->pdata_buf,
+			&resp->params.tpccfg,
+			sizeof(struct HostCmd_DS_802_11_TPC_CFG));
+		break;
+	case HostCmd_RET_802_11_LED_GPIO_CTRL:
+		memmove(Adapter->CurCmd->pdata_buf,
+			&resp->params.ledgpio,
+			sizeof(struct HostCmd_DS_802_11_LED_CTRL));
+		break;
+	case HostCmd_RET_802_11_PWR_CFG:
+		memmove(Adapter->CurCmd->pdata_buf,
+			&resp->params.pwrcfg,
+			sizeof(struct HostCmd_DS_802_11_PWR_CFG));
+
+		break;
+
+	case HostCmd_RET_GET_TSF:
+		memcpy(priv->adapter->CurCmd->pdata_buf,
+		       &resp->params.gettsf.TsfValue, sizeof(u64));
+		break;
+	case HostCmd_RET_DFT_ACCESS:
+		if (Adapter->CurCmd->pdata_buf)
+			memcpy(Adapter->CurCmd->pdata_buf,
+			       &resp->params.dft.addr1, 2 * ETH_ALEN);
+		break;
+	case HostCmd_RTE_802_11_TX_RATE_QUERY:
+		priv->adapter->TxRate = resp->params.txrate.TxRate;
+		break;
+	default:
+		PRINTM(INFO, "CMD_RESP: Unknown command response %#x\n",
+		       resp->Command);
+		break;
+	}
+
+	if (Adapter->CurCmd) {
+		/* Clean up and Put current command back to CmdFreeQ */
+		libertas_cleanup_and_insert_cmd(priv, Adapter->CurCmd);
+		spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+		Adapter->CurCmd = NULL;
+		spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+	}
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function handles events generated by firmware
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_process_event(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	PRINTM(INFO, "EVENT Cause %x\n", Adapter->EventCause);
+
+	switch (Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT) {
+	case MACREG_INT_CODE_LINK_SENSED:
+		PRINTM(INFO, "EVENT: MACREG_INT_CODE_LINK_SENSED\n");
+		break;
+
+	case MACREG_INT_CODE_DEAUTHENTICATED:
+		PRINTM(INFO, "EVENT: Deauthenticated\n");
+		HandleDisconnectEvent(priv);
+		break;
+
+	case MACREG_INT_CODE_DISASSOCIATED:
+		PRINTM(INFO, "EVENT: Disassociated\n");
+		HandleDisconnectEvent(priv);
+		break;
+
+	case MACREG_INT_CODE_LINK_LOSE_NO_SCAN:
+		PRINTM(INFO, "EVENT: Link lost\n");
+		HandleDisconnectEvent(priv);
+		break;
+
+	case MACREG_INT_CODE_PS_SLEEP:
+		PRINTM(INFO, "EVENT: SLEEP\n");
+		PRINTM(INFO, "_");
+
+		/* handle unexpected PS SLEEP event */
+		if (Adapter->PSState == PS_STATE_FULL_POWER) {
+			PRINTM(INFO,
+			       "EVENT: In FULL POWER mode - ignore PS SLEEP\n");
+			break;
+		}
+		Adapter->PSState = PS_STATE_PRE_SLEEP;
+
+		libertas_ps_confirm_sleep(priv, (u16) Adapter->PSMode);
+
+		break;
+
+	case MACREG_INT_CODE_PS_AWAKE:
+		PRINTM(INFO, "EVENT: AWAKE \n");
+		PRINTM(INFO, "|");
+
+		/* handle unexpected PS AWAKE event */
+		if (Adapter->PSState == PS_STATE_FULL_POWER) {
+			PRINTM(INFO,
+			       "EVENT: In FULL POWER mode - ignore PS AWAKE\n");
+			break;
+		}
+
+		Adapter->TxLockFlag = 0;
+		if (libertas_check_last_packet_indication(priv)) {
+			if (Adapter->gen_null_pkg) {
+				libertas_send_null_packet(priv,
+					       MRVDRV_TxPD_POWER_MGMT_NULL_PACKET
+					       |
+					       MRVDRV_TxPD_POWER_MGMT_LAST_PACKET);
+				Adapter->TxLockFlag = 1;
+			}
+		}
+
+		Adapter->PSState = PS_STATE_AWAKE;
+
+		if (Adapter->NeedToWakeup) {
+			/*
+			 * wait for the command processing to finish
+			 * before resuming sending 
+			 * Adapter->NeedToWakeup will be set to FALSE 
+			 * in libertas_ps_wakeup()
+			 */
+			PRINTM(INFO, "Waking up...\n");
+			libertas_ps_wakeup(priv, 0);
+		}
+		break;
+
+	case MACREG_INT_CODE_MIC_ERR_UNICAST:
+		PRINTM(INFO, "EVENT: UNICAST MIC ERROR\n");
+		HandleMICFailureEvent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST);
+		break;
+
+	case MACREG_INT_CODE_MIC_ERR_MULTICAST:
+		PRINTM(INFO, "EVENT: MULTICAST MIC ERROR\n");
+		HandleMICFailureEvent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST);
+		break;
+	case MACREG_INT_CODE_MIB_CHANGED:
+	case MACREG_INT_CODE_INIT_DONE:
+		break;
+
+	case MACREG_INT_CODE_ADHOC_BCN_LOST:
+		PRINTM(INFO, "EVENT: HWAC - ADHOC BCN LOST\n");
+		break;
+
+	case MACREG_INT_CODE_RSSI_LOW:
+		PRINTM(MSG, "EVENT: RSSI_LOW\n");
+		break;
+	case MACREG_INT_CODE_SNR_LOW:
+		PRINTM(MSG, "EVENT: SNR_LOW\n");
+		break;
+	case MACREG_INT_CODE_MAX_FAIL:
+		PRINTM(MSG, "EVENT: MAX_FAIL\n");
+		break;
+	case MACREG_INT_CODE_RSSI_HIGH:
+		PRINTM(MSG, "EVENT: RSSI_HIGH\n");
+		break;
+	case MACREG_INT_CODE_SNR_HIGH:
+		PRINTM(MSG, "EVENT: SNR_HIGH\n");
+		break;
+
+	default:
+		PRINTM(INFO, "EVENT: unknown event id: %#x\n",
+		       Adapter->EventCause >> SBI_EVENT_CAUSE_SHIFT);
+		break;
+	}
+
+	Adapter->EventCause = 0;
+	LEAVE();
+	return ret;
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/Makefile linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/Makefile
--- linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/Makefile	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/Makefile	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,61 @@
+#
+# File : app/Makefile
+#
+# (c) Copyright © 2003-2006, Marvell International Ltd. 
+# All Rights Reserved
+#
+# This software file (the "File") is distributed by Marvell International 
+# Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+# (the "License").  You may use, redistribute and/or modify this File in 
+# accordance with the terms and conditions of the License, a copy of which 
+# is available along with the File in the license.txt file or by writing to 
+# the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+# 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+#
+# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+# ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+# this warranty disclaimer.
+#
+
+# Path to the top directory of the wlan distribution
+PATH_TO_TOP = ..
+
+# Determine how we should copy things to the install directory
+ABSPATH := $(filter /%, $(INSTALLDIR))
+RELPATH := $(filter-out /%, $(INSTALLDIR))
+INSTALLPATH := $(ABSPATH)
+ifeq ($(strip $(INSTALLPATH)),)
+INSTALLPATH := $(PATH_TO_TOP)/$(RELPATH)
+endif
+
+# Override CFLAGS for application sources, remove __ kernel namespace defines
+CFLAGS := $(filter-out -D__%, $(CFLAGS))
+
+# Add the wlan driver directory to the preprocessor include path
+CFLAGS +=  -I$(PATH_TO_TOP)/
+
+#
+# List of application executables to create
+#
+TARGETS := wlanconfig
+
+#
+# Make target rules
+#
+
+# All rule compiles list of TARGETS using builtin program target from src rule
+all : $(TARGETS)
+
+# Install rule; INSTALLPATH calculated above from passed INSTALLDIR variable
+$(INSTALLPATH)/% : ./%
+	@cp -f $< $@
+
+# Map build and install invocation to the install rule for each TARGET file
+build install: $(addprefix $(INSTALLPATH)/, $(TARGETS))
+
+clean:
+	@rm -f $(TARGETS)
+
+distclean: clean
+	@rm -f *~ core
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/wlanconfig.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,2255 @@
+/** @file  wlanconfig.c
+  * @brief Program to configure addition paramters into the wlan driver
+  * 
+  *  Usage: wlanconfig <ethX> <cmd> [...] 
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/12/05: Add Doxygen format comments
+	11/03/05: Load priv ioctls on demand, ifdef code for features in driver
+	11/04/05: Add crypto_test 
+	12/14/05: Support wildcard SSID in BGSCAN	
+	01/11/06: Add getscantable, setuserscan, setmrvltlv, getassocrsp 
+	01/31/06: Add support to selectively enabe the FW Scan channel filter	
+	02/24/06: fix getscanlist function not work on linux 2.6.15 X86
+	04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+	04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+********************************************************/
+
+#include    <stdio.h>
+#include    <unistd.h>
+#include    <time.h>
+#include    <ctype.h>
+#include    <sys/types.h>
+#include    <sys/socket.h>
+#include    <string.h>
+#include    <stdlib.h>
+#include    <linux/if.h>
+#include    <sys/ioctl.h>
+#include    <linux/wireless.h>
+#include    <linux/if_ether.h>
+#include    <linux/byteorder/swab.h>
+#include    <errno.h>
+
+typedef unsigned char		u8;
+typedef unsigned short  	u16;
+typedef unsigned long		u32;
+typedef unsigned long long	u64;
+typedef char		s8;
+typedef short  		s16;
+typedef long		s32;
+
+#ifdef 	BYTE_SWAP
+#define 	cpu_to_le16(x)	__swab16(x)
+#else
+#define		cpu_to_le16(x)	(x)
+#endif
+
+#ifndef __ATTRIB_ALIGN__
+#define __ATTRIB_ALIGN__ __attribute__((aligned(4)))
+#endif
+
+#ifndef __ATTRIB_PACK__
+#define __ATTRIB_PACK__  __attribute__((packed))
+#endif
+
+/*
+ *  ctype from older glib installations defines BIG_ENDIAN.  Check it 
+ *   and undef it if necessary to correctly process the wlan header
+ *   files
+ */
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+#undef BIG_ENDIAN
+#endif
+
+#include	"wlan_defs.h"
+#include	"wlan_types.h"
+#include    "wlan_11d.h"
+#include	"host.h"
+#include	"hostcmd.h"
+#include    "wlan_scan.h"
+#include	"wlan_wext.h"
+#include	"wlanconfig.h"
+
+enum COMMANDS {
+	CMD_HOSTCMD,
+	CMD_RDMAC,
+	CMD_WRMAC,
+	CMD_RDBBP,
+	CMD_WRBBP,
+	CMD_RDRF,
+	CMD_WRRF,
+	CMD_RDEEPROM,
+	CMD_CMD52R,
+	CMD_CMD52W,
+	CMD_CMD53R,
+	CMD_CMD53W,
+	CMD_CFREGR,
+	CMD_CFREGW,
+	CMD_GETRATE,
+	CMD_SLEEPPARAMS,
+    CMD_BCA_TS,
+	CMD_EXTSCAN,
+	CMD_SCAN_LIST,
+	CMD_GET_SCAN_RSP,
+	CMD_SET_USER_SCAN,
+};
+
+#define IW_MAX_PRIV_DEF		128
+
+/********************************************************
+		Local Variables
+********************************************************/
+static s8    *commands[] = {
+	"hostcmd",
+	"rdmac",
+	"wrmac",
+	"rdbbp",
+	"wrbbp",
+	"rdrf",
+	"wrrf",
+	"rdeeprom",
+	"sdcmd52r",
+	"sdcmd52w",
+	"sdcmd53r",
+	"sdcmd53w",
+	"rdcfreg",
+	"wrcfreg",
+	"getrate",
+	"sleepparams",
+	"bca-ts",
+	"extscan",
+	"getscanlist",
+	"getscantable",
+	"setuserscan",
+};
+
+static s8    *usage[] = {
+	"Usage: wlanconfig <ethX> <cmd> [...]",
+	"where",
+	"	ethX	: wireless network interface",
+	"	cmd	: hostcmd, rdmac, wrmac, rdbbp, wrbbp, rdrf, wrrf",
+	"		: sdcmd52r, sdcmd52w, sdcmd53r",
+	"		: caldataext, rdcfreg, wrcfreg, rdeeprom",
+    "		: sleepparams, bca-ts",
+	"		: setadhocch, getadhocch",
+	"		: getscantable, setuserscan",
+	"	[...]	: additional parameters for read registers are",
+	"		:	<offset>",
+	"		: additional parameters for write registers are",
+	"		:	<offset> <value>",
+	"		: additonal parameter for hostcmd",
+	"		: 	<filename> <cmd>",
+	"		: addition parameters for caldataext",
+	"		: 	<filename>",
+};
+
+static s32  sockfd;
+static s8	dev_name[IFNAMSIZ + 1];
+static struct iw_priv_args	Priv_args[IW_MAX_PRIV_DEF];
+static int we_version_compiled=0;
+#define MRV_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \
+			  (char *) NULL)
+
+
+
+static s8 * wlan_config_get_line(s8 *s, s32 size, FILE *stream, int *line);
+
+/********************************************************
+		Global Variables
+********************************************************/
+
+
+/********************************************************
+		Local Functions
+********************************************************/
+/** 
+ *  @brief convert char to hex integer
+ * 
+ *  @param chr 		char to convert
+ *  @return      	hex integer or 0
+ */
+static int hexval(s32 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		return chr - '0';
+	if (chr >= 'A' && chr <= 'F')
+		return chr - 'A' + 10;
+	if (chr >= 'a' && chr <= 'f')
+		return chr - 'a' + 10;
+
+	return 0;
+}
+
+/** 
+ *  @brief Hump hex data
+ *
+ *  @param prompt	A pointer prompt buffer
+ *  @param p		A pointer to data buffer
+ *  @param len		the len of data buffer
+ *  @param delim	delim char
+ *  @return            	hex integer
+ */
+static void hexdump(s8 *prompt, void *p, s32 len, s8 delim)
+{
+	s32             i;
+	u8  *s = p;
+	
+    if (prompt) {
+        printf("%s: ", prompt);
+    }
+	for (i = 0; i < len; i++) {
+		if (i != len - 1)
+			printf("%02x%c", *s++, delim);
+		else
+			printf("%02x\n", *s);
+	}
+}
+
+/** 
+ *  @brief convert char to hex integer
+ *
+ *  @param chr		char
+ *  @return            	hex integer
+ */
+static u8 hexc2bin(s8 chr)
+{
+	if (chr >= '0' && chr <= '9')
+		chr -= '0';
+	else if (chr >= 'A' && chr <= 'F')
+		chr -= ('A' - 10);
+	else if (chr >= 'a' && chr <= 'f')
+		chr -= ('a' - 10);
+
+	return chr;
+}
+
+/** 
+ *  @brief convert string to hex integer
+ *
+ *  @param s		A pointer string buffer
+ *  @return            	hex integer
+ */
+static u32 a2hex(s8 *s)
+{
+	u32    val = 0;
+	while (*s && isxdigit(*s)) {
+		val = (val << 4) + hexc2bin(*s++);
+	}
+
+	return val;
+}
+
+
+/* 
+ *  @brief convert String to integer
+ *  
+ *  @param value	A pointer to string
+ *  @return             integer
+ */
+static u32 a2hex_or_atoi(s8 *value)
+{
+	if (value[0] == '0' && (value[1] == 'X' || value[1] == 'x'))
+		return a2hex(value + 2);
+	else
+		return atoi(value);
+}
+
+
+/** 
+ *  @brief convert string to integer
+ * 
+ *  @param ptr		A pointer to data buffer
+ *  @param chr 		A pointer to return integer
+ *  @return      	A pointer to next data field
+ */
+s8 *convert2hex(s8 *ptr, u8 *chr)
+{
+	u8	val;
+
+	for (val = 0; *ptr && isxdigit(*ptr); ptr++) {
+		val = (val * 16) + hexval(*ptr);
+	}
+
+	*chr = val;
+
+	return ptr;
+}
+
+/** 
+ *  @brief Get private info.
+ *   
+ *  @param ifname   A pointer to net name
+ *  @return 	    WLAN_STATUS_SUCCESS--success, otherwise --fail
+ */
+static int get_private_info(const s8 *ifname)
+{
+	/* This function sends the SIOCGIWPRIV command which is
+	 * handled by the kernel. and gets the total number of
+	 * private ioctl's available in the host driver.
+	 */
+	struct iwreq iwr;
+	int s, ret = WLAN_STATUS_SUCCESS;
+	struct iw_priv_args *pPriv = Priv_args;
+
+	s = socket(PF_INET, SOCK_DGRAM, 0);
+	if (s < 0) {
+		perror("socket[PF_INET,SOCK_DGRAM]");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, ifname, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) pPriv;
+	iwr.u.data.length = IW_MAX_PRIV_DEF;
+	iwr.u.data.flags = 0;
+	      
+	if (ioctl(s, SIOCGIWPRIV, &iwr) < 0) {
+		perror("ioctl[SIOCGIWPRIV]");
+		ret = WLAN_STATUS_FAILURE;
+	} else {
+		/* Return the number of private ioctls */
+		ret = iwr.u.data.length;
+	}
+
+	close(s);
+
+	return ret;
+}
+
+/** 
+ *  @brief Get Sub command ioctl number
+ *   
+ *  @param i        command index
+ *  @param priv_cnt     Total number of private ioctls availabe in driver
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *  @return 	        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int marvell_get_subioctl_no(s32 i, 
+                                   s32 priv_cnt,
+                                   int *ioctl_val,
+                                   int *subioctl_val)
+{
+	s32 j;
+
+	if (Priv_args[i].cmd >= SIOCDEVPRIVATE) {
+        *ioctl_val    = Priv_args[i].cmd;
+        *subioctl_val = 0;
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	j = -1;
+
+	/* Find the matching *real* ioctl */
+
+	while ((++j < priv_cnt) 
+           && ((Priv_args[j].name[0] != '\0') ||
+               (Priv_args[j].set_args != Priv_args[i].set_args) ||
+               (Priv_args[j].get_args != Priv_args[i].get_args))) {
+    }
+
+	/* If not found... */
+	if (j == priv_cnt) {
+		printf("%s: Invalid private ioctl definition for: 0x%x\n",
+					dev_name, Priv_args[i].cmd);
+		return  WLAN_STATUS_FAILURE;
+	}
+
+	/* Save ioctl numbers */
+	*ioctl_val    = Priv_args[j].cmd;
+	*subioctl_val = Priv_args[i].cmd;
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get ioctl number
+ *   
+ *  @param ifname   	A pointer to net name
+ *  @param priv_cmd	A pointer to priv command buffer
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *  @return 	        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int marvell_get_ioctl_no(const s8 *ifname, 
+                                const s8 *priv_cmd, 
+                                int *ioctl_val,
+                                int *subioctl_val)
+{
+	s32	i;
+    s32 priv_cnt;
+
+    priv_cnt = get_private_info(ifname);
+    
+	/* Are there any private ioctls? */
+	if (priv_cnt <= 0) {
+		/* Could skip this message ? */
+		printf("%-8.8s  no private ioctls.\n", ifname);
+	} else {
+		for (i = 0; i < priv_cnt; i++) {
+			if (Priv_args[i].name[0] && !strcmp(Priv_args[i].name, priv_cmd)) {
+                return marvell_get_subioctl_no(i, priv_cnt, 
+                                               ioctl_val, subioctl_val);
+			}
+		}
+	}
+
+    return WLAN_STATUS_FAILURE;
+}
+
+/** 
+ *  @brief Retrieve the ioctl and sub-ioctl numbers for the given ioctl string
+ *   
+ *  @param ifname       Private IOCTL string name
+ *  @param ioctl_val    A pointer to return ioctl number
+ *  @param subioctl_val A pointer to return sub-ioctl number
+ *
+ *  @return             WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int get_priv_ioctl(char* ioctl_name, int* ioctl_val, int* subioctl_val)
+{
+    int retval;
+
+    retval = marvell_get_ioctl_no(dev_name,
+                                  ioctl_name,
+                                  ioctl_val,
+                                  subioctl_val);
+    
+#if 0
+    /* Debug print discovered IOCTL values */
+    printf("ioctl %s: %x, %x\n", ioctl_name, *ioctl_val, *subioctl_val);
+#endif
+    
+    return retval;
+}
+
+
+/** 
+ *  @brief  get range 
+ *   
+ *  @return	WLAN_STATUS_SUCCESS--success, otherwise --fail
+ */
+static int get_range(void) 
+{
+	struct iw_range *range;
+	struct iwreq	iwr;
+	size_t buflen;
+	WCON_HANDLE	mhandle, *pHandle = &mhandle;
+
+	buflen = sizeof(struct iw_range) + 500;
+	range = malloc(buflen);
+	if (range == NULL)
+		return WLAN_STATUS_FAILURE;
+	memset(range, 0, buflen);
+	
+	memset(pHandle, 0, sizeof(WCON_HANDLE));
+	memset(&iwr, 0, sizeof(struct iwreq));
+	
+	iwr.u.data.pointer = (caddr_t) range;
+	iwr.u.data.length = buflen;
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+
+	if ((ioctl(sockfd, SIOCGIWRANGE, &iwr)) < 0) {
+		printf("Get Range Results Failed\n");
+		free(range);
+		return WLAN_STATUS_FAILURE;
+	}
+	we_version_compiled = range->we_version_compiled;
+	printf("Driver build with Wireless Extension %d\n",range->we_version_compiled);
+	free(range);
+	return WLAN_STATUS_SUCCESS;
+}
+#define WLAN_MAX_RATES	14
+#define	GIGA		1e9
+#define	MEGA		1e6
+#define	KILO		1e3
+
+/** 
+ *  @brief print bit rate
+ *   
+ *  @param rate  	rate to be print
+ *  @param current      if current is TRUE, data rate not need convert
+ *  @param fixed        not used
+ *  @return 	        WLAN_STATUS_SUCCESS
+ */
+static int print_bitrate(double rate, s32 current, s32 fixed) 
+{
+	s8	scale = 'k', buf[128];
+	s32	divisor = KILO;
+	
+	if (!current)
+		rate *= 500000;
+
+	if (rate >= GIGA) {
+		scale = 'G';
+		divisor = GIGA;
+	} else if (rate >= MEGA) {
+		scale = 'M';
+		divisor = MEGA;
+	}
+
+	snprintf(buf, sizeof(buf), "%g %cb/s", rate/divisor, scale);
+
+	if (current) {
+		printf("\t  Current Bit Rate%c%s\n\n",
+					(fixed) ? '=' : ':', buf);
+	} else {
+		printf("\t  %s\n", buf);
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/* 
+ *  @brief get hostcmd data
+ *  
+ *  @param fp			A pointer to file stream
+ *  @param ln			A pointer to line number
+ *  @param buf			A pointer to hostcmd data
+ *  @param size			A pointer to the return size of hostcmd buffer
+ *  @return      		WLAN_STATUS_SUCCESS
+ */
+static int wlan_get_hostcmd_data(FILE *fp, int *ln, u8 *buf, u16 *size)
+{
+	s32	errors = 0, i;
+	s8	line[256], *pos, *pos1, *pos2, *pos3;
+	u16	len;
+
+
+	while ((pos = wlan_config_get_line(line, sizeof(line), fp, ln))) {
+		(*ln)++;
+		if (strcmp(pos, "}") == 0) {
+			break;
+		}
+
+		pos1 = strchr(pos, ':');
+		if (pos1 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos);
+			errors++;
+			continue;
+		}
+		*pos1++ = '\0';
+
+		pos2 = strchr(pos1, '=');
+		if (pos2 == NULL) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos);
+			errors++;
+			continue;
+		}
+		*pos2++ = '\0';
+
+		len = a2hex_or_atoi(pos1);
+		if (len < 1 || len > MRVDRV_SIZE_OF_CMD_BUFFER) {
+			printf("Line %d: Invalid hostcmd line '%s'\n", *ln, pos);
+			errors++;
+			continue;
+		}
+
+		*size += len;
+
+		if (*pos2 == '"') {
+			pos2++;
+			if ((pos3=strchr(pos2, '"')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln, pos);
+				errors++;
+				continue;
+			}
+			*pos3 = '\0';
+			memset(buf, 0, len);
+			memmove(buf, pos2, min(strlen(pos2),len));
+			buf += len;
+		}
+		else if (*pos2 == '\'') {
+			pos2++;
+			if ((pos3=strchr(pos2, '\'')) == NULL) {
+				printf("Line %d: invalid quotation '%s'\n", *ln, pos);
+				errors++;
+				continue;
+			}
+			*pos3 = ',';
+			for (i=0; i<len; i++) {
+				if ((pos3=strchr(pos2, ',')) != NULL) {
+					*pos3 = '\0';
+					*buf++ = (u8)a2hex_or_atoi(pos2);
+					pos2 = pos3 + 1;
+				}
+				else
+					*buf++ = 0;
+			}
+		}
+		else if (*pos2 == '{') {
+			u16 *tlvlen = (u16 *)buf;
+			wlan_get_hostcmd_data(fp, ln, buf+len, tlvlen);
+			*size += *tlvlen;
+			buf += len + *tlvlen;
+		}
+		else {
+			u32 value = a2hex_or_atoi(pos2);
+			while (len--) {
+				*buf++ = (u8)(value & 0xff);
+				value >>= 8;
+			}
+		}
+	}
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Process host_cmd 
+ *  @param hostcmd      A pointer to HostCmd_DS_GEN data structure
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_host_cmd(int argc, char *argv[])
+{
+	u8		line[256], cmdname[256], *pos;
+	s8		*buf;
+	FILE		*fp;
+	struct HostCmd_DS_GEN	*hostcmd;
+	struct ifreq	userdata;
+	int 		ln = 0;
+	int		cmdname_found = 0, cmdcode_found = 0;
+	int		ret = WLAN_STATUS_SUCCESS;
+
+	if (argc < 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./wlanconfig eth1 hostcmd <hostcmd.conf> <cmdname>\n");
+		exit(1);
+	}
+	
+	if ((fp = fopen(argv[3], "r")) == NULL) {
+		fprintf(stderr, "Cannot open file %s\n", argv[4]);
+		exit(1);
+	}
+
+	buf = (u8 *)malloc(MRVDRV_SIZE_OF_CMD_BUFFER);
+	memset(buf, 0, MRVDRV_SIZE_OF_CMD_BUFFER);
+	hostcmd = (struct HostCmd_DS_GEN *)buf;
+
+	hostcmd->Command = 0xffff;
+
+	sprintf(cmdname, "%s={", argv[4]);
+	cmdname_found = 0;
+	while ((pos = wlan_config_get_line(line, sizeof(line), fp, &ln))) {
+		if (strcmp(pos, cmdname) == 0) {
+			cmdname_found = 1;
+			sprintf(cmdname, "CmdCode=");
+			cmdcode_found = 0;
+			while ((pos = wlan_config_get_line(line, sizeof(line), fp, &ln))) {
+				if (strncmp(pos, cmdname, strlen(cmdname)) == 0) {
+					cmdcode_found = 1;
+					hostcmd->Command = a2hex_or_atoi(pos+strlen(cmdname));
+					hostcmd->Size = S_DS_GEN;
+					wlan_get_hostcmd_data(fp, &ln, buf+hostcmd->Size, &hostcmd->Size);
+					break;
+				}
+			}
+			if (!cmdcode_found) {
+				fprintf(stderr, "wlanconfig: CmdCode not found in file '%s'\n", argv[3]);
+			}
+			break;
+		}
+	}
+
+	fclose(fp);
+
+	if (!cmdname_found)
+		fprintf(stderr, "wlanconfig: cmdname '%s' not found in file '%s'\n", argv[4],argv[3]);
+
+	if (!cmdname_found || !cmdcode_found) {
+		ret = -1;
+		goto _exit_;
+	}
+
+	buf = (u8 *)hostcmd;
+
+	hostcmd->SeqNum = 0;
+	hostcmd->Result = 0;
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = (u8 *)hostcmd;
+
+	if (ioctl(sockfd, WLANHOSTCMD, &userdata)) {
+		fprintf(stderr, "wlanconfig: WLANHOSTCMD is not supported by %s\n", dev_name);
+		ret = -1;
+		goto _exit_;
+   	}
+
+	if (!hostcmd->Result) {
+		switch (hostcmd->Command) {
+		case HostCmd_RET_802_11_SUBSCRIBE_EVENT:
+		{
+			struct HostCmd_DS_802_11_SUBSCRIBE_EVENT *se = (struct HostCmd_DS_802_11_SUBSCRIBE_EVENT *)(buf + S_DS_GEN);
+			if (se->Action == HostCmd_ACT_GET) {
+				int len = S_DS_GEN + sizeof(struct HostCmd_DS_802_11_SUBSCRIBE_EVENT);
+				printf("\nEvent\t\tValue\tFreq\tsubscribed\n\n");
+				while (len < hostcmd->Size) {
+					MrvlIEtypesHeader_t *header = (MrvlIEtypesHeader_t *)(buf + len);
+					switch (header->Type) {
+					case TLV_TYPE_RSSI_LOW:
+					{
+						MrvlIEtypes_RssiParamSet_t *LowRssi = (MrvlIEtypes_RssiParamSet_t *)(buf + len);
+						printf("Low RSSI\t%d\t%d\t%s\n",LowRssi->RSSIValue,LowRssi->RSSIFreq,(se->Events & 0x0001)?"yes":"no");
+						len += sizeof(MrvlIEtypes_RssiParamSet_t);
+						break;
+					}
+					case TLV_TYPE_SNR_LOW:
+					{
+						MrvlIEtypes_SnrThreshold_t *LowSnr = (MrvlIEtypes_SnrThreshold_t *)(buf + len);
+						printf("Low SNR\t\t%d\t%d\t%s\n",LowSnr->SNRValue,LowSnr->SNRFreq,(se->Events & 0x0002)?"yes":"no");
+						len += sizeof(MrvlIEtypes_SnrThreshold_t);
+						break;
+					}
+					case TLV_TYPE_FAILCOUNT:
+					{
+						MrvlIEtypes_FailureCount_t *FailureCount = (MrvlIEtypes_FailureCount_t *)(buf + len);
+						printf("Failure Count\t%d\t%d\t%s\n",FailureCount->FailValue,FailureCount->FailFreq,(se->Events & 0x0004)?"yes":"no");
+						len += sizeof(MrvlIEtypes_FailureCount_t);
+						break;
+					}
+					case TLV_TYPE_BCNMISS:
+					{
+						MrvlIEtypes_BeaconsMissed_t *BcnMissed = (MrvlIEtypes_BeaconsMissed_t *)(buf + len);
+						printf("Beacon Missed\t%d\tN/A\t%s\n",BcnMissed->BeaconMissed,(se->Events & 0x0008)?"yes":"no");
+						len += sizeof(MrvlIEtypes_BeaconsMissed_t);
+						break;
+					}
+					case TLV_TYPE_RSSI_HIGH:
+					{
+						MrvlIEtypes_RssiParamSet_t *HighRssi = (MrvlIEtypes_RssiParamSet_t *)(buf + len);
+						printf("High RSSI\t%d\t%d\t%s\n",HighRssi->RSSIValue,HighRssi->RSSIFreq,(se->Events & 0x0010)?"yes":"no");
+						len += sizeof(MrvlIEtypes_RssiParamSet_t);
+						break;
+					}
+					case TLV_TYPE_SNR_HIGH:
+					{
+						MrvlIEtypes_SnrThreshold_t *HighSnr = (MrvlIEtypes_SnrThreshold_t *)(buf + len);
+						printf("High SNR\t%d\t%d\t%s\n",HighSnr->SNRValue,HighSnr->SNRFreq,(se->Events & 0x0020)?"yes":"no");
+						len += sizeof(MrvlIEtypes_SnrThreshold_t);
+						break;
+					}
+					default:
+						printf("unknown subscribed event TLV Type=%#x, Len=%d\n", header->Type, header->Len);
+						len += sizeof(MrvlIEtypesHeader_t) + header->Len;
+						break;
+					}
+				}
+			}
+			break;
+		}
+		default:
+			printf("HOSTCMD_RESP: ReturnCode=%#04x, Result=%#04x\n",hostcmd->Command,hostcmd->Result);
+			break;
+		}
+	}
+	else {
+		printf("HOSTCMD failed: ReturnCode=%#04x, Result=%#04x\n",hostcmd->Command,hostcmd->Result);
+	}
+
+_exit_:
+	if (buf)
+		free(buf);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get Rate
+ *   
+ *  @return      WLAN_STATUS_SUCCESS--success, otherwise --fail
+ */
+static int process_get_rate(void)
+{
+	u32	bitrate[WLAN_MAX_RATES];
+	struct iwreq	iwr;
+	s32		i = 0;
+    int ioctl_val, subioctl_val;
+
+    if (get_priv_ioctl("getrate", 
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+    
+	memset(&iwr, 0, sizeof(iwr));
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) bitrate;
+	iwr.u.data.length = sizeof(bitrate);
+	iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("wlanconfig");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	printf("%-8.16s  %d available bit-rates :\n",
+					dev_name, iwr.u.data.length);
+	
+	for (i = 0; i < iwr.u.data.length; i++) {
+		print_bitrate(bitrate[i], 0, 0);
+	}
+
+	if (ioctl(sockfd, SIOCGIWRATE, &iwr)) {
+		perror("wlanconfig");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	print_bitrate(iwr.u.bitrate.value, 1, iwr.u.bitrate.fixed);
+	
+	return  WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Check the Hex String
+ *  @param s		A pointer to the string      
+ *  @return      	0--HexString, -1--not HexString
+ */
+static int ishexstring(s8 *s)
+{
+	int ret = -1;
+	s32 tmp;
+	
+	while(*s) {
+		tmp = toupper(*s);
+		if (tmp >= 'A' && tmp <= 'F') {
+			ret = 0;
+			break;
+		}
+		s++;
+	}
+	
+	return ret;
+}
+
+/** 
+ *  @brief Convert String to Integer
+ *  @param buf		A pointer to the string      
+ *  @return      	Integer
+ */
+static int atoval(s8 *buf)
+{
+	if (!strncasecmp(buf, "0x", 2))
+		return a2hex(buf+2);
+	else if (!ishexstring(buf))
+		return a2hex(buf);
+	else 	
+		return atoi(buf);
+}
+
+
+/** 
+ *  @brief Display sleep params
+ *  @param sp		A pointer to wlan_ioctl_sleep_params_config structure    
+ *  @return      	NA
+ */
+void display_sleep_params(wlan_ioctl_sleep_params_config *sp)
+{
+	printf("Sleep Params for %s:\n", sp->Action ? "set" : "get");
+   	printf("----------------------------------------\n");
+	printf("Error		: %u\n", sp->Error);
+	printf("Offset		: %u\n", sp->Offset);
+	printf("StableTime	: %u\n", sp->StableTime);
+	printf("CalControl	: %u\n", sp->CalControl);
+	printf("ExtSleepClk	: %u\n", sp->ExtSleepClk);
+	printf("Reserved	: %u\n", sp->Reserved);
+}
+
+/** 
+ *  @brief Process sleep params
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_sleep_params(int argc, char *argv[])
+{
+	struct iwreq			iwr;
+	int				ret;
+	wlan_ioctl_sleep_params_config 	sp;
+    int ioctl_val, subioctl_val;
+
+    if (get_priv_ioctl("sleepparams",
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+
+	if (argc < 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./wlanconfig eth1 sleepparams get/set <p1>"
+				" <p2> <p3> <p4> <p5> <p6>\n");
+		exit(1);
+	}
+
+	memset(&sp, 0, sizeof(wlan_ioctl_sleep_params_config));
+	if (!strcmp(argv[3], "get")) {
+		sp.Action = 0;
+	} else if (!strncmp(argv[3], "set", 3)) {
+		if (argc != 10) {
+			printf("Error: invalid no of arguments\n");
+			printf("Syntax: ./wlanconfig eth1 sleepparams get/set" 
+					"<p1> <p2> <p3> <p4> <p5> <p6>\n");
+			exit(1);
+		}
+
+		sp.Action = 1;
+		if ((ret = atoval(argv[4])) < 0)
+			return -EINVAL;
+		sp.Error = (u16) ret;
+		if ((ret = atoval(argv[5])) < 0)
+			return -EINVAL;
+		sp.Offset = (u16) ret;
+		if ((ret = atoval(argv[6])) < 0)
+			return -EINVAL;
+		sp.StableTime = (u16) ret;
+		if ((ret = atoval(argv[7])) < 0)
+			return -EINVAL;
+		sp.CalControl = (u8) ret;
+		if ((ret = atoval(argv[8])) < 0)
+			return -EINVAL;
+		sp.ExtSleepClk = (u8) ret;
+		if ((ret = atoval(argv[9])) < 0)
+			return -EINVAL;
+		sp.Reserved = (u16) ret;
+	} else 	{
+		return -EINVAL;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) &sp;
+	iwr.u.data.length = sizeof(wlan_ioctl_sleep_params_config);
+    iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("wlanconfig");
+		return -1;
+	}
+
+	display_sleep_params(&sp);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Display BCA Time Share Params
+ *  @param sp		A point to wlan_ioctl_bca_timeshare_config structure    
+ *  @return      	NA
+ */
+static void display_bca_ts_params(wlan_ioctl_bca_timeshare_config *bca_ts)
+{
+	printf("BCA Time Share Params for %s:\n", bca_ts->Action?"set" : "get");
+   	printf("----------------------------------------\n");
+	printf("TrafficType		: %u\n", bca_ts->TrafficType);	
+	printf("TimeShareInterval	: %lu\n", bca_ts->TimeShareInterval);	
+	printf("BTTime			: %lu\n", bca_ts->BTTime);	
+}
+
+/** 
+ *  @brief Process BCA Time Share Params
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_bca_ts(int argc, char *argv[]) 
+{
+	int				ret, i;
+	struct iwreq			iwr;
+	wlan_ioctl_bca_timeshare_config	bca_ts;
+    int ioctl_val, subioctl_val;
+
+    if (get_priv_ioctl("bca-ts",
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+
+	if (argc < 5) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./wlanconfig eth1 bca_ts get/set <p1>"
+								" <p2> <p3>\n");
+		exit(1);
+	}
+
+	memset(&bca_ts, 0, sizeof(wlan_ioctl_bca_timeshare_config));
+	
+	if ((ret = atoval(argv[4])) < 0)
+		return -EINVAL;
+	if (ret > 1)
+		return -EINVAL;
+	bca_ts.TrafficType = (u16) ret; // 0 or 1
+	
+	if (!strcmp(argv[3], "get")) {
+		bca_ts.Action = 0;
+	} else if (!strncmp(argv[3], "set", 3)) {
+		if (argc != 7) {
+			printf("Error: invalid no of arguments\n");
+			printf("Syntax: ./wlanconfig eth1 bca_ts get/set" 
+							" <p1> <p2> <p3>\n");
+			exit(1);
+		}
+
+		bca_ts.Action = 1;
+		
+		if ((ret = atoval(argv[5])) < 0)
+			return -EINVAL;
+		/* If value is not multiple of 10 then take the floor value */
+		i = ret % 10;
+		ret -= i;
+		/* Valid Range for TimeShareInterval: < 20 ... 60_000 > ms */
+		if (ret < 20  || ret > 60000) {
+			printf("Invalid TimeShareInterval Range:"
+						" < 20 ... 60000 > ms\n");
+			return -EINVAL;
+		}
+		bca_ts.TimeShareInterval = (u32) ret;
+		
+		if ((ret = atoval(argv[6])) < 0)
+			return -EINVAL;
+		/* If value is not multiple of 10 then take the floor value */
+		i = ret % 10;
+		ret -= i;
+		
+		if (ret > bca_ts.TimeShareInterval) {
+			printf("Invalid BTTime"
+				"  Range: < 0 .. TimeShareInterval > ms\n");
+			return -EINVAL;
+		}
+		bca_ts.BTTime = (u32) ret;
+	} else 	{
+		return -EINVAL;
+	}
+
+	memset(&iwr, 0, sizeof(iwr));
+	
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) &bca_ts;
+	iwr.u.data.length = sizeof(wlan_ioctl_bca_timeshare_config);
+    iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("wlanconfig");
+		return -1;
+	}
+
+	display_bca_ts_params(&bca_ts);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+
+
+
+/**
+ *  @brief Retrieve and display the contents of the driver scan table.
+ *
+ *  The ioctl to retrieve the scan table contents will be invoked, and portions
+ *   of the scan data will be displayed on stdout.  The entire beacon or 
+ *   probe response is also retrieved (if available in the driver).  This 
+ *   data would be needed in case the application was explicitly controlling
+ *   the association (inserting IEs, TLVs, etc).
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array    
+ *
+ *  @return         WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_getscantable(int argc, char *argv[])
+{
+    int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+    u8 scanRspBuffer[500]; /* Stack buffer can be as large as ioctl allows */
+
+    uint scanStart;
+    uint idx;
+
+    u8* pCurrent;
+    u8* pNext;
+    IEEEtypes_ElementId_e* pElementId;
+    u8* pElementLen;
+    int bssInfoLen;
+    int ssidIdx;
+    u16 tmpCap;
+    u8* pByte;
+
+    IEEEtypes_CapInfo_t capInfo;
+    u8 tsf[8];
+    u16 beaconInterval;
+
+    wlan_ioctl_get_scan_table_info* pRspInfo;
+    wlan_ioctl_get_scan_table_entry* pRspEntry;
+
+    pRspInfo = (wlan_ioctl_get_scan_table_info*)scanRspBuffer;
+    
+    if (get_priv_ioctl("getscantable", 
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+
+    scanStart = 0;
+
+    printf("---------------------------------------");
+    printf("---------------------------------------\n");
+    printf("# | ch  | ss  |       bssid       |   cap    |   SSID \n");
+    printf("---------------------------------------");
+    printf("---------------------------------------\n");
+
+    do {
+        pRspInfo->scanNumber = scanStart;
+        
+        /* 
+         * Set up and execute the ioctl call
+         */
+        strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+        iwr.u.data.pointer = (caddr_t)pRspInfo;
+        iwr.u.data.length  = sizeof(scanRspBuffer);
+        iwr.u.data.flags   = subioctl_val;
+        
+        if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+            perror("wlanconfig: getscantable ioctl");
+            return -EFAULT;
+        }
+
+        pCurrent = 0;
+        pNext = pRspInfo->scan_table_entry_buffer;
+
+        for (idx = 0; idx < pRspInfo->scanNumber; idx++) {
+            
+            /* 
+             * Set pCurrent to pNext in case pad bytes are at the end
+             *   of the last IE we processed.
+             */
+            pCurrent = pNext;  
+
+            pRspEntry = (wlan_ioctl_get_scan_table_entry*)pCurrent;
+            
+            printf("%02u| %03d | %03d | %02x:%02x:%02x:%02x:%02x:%02x |",
+                   scanStart + idx,
+                   pRspEntry->fixedFields.channel,
+                   pRspEntry->fixedFields.rssi,
+                   pRspEntry->fixedFields.bssid[0],
+                   pRspEntry->fixedFields.bssid[1],
+                   pRspEntry->fixedFields.bssid[2],
+                   pRspEntry->fixedFields.bssid[3],
+                   pRspEntry->fixedFields.bssid[4],
+                   pRspEntry->fixedFields.bssid[5]);
+
+#if 0
+            printf("fixed = %u, bssInfo = %u\n", 
+                   (unsigned int)pRspEntry->fixedFieldLength,
+                   (unsigned int)pRspEntry->bssInfoLength);
+#endif
+                
+            pCurrent += (sizeof(pRspEntry->fixedFieldLength) +
+                         pRspEntry->fixedFieldLength);
+
+            bssInfoLen = pRspEntry->bssInfoLength;
+            pCurrent  += sizeof(pRspEntry->bssInfoLength);
+            pNext      = pCurrent + pRspEntry->bssInfoLength;
+
+            if (bssInfoLen >= (sizeof(tsf) 
+                               + sizeof(beaconInterval) + sizeof(capInfo))) {
+                /* time stamp is 8 byte long */
+                memcpy(tsf, pCurrent, sizeof(tsf));
+                pCurrent   += sizeof(tsf);
+                bssInfoLen -= sizeof(tsf);
+            
+                /* beacon interval is 2 byte long */
+                memcpy(&beaconInterval, pCurrent, sizeof(beaconInterval));
+                pCurrent   += sizeof(beaconInterval);
+                bssInfoLen -= sizeof(beaconInterval);
+                
+                /* capability information is 2 byte long */
+                memcpy(&capInfo, pCurrent, sizeof(capInfo));
+                memcpy(&tmpCap, pCurrent, sizeof(tmpCap));
+                pCurrent   += sizeof(capInfo);
+                bssInfoLen -= sizeof(capInfo);
+            
+                printf(" %04x-", tmpCap);
+
+                printf("%c%c%c | ",
+                       capInfo.Ibss ? 'A' : 'I',
+                       capInfo.Privacy ? 'P' : ' ',
+                       capInfo.SpectrumMgmt ? 'S' : ' ');
+            } else {
+                printf("          | ");
+            }
+
+            while (bssInfoLen >= 2) {
+                pElementId  = (IEEEtypes_ElementId_e*)pCurrent;
+                pElementLen = pCurrent + 1;
+                pCurrent   += 2;
+                
+                switch (*pElementId) {
+                    
+                case SSID:
+                    if (*pElementLen && 
+                        *pElementLen <= MRVDRV_MAX_SSID_LENGTH) {
+                        for (ssidIdx = 0; ssidIdx < *pElementLen; ssidIdx++) {
+                            if (isprint(*(pCurrent + ssidIdx))) {
+                                printf("%c", *(pCurrent + ssidIdx));
+                            } else {
+                                printf("\\%02x", *(pCurrent + ssidIdx));
+                            }
+                        }
+                    }
+                    break;
+                    
+                default:
+#if 0
+                    printf("% d(%d), bil=%d\n", 
+                           *pElementId, *pElementLen, bssInfoLen);
+#endif
+                    break;
+                }
+                
+                pCurrent   += *pElementLen;
+                bssInfoLen -= (2 + *pElementLen);
+            }
+            
+            printf("\n");
+            
+            if (argc > 3) {
+                /* TSF is a u64, some formatted printing libs have
+                 *   trouble printing long longs, so cast and dump as bytes
+                 */
+                pByte = (u8*)&pRspEntry->fixedFields.networkTSF;
+                printf("    TSF=%02x%02x%02x%02x%02x%02x%02x%02x\n",
+                       pByte[7], pByte[6], pByte[5], pByte[4], 
+                       pByte[3], pByte[2], pByte[1], pByte[0]);
+            }
+        }
+        
+        scanStart += pRspInfo->scanNumber;
+        
+        
+    } while (pRspInfo->scanNumber);
+    
+    return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Request a scan from the driver and display the scan table afterwards
+ *
+ *  Command line interface for performing a specific immediate scan based
+ *    on the following keyword parsing:
+ *
+ *     chan=[chan#][band][mode] where band is [a,b,g] and mode is 
+ *                              blank for active or 'p' for passive
+ *     bssid=xx:xx:xx:xx:xx:xx  specify a BSSID filter for the scan
+ *     ssid="[SSID]"            specify a SSID filter for the scan
+ *     keep=[0 or 1]            keep the previous scan results (1), discard (0)
+ *     dur=[scan time]          time to scan for each channel in milliseconds
+ *     probes=[#]               number of probe requests to send on each chan
+ *     type=[1,2,3]             BSS type: 1 (Infra), 2(Adhoc), 3(Any)
+ *
+ *  Any combination of the above arguments can be supplied on the command line.
+ *    If the chan token is absent, a full channel scan will be completed by 
+ *    the driver.  If the dur or probes tokens are absent, the driver default
+ *    setting will be used.  The bssid and ssid fields, if blank, 
+ *    will produce an unfiltered scan. The type field will default to 3 (Any)
+ *    and the keep field will default to 0 (Discard).  
+ *
+ *  @param argc     number of arguments
+ *  @param argv     A pointer to arguments array    
+ *
+ *  @return         WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_setuserscan(int argc, char *argv[]) 
+{
+    wlan_ioctl_user_scan_cfg scanReq;
+    int ioctl_val, subioctl_val;
+	struct iwreq iwr;
+    char* pArgTok;
+    char* pChanTok;
+    char* pArgCookie;
+    char* pChanCookie;
+    int argIdx;
+    int chanParseIdx;
+    int chanCmdIdx;
+    char chanScratch[10];
+    char* pScratch;
+    int tmpIdx;
+	unsigned int mac[ETH_ALEN];
+    int scanTime;
+
+    memset(&scanReq, 0x00, sizeof(scanReq));
+    chanCmdIdx = 0;
+    scanTime = 0;
+    
+    if (get_priv_ioctl("setuserscan",
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+    
+    for (argIdx = 0; argIdx < argc; argIdx++) {
+        if (strncmp(argv[argIdx], "chan=", strlen("chan=")) == 0) {
+            /* 
+             *  "chan" token string handler
+             */
+            pArgTok = argv[argIdx] + strlen("chan=");
+
+            while ((pArgTok = strtok_r(pArgTok, ",", &pArgCookie)) != NULL) {
+                
+                memset(chanScratch, 0x00, sizeof(chanScratch));
+                pScratch = chanScratch;
+
+                for (chanParseIdx = 0; 
+                     chanParseIdx < strlen(pArgTok); chanParseIdx++) {
+                    if (isalpha(*(pArgTok + chanParseIdx))) {
+                        *pScratch++ = ' ';
+                    }
+
+                    *pScratch++ = *(pArgTok + chanParseIdx);
+                }
+                *pScratch = 0;
+                pArgTok = NULL;
+                
+                pChanTok = chanScratch;
+                
+                while ((pChanTok = strtok_r(pChanTok, " ",
+                                            &pChanCookie)) != NULL) {
+                    if (isdigit(*pChanTok)) {
+                        scanReq.chanList[chanCmdIdx].chanNumber
+                            = atoi(pChanTok);
+                    } else {
+                        switch (toupper(*pChanTok)) 
+                        {
+                        case 'A':
+                            scanReq.chanList[chanCmdIdx].radioType = 1;
+                            break;
+                        case 'B':
+                        case 'G':
+                            scanReq.chanList[chanCmdIdx].radioType = 0;
+                            break;
+                        case 'P':
+                            scanReq.chanList[chanCmdIdx].scanType = 1;
+                            break;
+                        }
+                    }
+                    pChanTok = NULL;
+                }
+                chanCmdIdx++;
+            }
+        } else if (strncmp(argv[argIdx], "bssid=", strlen("bssid=")) == 0) {
+            /* 
+             *  "bssid" token string handler
+             */
+            sscanf(argv[argIdx] + strlen("bssid="), "%2x:%2x:%2x:%2x:%2x:%2x",
+					 mac + 0, mac + 1, mac + 2, mac + 3, mac + 4, mac + 5);
+
+            for (tmpIdx = 0; tmpIdx < NELEMENTS(mac); tmpIdx++){
+                scanReq.specificBSSID[tmpIdx] = (u8)mac[tmpIdx];
+            }
+        } else if (strncmp(argv[argIdx], "keep=", strlen("keep=")) == 0) {
+            /* 
+             *  "keep" token string handler
+             */
+            scanReq.keepPreviousScan = atoi(argv[argIdx] + strlen("keep="));
+        } else if (strncmp(argv[argIdx], "dur=", strlen("dur=")) == 0) {
+            /* 
+             *  "dur" token string handler
+             */
+            scanTime = atoi(argv[argIdx] + strlen("dur="));
+        } else if (strncmp(argv[argIdx], "ssid=", strlen("ssid=")) == 0) {
+            /* 
+             *  "ssid" token string handler
+             */
+            strncpy(scanReq.specificSSID, argv[argIdx] + strlen("ssid="),
+                    sizeof(scanReq.specificSSID));
+        } else if (strncmp(argv[argIdx], "probes=", strlen("probes=")) == 0) {
+            /* 
+             *  "probes" token string handler
+             */
+            scanReq.numProbes = atoi(argv[argIdx] + strlen("probes="));
+        } else if (strncmp(argv[argIdx], "type=", strlen("type=")) == 0) {
+            /* 
+             *  "type" token string handler
+             */
+            scanReq.bssType = atoi(argv[argIdx] + strlen("type="));
+            switch (scanReq.bssType) 
+            {
+            case WLAN_SCAN_BSS_TYPE_BSS:
+            case WLAN_SCAN_BSS_TYPE_IBSS:
+                break;
+
+            default:
+            case WLAN_SCAN_BSS_TYPE_ANY:
+                /* Set any unknown types to ANY */
+                scanReq.bssType = WLAN_SCAN_BSS_TYPE_ANY;
+            }
+        }
+    }
+
+    /*
+     * Update all the channels to have the same scan time
+     */
+    for (tmpIdx = 0; tmpIdx < chanCmdIdx; tmpIdx++){
+        scanReq.chanList[tmpIdx].scanTime = scanTime;
+    }
+
+    strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+    iwr.u.data.pointer = (caddr_t)&scanReq;
+    iwr.u.data.length  = sizeof(scanReq);
+    iwr.u.data.flags   = subioctl_val;
+
+    if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+        perror("wlanconfig: setuserscan ioctl");
+        return -EFAULT;
+    }
+
+    process_getscantable(0, 0);
+
+    return WLAN_STATUS_SUCCESS;
+}
+
+
+
+/** 
+ *  @brief scan network with specific ssid
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_extscan(int argc, char *argv[]) 
+{
+	struct iwreq			iwr;
+	WCON_SSID 			Ssid;
+    int ioctl_val, subioctl_val;
+
+    if (get_priv_ioctl("extscan",
+                       &ioctl_val, &subioctl_val) == WLAN_STATUS_FAILURE) {
+		return -EOPNOTSUPP;
+    }
+    
+    if (argc != 4) {
+		printf("Error: invalid no of arguments\n");
+		printf("Syntax: ./wlanconfig eth1 extscan <SSID>\n");
+		exit(1);
+	}
+
+    printf("Ssid: %s\n", argv[3]);
+
+	memset(&Ssid, 0, sizeof(Ssid));
+	memset(&iwr, 0, sizeof(iwr));
+
+	Ssid.ssid_len = strlen(argv[3]);
+	memcpy(Ssid.ssid, argv[3], Ssid.ssid_len);
+
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+	iwr.u.data.pointer = (caddr_t) &Ssid;
+	iwr.u.data.length = sizeof(Ssid);
+    iwr.u.data.flags = subioctl_val;
+
+	if (ioctl(sockfd, ioctl_val, &iwr) < 0) {
+		perror("wlanconfig");
+		return -1;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+#if WIRELESS_EXT > 14
+/** 
+ *  @brief parse custom info
+ *  @param pHandle	A pointer to WCON_HANDLE
+ *  @param data         A pointer to iw_point structure
+ *  @param idx          AP index
+ *  @return      	NA
+ */
+static void parse_custom_info(WCON_HANDLE *pHandle, struct iw_point *data, s32 idx)
+{
+	s32	i = 0;
+	s8 	*custom_cmd[] = { "wpa_ie", "rsn_ie", NULL };
+	
+	if (!data->pointer || !data->length) {
+		printf("iw_point: Invalid Pointer/Length\n");
+		return;
+	}
+	
+	if (!strncmp(data->pointer, "wmm_ie", strlen("wmm_ie"))) {
+			pHandle->ScanList[idx].Wmm = WCON_WMM_ENABLED;
+	}
+
+	while (custom_cmd[i]) {
+		if (!strncmp(data->pointer, custom_cmd[i], 
+					strlen(custom_cmd[i]))) {
+			pHandle->ScanList[idx].WpaAP = WCON_WPA_ENABLED;
+			break;
+		}
+		i++;
+	}
+
+	printf("Wpa:\t %s\n", pHandle->ScanList[idx].WpaAP ?
+					"enabled" : "disabled");
+	printf("Wmm:\t %s\n", pHandle->ScanList[idx].Wmm ?
+					"enabled" : "disabled");
+}
+#endif 
+
+/** 
+ *  @brief parse scan info
+ *  @param pHandle	A pointer to WCON_HANDLE
+ *  @param buffer       A pointer to scan result buffer
+ *  @param length       length of scan result buffer
+ *  @return      	NA
+ */
+static void parse_scan_info(WCON_HANDLE *pHandle, u8 buffer[], s32 length)
+{
+	s32			len = 0;
+	s32			ap_index = -1;
+	s8			*mode[3] = {"auto", "ad-hoc", "infra"};
+	struct iw_event		iwe;
+	struct iw_point		iwp;
+
+	memset(pHandle->ScanList, 0, sizeof(pHandle->ScanList));
+	pHandle->ApNum = 0;
+
+	while (len + IW_EV_LCP_LEN < length) {
+		memcpy((s8 *)&iwe, buffer + len, sizeof(struct iw_event));
+		if ((iwe.cmd == SIOCGIWESSID)||(iwe.cmd ==SIOCGIWENCODE)||
+			(iwe.cmd ==IWEVCUSTOM)){
+				if(we_version_compiled > 18)	
+					memcpy((s8 *)&iwp, buffer + len + IW_EV_LCP_LEN - MRV_EV_POINT_OFF,
+						       	sizeof(struct iw_point));
+				else
+					memcpy((s8 *)&iwp, buffer + len + IW_EV_LCP_LEN,sizeof(struct iw_point));
+			iwp.pointer = buffer + len + IW_EV_POINT_LEN;				
+		}
+		switch (iwe.cmd) {
+		case SIOCGIWAP:
+			ap_index++;
+			memcpy(pHandle->ScanList[ap_index].Bssid, 
+					iwe.u.ap_addr.sa_data, ETH_ALEN);
+			printf("\nBSSID:\t %02X:%02X:%02X:%02X:%02X:%02X\n",
+				HWA_ARG(pHandle->ScanList[ap_index].Bssid));
+			break;
+			
+		case SIOCGIWESSID:
+			if ((iwp.pointer) && (iwp.length)) {
+				memcpy(pHandle->ScanList[ap_index].Ssid.ssid,
+						(s8 *)iwp.pointer,
+						iwp.length);
+				pHandle->ScanList[ap_index].Ssid.ssid_len = 
+							iwp.length;
+			}
+			printf("SSID:\t %s\n",
+				pHandle->ScanList[ap_index].Ssid.ssid);
+			break;
+		
+		case SIOCGIWENCODE:
+			if (!(iwp.flags & IW_ENCODE_DISABLED)) {
+				pHandle->ScanList[ap_index].Privacy =
+							WCON_ENC_ENABLED;
+			}
+			printf("Privacy: %s\n", 
+					pHandle->ScanList[ap_index].Privacy ?
+					"enabled": "disabled");
+			break;
+
+		case SIOCGIWMODE:
+			pHandle->ScanList[ap_index].NetMode = iwe.u.mode;
+			printf("NetMode: %s\n", 
+				mode[pHandle->ScanList[ap_index].NetMode]);
+			break;
+	
+#if WIRELESS_EXT > 14
+		case IWEVCUSTOM:
+			parse_custom_info(pHandle, &iwp, ap_index);
+			break;
+#endif
+
+		case IWEVQUAL:
+			pHandle->ScanList[ap_index].Rssi = iwe.u.qual.level;
+			printf("Quality: %d\n", 
+					pHandle->ScanList[ap_index].Rssi);
+			break;
+		}
+		
+		len += iwe.len;
+	}
+	
+	pHandle->ApNum = ap_index + 1;
+	printf("\nNo of AP's = %d\n", pHandle->ApNum);
+
+	return;
+}
+
+/* 
+ *  @brief Process scan results
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_scan_results(int argc, char *argv[]) 
+{
+	u8		buffer[IW_SCAN_MAX_DATA];
+	struct iwreq	iwr;
+	WCON_HANDLE	mhandle, *pHandle = &mhandle;
+
+	memset(pHandle, 0, sizeof(WCON_HANDLE));
+	memset(&iwr, 0, sizeof(struct iwreq));
+	
+	iwr.u.data.pointer = buffer;
+	iwr.u.data.length = sizeof(buffer);
+	strncpy(iwr.ifr_name, dev_name, IFNAMSIZ);
+
+	if ((ioctl(sockfd, SIOCGIWSCAN, &iwr)) < 0) {
+		printf("Get Scan Results Failed\n");
+		return -1;
+	}
+
+	parse_scan_info(pHandle, buffer, iwr.u.data.length);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+/** 
+ *  @brief Process read eeprom
+ *
+ *  @param stroffset	A pointer to the offset string
+ *  @param strnob	A pointer to NOB string
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_read_eeprom(s8 *stroffset, s8 *strnob)
+{
+	s8 			buffer[MAX_EEPROM_DATA];
+	struct ifreq    	userdata;
+	wlan_ioctl_regrdwr 	*reg = (wlan_ioctl_regrdwr *)buffer;
+
+	memset(buffer, 0, sizeof(buffer));
+	reg->WhichReg = REG_EEPROM;
+	reg->Action = 0;
+
+	if (!strncasecmp(stroffset, "0x", 2))
+		reg->Offset = a2hex((stroffset + 2));
+	else
+		reg->Offset = atoi(stroffset);
+
+	if (!strncasecmp(strnob, "0x", 2))
+		reg->NOB = a2hex((strnob + 2));
+	else
+		reg->NOB = atoi(strnob);
+
+	if (reg->NOB > MAX_EEPROM_DATA) {
+		fprintf(stderr, "Number of bytes exceeds MAX EEPROM Read size\n");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = buffer;
+
+	if (ioctl(sockfd, WLANREGRDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr, 
+			"wlanconfig: EEPROM read not possible "
+			"by interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	hexdump("RD EEPROM", &reg->Value, reg->NOB, ' '); 
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/* 
+ *  @brief Display usage
+ *  
+ *  @return       NA
+ */
+static void display_usage(void)
+{
+	s32 i;
+
+	for (i = 0; i < NELEMENTS(usage); i++)
+		fprintf(stderr, "%s\n", usage[i]);
+}
+
+/* 
+ *  @brief Find command
+ *  
+ *  @param maxcmds	max command number
+ *  @param cmds		A pointer to commands buffer
+ *  @param cmd		A pointer to command buffer
+ *  @return      	index of command or WLAN_STATUS_FAILURE
+ */
+static int findcommand(s32 maxcmds, s8 *cmds[], s8 *cmd)
+{
+	s32 i;
+
+	for (i = 0; i < maxcmds; i++) {
+		if (!strcasecmp(cmds[i], cmd)) {
+			return i;
+		}
+	}
+
+	return WLAN_STATUS_FAILURE;
+}
+
+/* 
+ *  @brief SD comand52 read
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_sdcmd52r(int argc, char *argv[])
+{
+	struct ifreq    userdata;
+	u8	 	buf[6];
+	u32	 	tmp;
+
+	buf[0] = 0;			//CMD52 read
+	if (argc == 5) {
+		buf[1] = atoval(argv[3]);	//func
+		tmp = 	 atoval(argv[4]);	//reg
+		buf[2] = tmp & 0xff;
+		buf[3] = (tmp >> 8) & 0xff;
+		buf[4] = (tmp >> 16) & 0xff;
+		buf[5] = (tmp >> 24) & 0xff;
+	} else {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = buf;
+
+	if (ioctl(sockfd, WLANCMD52RDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr,
+			"wlanconfig: CMD52 R/W not supported by "
+				"interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+   	}
+   	printf("sdcmd52r returns 0x%02X\n", buf[0]);
+
+   	return WLAN_STATUS_SUCCESS;
+}
+
+/* 
+ *  @brief SD comand52 write
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_sdcmd52w(int argc, char *argv[])
+{
+   	struct ifreq    userdata;
+   	u8	 	buf[7];
+   	u32	 	tmp;
+
+	buf[0] = 1;			//CMD52 write
+	if (argc == 6) {
+		buf[1] = atoval(argv[3]);		//func
+		tmp =    atoval(argv[4]);		//reg
+		buf[2] = tmp & 0xff;
+		buf[3] = (tmp >> 8) & 0xff;
+		buf[4] = (tmp >> 16) & 0xff;
+		buf[5] = (tmp >> 24) & 0xff;
+		buf[6] = atoval(argv[5]);		//dat
+	} else {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = buf;
+
+	if (ioctl(sockfd, WLANCMD52RDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr,
+			"wlanconfig: CMD52 R/W not supported by "
+				"interface %s\n", dev_name);
+			return WLAN_STATUS_FAILURE;
+   	}
+   	printf("sdcmd52w returns 0x%02X\n",buf[0]);
+
+   	return WLAN_STATUS_SUCCESS;
+}
+
+/* 
+ *  @brief SD comand53 read
+ *  
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+static int process_sdcmd53r(void)
+{
+	struct ifreq    userdata;
+	s8 		buf[CMD53BUFLEN];
+	int 		i;
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = buf;
+
+	for(i=0; i < NELEMENTS(buf); i++)
+		buf[i] = i & 0xff;
+
+	if (ioctl(sockfd, WLANCMD53RDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr,
+			"wlanconfig: CMD53 R/W not supported by "
+			"interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	for(i=0; i < NELEMENTS(buf); i++) {
+		if (buf[i] != (i ^ 0xff))
+			printf("i=%02X  %02X\n",i,buf[i]);
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+
+
+/* 
+ *  @brief Get one line from the File
+ *  
+ *  @param s	        Storage location for data.
+ *  @param size 	Maximum number of characters to read. 
+ *  @param stream 	File stream	  	
+ *  @param line		A pointer to return current line number
+ *  @return             returns string or NULL 
+ */
+static s8 * wlan_config_get_line(s8 *s, s32 size, FILE *stream, int *line)
+{
+	s8 *pos, *end, *sstart;
+
+	while (fgets(s, size, stream)) {
+		(*line)++;
+		s[size - 1] = '\0';
+		pos = s;
+
+		while (*pos == ' ' || *pos == '\t')
+			pos++;
+		if (*pos == '#' || (*pos == '\r' && *(pos+1) == '\n') || 
+						*pos == '\n' || *pos == '\0')
+			continue;
+
+		/* Remove # comments unless they are within a double quoted
+		* string. Remove trailing white space. */
+		sstart = strchr(pos, '"');
+		if (sstart)
+			sstart = strchr(sstart + 1, '"');
+		if (!sstart)
+			sstart = pos;
+		end = strchr(sstart, '#');
+		if (end)
+			*end-- = '\0';
+		else
+			end = pos + strlen(pos) - 1;
+		while (end > pos && (*end == '\r' || *end == '\n' || 
+						*end == ' ' || *end == '\t')) {
+			*end-- = '\0';
+		}
+		if (*pos == '\0')
+			continue;
+		return pos;
+	}
+
+	return NULL;
+}
+
+
+
+/** 
+ *  @brief read register
+ *  @param cmd 		the type of register
+ *  @param stroffset	A pointer to register index string
+ *  @return            	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int process_read_register(s32 cmd, s8 *stroffset)
+{
+	struct ifreq    userdata;
+	wlan_ioctl_regrdwr reg;
+	s8           *whichreg;
+
+	switch (cmd) {
+		case CMD_RDMAC:
+			/*
+			 * HostCmd_CMD_MAC_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_MAC;
+			whichreg = "MAC";
+			break;
+		case CMD_RDBBP:
+			/*
+			 * HostCmd_CMD_BBP_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_BBP;
+			whichreg = "BBP";
+			break;
+		case CMD_RDRF:
+			/*
+			 * HostCmd_CMD_RF_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_RF;
+			whichreg = "RF";
+			break;
+		default:
+			fprintf(stderr, 
+				"Invalid Register set specified.\n");
+			return -1;
+	}
+
+	reg.Action = 0;		/* READ */
+
+	if (!strncasecmp(stroffset, "0x", 2))
+		reg.Offset = a2hex((stroffset + 2));
+	else
+		reg.Offset = atoi(stroffset);
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = (s8 *) &reg;
+
+	if (ioctl(sockfd, WLANREGRDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr,
+			"wlanconfig: Register Reading not supported by"
+			"interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	printf("%s[0x%04lx] = 0x%08lx\n", 
+			whichreg, reg.Offset, reg.Value);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief write register
+ *  @param cmd 		the type of register
+ *  @param stroffset	A pointer to register index string
+ *  @param strvalue	A pointer to the register value
+ *  @return            	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int process_write_register(s32 cmd, s8 *stroffset, s8 *strvalue)
+{
+	struct ifreq    	userdata;
+	wlan_ioctl_regrdwr 	reg;
+	s8           		*whichreg;
+
+	switch (cmd) {
+		case CMD_WRMAC:
+			/*
+			 * HostCmd_CMD_MAC_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_MAC;
+			whichreg = "MAC";
+			break;
+		case CMD_WRBBP:
+			/*
+			 * HostCmd_CMD_BBP_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_BBP;
+			whichreg = "BBP";
+			break;
+		case CMD_WRRF:
+			/*
+			 * HostCmd_CMD_RF_REG_ACCESS 
+			 */
+			reg.WhichReg = REG_RF;
+			whichreg = "RF";
+			break;
+		default:
+			fprintf(stderr, 
+				"Invalid register set specified.\n");
+			return -1;
+	}
+
+	reg.Action = 1;		/* WRITE */
+
+	if (!strncasecmp(stroffset, "0x", 2))
+		reg.Offset = a2hex((stroffset + 2));
+	else
+		reg.Offset = atoi(stroffset);
+
+	if (!strncasecmp(strvalue, "0x", 2))
+		reg.Value = a2hex((strvalue + 2));
+	else
+		reg.Value = atoi(strvalue);
+
+	printf("Writing %s Register 0x%04lx with 0x%08lx\n", whichreg,
+			reg.Offset, reg.Value);
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = (s8 *) &reg;
+
+	if (ioctl(sockfd, WLANREGRDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr, 
+			"wlanconfig: Register Writing not supported "
+			"by interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	printf("%s[0x%04lx] = 0x%08lx\n",
+			whichreg, reg.Offset, reg.Value);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief read CF register
+ *
+ *  @param stroffset	A pointer to register index string
+ *  @return            	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int process_read_cfreg(s8 *stroffset)
+{
+	struct ifreq    	userdata;
+	wlan_ioctl_cfregrdwr 	reg;
+	
+	reg.Action = 0; //Read register
+
+	if (!strncasecmp(stroffset, "0x", 2))
+		reg.Offset = a2hex((stroffset + 2));
+	else
+		reg.Offset = atoi(stroffset);
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = (s8 *) &reg;
+
+	if (ioctl(sockfd, WLANREGCFRDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr, 
+			"wlanconfig: Register reading not supported "
+			"by interface %s\n", dev_name);
+		return  WLAN_STATUS_FAILURE;
+	}
+
+	printf("CFREG[0x%04X] = 0x%04X\n",
+				reg.Offset, reg.Value);
+
+	return  WLAN_STATUS_SUCCESS;
+
+}
+
+/** 
+ *  @brief write CF register
+ *
+ *  @param stroffset	A pointer to register index string
+ *  @param strvalue	A pointer to the register value 
+ *  @return            	WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int process_write_cfreg(s8 *stroffset, s8 *strvalue)
+{
+	struct ifreq    	userdata;
+	wlan_ioctl_cfregrdwr 	reg;
+
+	reg.Action = 1; //Write register
+
+	if (!strncasecmp(stroffset, "0x", 2))
+		reg.Offset = a2hex((stroffset + 2));
+	else
+		reg.Offset = atoi(stroffset);
+
+	if (!strncasecmp(strvalue, "0x", 2))
+		reg.Value = a2hex((strvalue + 2));
+	else
+		reg.Value = atoi(strvalue);
+
+	strncpy(userdata.ifr_name, dev_name, IFNAMSIZ);
+	userdata.ifr_data = (s8 *) &reg;
+
+	if (ioctl(sockfd, WLANREGCFRDWR, &userdata)) {
+		perror("wlanconfig");
+		fprintf(stderr, 
+			"wlanconfig: Register writing not supported "
+			"by interface %s\n", dev_name);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/********************************************************
+		Global Functions
+********************************************************/
+/* 
+ *  @brief Entry function for wlanconfig
+ *  @param argc		number of arguments
+ *  @param argv         A pointer to arguments array    
+ *  @return      	WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int main(int argc, char *argv[])
+{
+	s32             cmd;
+
+	if (argc < 3) {
+		fprintf(stderr, "Invalid number of parameters!\n");
+		display_usage();
+		exit(1);
+	}
+
+	strncpy(dev_name, argv[1], IFNAMSIZ);
+
+	/*
+	 * create a socket 
+	 */
+	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
+		fprintf(stderr, "wlanconfig: Cannot open socket.\n");
+		exit(1);
+	}
+	if(get_range() < 0){
+		fprintf(stderr, "wlanconfig: Cannot get range.\n");
+		exit(1);
+	}
+	switch ((cmd = findcommand(NELEMENTS(commands), commands, argv[2]))) {
+	case CMD_HOSTCMD:
+		process_host_cmd(argc, argv);
+		break;
+	case CMD_RDMAC:
+	case CMD_RDBBP:
+	case CMD_RDRF:
+		if (argc < 4) {
+			fprintf(stderr, "Register offset required!\n");
+			display_usage();
+			exit(1);
+		}
+
+		if (process_read_register(cmd, argv[3])) {
+			fprintf(stderr, "Read command failed!\n");
+			exit(1);
+		}
+		break;
+	case CMD_WRMAC:
+	case CMD_WRBBP:
+	case CMD_WRRF:
+		if (argc < 5) {
+			fprintf(stderr, "Register offset required & value!\n");
+			display_usage();
+			exit(1);
+		}
+		if (process_write_register(cmd, argv[3],
+					argv[4])) {
+			fprintf(stderr, "Write command failed!\n");
+			exit(1);
+		}
+		break;
+	case CMD_CMD52R:
+		process_sdcmd52r(argc,argv);
+		break;
+	case CMD_CMD52W:
+		process_sdcmd52w(argc,argv);
+		break;
+	case CMD_CMD53R:
+		process_sdcmd53r();
+		break;
+	case CMD_CFREGR:
+		printf("process read cfreg\n");
+		if (argc < 4) {
+			fprintf(stderr,	"Register offset required!\n");
+			display_usage();
+			exit(1);
+		}
+		if (process_read_cfreg(argv[3])) {
+			fprintf(stderr, "Read CF register failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_CFREGW:
+		printf("process write cfreg\n");
+		if (argc < 5) {
+			fprintf(stderr,	"Register offset required!\n");
+			display_usage();
+			exit(1);
+		}
+		if (process_write_cfreg(argv[3], argv[4])) {
+			fprintf(stderr, "Read CF register failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_RDEEPROM:
+		printf("proces read eeprom\n");
+
+		if(argc < 5) {
+			fprintf(stderr, "Register offset, number of bytes required\n");
+			display_usage();
+			exit(1);
+		}
+		
+		if(process_read_eeprom(argv[3], argv[4])) {
+			fprintf(stderr, "EEPROM Read failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_GETRATE:
+		if (process_get_rate()) {
+			fprintf(stderr, "Get Rate Failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_SLEEPPARAMS:
+		if (process_sleep_params(argc, argv)) {
+			fprintf(stderr, "Sleep Params Failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_BCA_TS:
+		if (process_bca_ts(argc, argv)) {
+			fprintf(stderr, "SetBcaTs Failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_EXTSCAN:
+		if (process_extscan(argc, argv)) {
+			fprintf(stderr, "ExtScan Failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_SCAN_LIST:
+		if (process_scan_results(argc, argv)) {
+			fprintf(stderr, "getscanlist Failed\n");
+			display_usage();
+			exit(1);
+		}
+		break;
+	case CMD_GET_SCAN_RSP:
+        if (process_getscantable(argc, argv)) {
+			exit(1);
+        }
+        break;
+
+    case CMD_SET_USER_SCAN:
+        if (process_setuserscan(argc, argv)) {
+            exit(1);
+        }
+        break;
+
+	default:
+		fprintf(stderr, "Invalid command specified!\n");
+		display_usage();
+		exit(1);
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/wlanconfig.h linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/wlanconfig.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlanconfig/wlanconfig.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlanconfig/wlanconfig.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,82 @@
+/** @file wlan_config.h
+  * 
+  * @brief This file contains definitions for application
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/****************************************************************
+Change log:
+	09/26/05: add Doxygen format comments
+****************************************************************/
+
+#ifndef _WLANCONFIG_H_
+#define _WLANCONFIG_H_
+
+#define NULLBSSID		"\x00\x00\x00\x00\x00\x00"
+
+/* to create pointers to 6-byte hardware address */
+#define HWA_ARG(x)		*(((u8 *)x + 0)), *(((u8 *)x + 1)), \
+				*(((u8 *)x + 2)), *(((u8 *)x + 3)), \
+				*(((u8 *)x + 4)), *(((u8 *)x + 5))
+
+#define WCON_ENC_DISABLED	0
+#define WCON_ENC_ENABLED	1	
+
+#define WCON_WPA_DISABLED	0
+#define WCON_WPA_ENABLED	1	
+
+#define WCON_WMM_DISABLED	0
+#define WCON_WMM_ENABLED	1	
+
+/** struct of SSID network name */
+typedef struct _WCON_SSID {
+	/** SSID name length */
+	u32	ssid_len;
+	/** SSID name string */
+	u8	ssid[IW_ESSID_MAX_SIZE + 1];
+} WCON_SSID;
+
+typedef u8 WCON_BSSID[ETH_ALEN];
+
+/** struct of SSID network information */
+typedef struct _WCON_NET_INFO {
+	/** SSID network name struct */
+	WCON_SSID	Ssid;
+	/** hardware address of the SSID network */
+	WCON_BSSID	Bssid;
+	/** rssi value */
+	unsigned int	Rssi;
+	/**  network operating mode */
+	int		NetMode;
+	/** network privacy mode */
+	int		Privacy;
+	/** WPA enable */
+	int		WpaAP;
+	/** WMM enable */
+	int		Wmm;
+} WCON_NET_INFO;
+
+/** struct of SSID list from scan */
+typedef struct _WCON_HANDLE {
+	/** list of scan result */
+	WCON_NET_INFO	ScanList[IW_MAX_AP];
+	int		ApNum; 
+} WCON_HANDLE;
+
+#endif /* _WLANCONFIG_H_ */
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_debugfs.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_debugfs.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_debugfs.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_debugfs.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,314 @@
+
+#include <linux/module.h>
+#include <linux/dcache.h>
+#include <linux/debugfs.h>
+#include "wlan_dev.h"
+#include "wlan_decl.h"
+
+static struct dentry *libertas_dir = NULL;
+static const int big_buffer_len = 4096;
+static char big_buffer[4096];
+static DECLARE_MUTEX(big_buffer_sem);
+
+static char *szStates[] = {
+	"Connected",
+	"Disconnected"
+};
+
+void libertas_debug_init(wlan_private * priv, struct net_device *dev);
+
+static int open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t write_file_dummy(struct file *file, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+        return -EINVAL;
+}
+
+static ssize_t libertas_dev_info(struct file *file, char __user *userbuf,
+				  size_t count, loff_t *ppos)
+{
+	wlan_private *priv = file->private_data;
+	size_t pos = 0;
+	const size_t len = big_buffer_len;
+	char *buf = big_buffer;
+	ssize_t res;
+	char fmt[64];
+
+	libertas_get_version(priv->adapter, fmt, sizeof(fmt) - 1);
+	down(&big_buffer_sem);
+
+	pos += snprintf(buf+pos, len-pos, "libertas_driver_version = %s\n", fmt);
+	pos += snprintf(buf+pos, len-pos, "state=%s\n",
+				szStates[priv->adapter->MediaConnectStatus]);
+	pos += snprintf(buf+pos, len-pos, "region_code = %02x\n",
+				(u32) priv->adapter->RegionCode);
+
+	res = simple_read_from_buffer(userbuf, count, ppos, buf, pos);
+
+	up(&big_buffer_sem);
+
+	return res;
+}
+
+static struct file_operations libertas_devinfo_fops = { 
+	.owner = THIS_MODULE,
+	.open = open_file_generic,
+	.write = write_file_dummy,
+	.read = libertas_dev_info,
+};
+
+void libertas_debugfs_init(void)
+{
+	if (!libertas_dir) {
+		libertas_dir = debugfs_create_dir("libertas_wireless", NULL);
+		if (!libertas_dir || IS_ERR(libertas_dir))
+			libertas_dir = NULL;
+	}
+	return;
+}
+
+void libertas_debugfs_remove(void)
+{
+	if (libertas_dir)
+		 debugfs_remove(libertas_dir);
+	return;
+}
+
+void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev)
+{
+	if (!libertas_dir)
+		goto exit;
+
+	priv->debugfs_dir = debugfs_create_dir(dev->name, libertas_dir);
+	if (!priv->debugfs_dir || IS_ERR(priv->debugfs_dir)) {
+		priv->debugfs_dir = NULL;
+		goto exit;
+	}
+
+	priv->debugfs_devinfo = debugfs_create_file("info", 0444,
+						    priv->debugfs_dir,
+						    priv,
+						    &libertas_devinfo_fops);
+
+	if (!priv->debugfs_devinfo || IS_ERR(priv->debugfs_devinfo)) {
+		priv->debugfs_devinfo = NULL;
+		goto exit;
+	}
+#ifdef PROC_DEBUG
+	libertas_debug_init(priv, dev);
+#endif
+
+exit:
+	return;
+}
+
+void libertas_debugfs_remove_one(wlan_private *priv)
+{
+#ifdef PROC_DEBUG
+	debugfs_remove(priv->debugfs_debug);
+#endif
+	debugfs_remove(priv->debugfs_devinfo);
+	debugfs_remove(priv->debugfs_dir);
+}
+
+/* debug entry */
+
+#define item_size(n) (sizeof ((wlan_adapter *)0)->n)
+#define item_addr(n) ((u32) &((wlan_adapter *)0)->n)
+
+struct debug_data {
+	char name[32];
+	u32 size;
+	u32 addr;
+};
+
+/* To debug any member of wlan_adapter, simply add one line here.
+ */
+static struct debug_data items[] = {
+	{"IntCounter", item_size(IntCounter), item_addr(IntCounter)},
+	{"PSMode", item_size(PSMode), item_addr(PSMode)},
+	{"PSState", item_size(PSState), item_addr(PSState)},
+};
+
+static int num_of_items = sizeof(items) / sizeof(items[0]);
+
+/** 
+ *  @brief convert string to number
+ *
+ *  @param s   	   pointer to numbered string
+ *  @return 	   converted number from string s
+ */
+static int string_to_number(char *s)
+{
+	int r = 0;
+	int base = 0;
+
+	if ((strncmp(s, "0x", 2) == 0) || (strncmp(s, "0X", 2) == 0))
+		base = 16;
+	else
+		base = 10;
+
+	if (base == 16)
+		s += 2;
+
+	for (s = s; *s != 0; s++) {
+		if ((*s >= 48) && (*s <= 57))
+			r = (r * base) + (*s - 48);
+		else if ((*s >= 65) && (*s <= 70))
+			r = (r * base) + (*s - 55);
+		else if ((*s >= 97) && (*s <= 102))
+			r = (r * base) + (*s - 87);
+		else
+			break;
+	}
+
+	return r;
+}
+
+/** 
+ *  @brief proc read function
+ *
+ *  @param page	   pointer to buffer
+ *  @param s       read data starting position
+ *  @param off     offset
+ *  @param cnt     counter 
+ *  @param eof     end of file flag
+ *  @param data    data to output
+ *  @return 	   number of output data
+ */
+static ssize_t wlan_debugfs_read(struct file *file, char __user *userbuf, 
+			size_t count, loff_t *ppos)
+{
+	int val = 0;
+	size_t pos = 0;
+	ssize_t res;
+	char *p;
+	int i;
+	struct debug_data *d;
+
+	down(&big_buffer_sem);
+
+	p = big_buffer;
+
+	d = (struct debug_data *)file->private_data;
+
+	for (i = 0; i < num_of_items; i++) {
+		if (d[i].size == 1)
+			val = *((u8 *) d[i].addr);
+		else if (d[i].size == 2)
+			val = *((u16 *) d[i].addr);
+		else if (d[i].size == 4)
+			val = *((u32 *) d[i].addr);
+
+		pos += sprintf(p + pos, "%s=%d\n", d[i].name, val);
+	}
+
+	res = simple_read_from_buffer(userbuf, count, ppos, p, pos);
+
+	up(&big_buffer_sem);
+
+	return res;
+}
+
+/** 
+ *  @brief proc write function
+ *
+ *  @param f	   file pointer
+ *  @param buf     pointer to data buffer
+ *  @param cnt     data number to write
+ *  @param data    data to write
+ *  @return 	   number of data
+ */
+static int wlan_debugfs_write(struct file *f, const char __user *buf,
+			    size_t cnt, loff_t *ppos)
+{
+	int r, i;
+	char *pdata;
+	char *p;
+	char *p0;
+	char *p1;
+	char *p2;
+	struct debug_data *d = (struct debug_data *)f->private_data;
+
+	pdata = (char *)kmalloc(cnt, GFP_KERNEL);
+	if (pdata == NULL)
+		return 0;
+
+	if (copy_from_user(pdata, buf, cnt)) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return 0;
+	}
+
+	p0 = pdata;
+	for (i = 0; i < num_of_items; i++) {
+		do {
+			p = strstr(p0, d[i].name);
+			if (p == NULL)
+				break;
+			p1 = strchr(p, '\n');
+			if (p1 == NULL)
+				break;
+			p0 = p1++;
+			p2 = strchr(p, '=');
+			if (!p2)
+				break;
+			p2++;
+			r = string_to_number(p2);
+			if (d[i].size == 1)
+				*((u8 *) d[i].addr) = (u8) r;
+			else if (d[i].size == 2)
+				*((u16 *) d[i].addr) = (u16) r;
+			else if (d[i].size == 4)
+				*((u32 *) d[i].addr) = (u32) r;
+			break;
+		} while (1);
+	}
+	kfree(pdata);
+
+	return cnt;
+}
+
+static struct file_operations libertas_debug_fops = { 
+	.owner = THIS_MODULE,
+	.open = open_file_generic,
+	.write = wlan_debugfs_write,
+	.read = wlan_debugfs_read,
+};
+
+/** 
+ *  @brief create debug proc file
+ *
+ *  @param priv	   pointer wlan_private
+ *  @param dev     pointer net_device
+ *  @return 	   N/A
+ */
+void libertas_debug_init(wlan_private * priv, struct net_device *dev)
+{
+	int i;
+
+	if (!priv->debugfs_dir)
+		return;
+
+	for (i = 0; i < num_of_items; i++) 
+		items[i].addr += (u32) priv->adapter;
+
+	priv->debugfs_debug = debugfs_create_file("debug", 0644,
+						  priv->debugfs_dir, &items[0],
+						  &libertas_debug_fops);
+}
+
+/** 
+ *  @brief remove proc file
+ *
+ *  @param priv	   pointer wlan_private
+ *  @return 	   N/A
+ */
+void libertas_debug_remove(wlan_private * priv)
+{
+	debugfs_remove(priv->debugfs_debug);
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_debugfs.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_debugfs.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_debugfs.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_debugfs.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,6 @@
+void libertas_debugfs_init(void);
+void libertas_debugfs_remove(void);
+
+void libertas_debugfs_init_one(wlan_private *priv, struct net_device *dev);
+void libertas_debugfs_remove_one(wlan_private *priv);
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_decl.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_decl.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_decl.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_decl.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,108 @@
+/** @file wlan_decl.h
+  *  @brief This file contains declaration referring to
+  *  functions defined in other source files
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/******************************************************
+Change log:
+	09/29/05: add Doxygen format comments
+	01/05/06: Add kernel 2.6.x support	
+	01/11/06: Change compile flag BULVERDE_SDIO to SD to support
+	          Monahans/Zylonite
+	01/11/06: Conditionalize new scan/join structures.
+	          Move wlan_wext statics to their source file.
+******************************************************/
+
+#ifndef _WLAN_DECL_H_
+#define _WLAN_DECL_H_
+
+#include "wlan_defs.h"
+
+/** Function Prototype Declaration */
+struct wlan_private;
+struct sk_buff;
+struct net_device;
+
+void libertas_free_adapter(wlan_private * priv);
+int libertas_set_mac_packet_filter(wlan_private * priv);
+
+int libertas_send_null_packet(wlan_private * priv, u8 pwr_mgmt);
+void libertas_send_tx_feedback(wlan_private * priv);
+u8 libertas_check_last_packet_indication(wlan_private * priv);
+
+int libertas_free_cmd_buffer(wlan_private * priv);
+struct CmdCtrlNode;
+struct CmdCtrlNode *libertas_get_free_cmd_ctrl_node(wlan_private * priv);
+
+void libertas_set_cmd_ctrl_node(wlan_private * priv,
+		    struct CmdCtrlNode *pTempNode,
+		    u32 cmd_oid, u16 wait_option, void *pdata_buf);
+
+int libertas_prepare_and_send_command(wlan_private * priv,
+			  u16 cmd_no,
+			  u16 cmd_action,
+			  u16 wait_option, u32 cmd_oid, void *pdata_buf);
+
+void libertas_queue_cmd(wlan_adapter * Adapter, struct CmdCtrlNode *CmdNode, u8 addtail);
+
+int libertas_allocate_cmd_buffer(wlan_private * priv);
+int libertas_execute_next_command(wlan_private * priv);
+int libertas_process_event(wlan_private * priv);
+void libertas_interrupt(struct net_device *);
+int libertas_set_radio_control(wlan_private * priv);
+u32 libertas_index_to_data_rate(u8 index);
+u8 libertas_data_rate_to_index(u32 rate);
+void libertas_get_version(wlan_adapter * adapter, char *version, int maxlen);
+
+int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb);
+
+/** The proc fs interface */
+int libertas_process_rx_command(wlan_private * priv);
+int libertas_process_tx(wlan_private * priv, struct sk_buff *skb);
+void libertas_cleanup_and_insert_cmd(wlan_private * priv,
+					struct CmdCtrlNode *pTempCmd);
+
+#ifdef REASSOCIATION
+void libertas_reassoc_timer_fn(unsigned long data);
+#endif				/* REASSOCIATION */
+
+struct iw_point;
+struct iw_request_info;
+int libertas_set_essid(struct net_device *dev, struct iw_request_info *info,
+		   struct iw_point *dwrq, char *extra);
+int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band);
+
+int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *);
+
+void libertas_ps_sleep(wlan_private * priv, int wait_option);
+void libertas_ps_confirm_sleep(wlan_private * priv, u16 PSMode);
+void libertas_ps_wakeup(wlan_private * priv, int wait_option);
+
+void libertas_tx_runqueue(wlan_private *priv);
+
+#define SDIO_HEADER_LEN		4
+
+extern struct chan_freq_power *libertas_find_cfp_by_band_and_channel(
+				wlan_adapter * adapter, u8 band, u16 channel);
+
+extern void libertas_mac_event_disconnected(wlan_private * priv);
+
+void libertas_send_iwevcustom_event(wlan_private * priv, s8 * str);
+
+#endif				/* _WLAN_DECL_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_defs.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_defs.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_defs.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_defs.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,571 @@
+/** @file wlan_defs.h
+  * @brief This header file contains global constant/enum definitions,
+  * global variable declaration.
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change log:
+	10/11/05: add Doxygen format comments 
+	01/11/06: Change compile flag BULVERDE_SDIO to SD to support
+	          Monahans/Zylonite
+	01/11/06: Add NELEMENTS, BAND_XX defines
+	04/10/06: Add hostcmd generic API and power_adapt_cfg_ext command
+************************************************************/
+
+#ifndef _WLAN_DEFS_H_
+#define _WLAN_DEFS_H_
+
+#include <linux/spinlock.h>
+
+/** Double-Word(32Bit) Bit definition */
+#define DW_BIT_0	0x00000001
+#define DW_BIT_1	0x00000002
+#define DW_BIT_2	0x00000004
+#define DW_BIT_3	0x00000008
+#define DW_BIT_4	0x00000010
+#define DW_BIT_5	0x00000020
+#define DW_BIT_6	0x00000040
+#define DW_BIT_7	0x00000080
+#define DW_BIT_8	0x00000100
+#define DW_BIT_9	0x00000200
+#define DW_BIT_10	0x00000400
+#define DW_BIT_11       0x00000800
+#define DW_BIT_12       0x00001000
+#define DW_BIT_13       0x00002000
+#define DW_BIT_14       0x00004000
+#define DW_BIT_15       0x00008000
+#define DW_BIT_16       0x00010000
+#define DW_BIT_17       0x00020000
+#define DW_BIT_18       0x00040000
+#define DW_BIT_19       0x00080000
+#define DW_BIT_20       0x00100000
+#define DW_BIT_21       0x00200000
+#define DW_BIT_22       0x00400000
+#define DW_BIT_23       0x00800000
+#define DW_BIT_24       0x01000000
+#define DW_BIT_25       0x02000000
+#define DW_BIT_26       0x04000000
+#define DW_BIT_27       0x08000000
+#define DW_BIT_28       0x10000000
+#define DW_BIT_29       0x20000000
+#define DW_BIT_30	0x40000000
+#define DW_BIT_31	0x80000000
+
+/** Word (16bit) Bit Definition*/
+#define W_BIT_0		0x0001
+#define W_BIT_1		0x0002
+#define W_BIT_2		0x0004
+#define W_BIT_3		0x0008
+#define W_BIT_4		0x0010
+#define W_BIT_5		0x0020
+#define W_BIT_6		0x0040
+#define W_BIT_7		0x0080
+#define W_BIT_8		0x0100
+#define W_BIT_9		0x0200
+#define W_BIT_10	0x0400
+#define W_BIT_11	0x0800
+#define W_BIT_12	0x1000
+#define W_BIT_13	0x2000
+#define W_BIT_14	0x4000
+#define W_BIT_15	0x8000
+
+/** Byte (8Bit) Bit definition*/
+#define B_BIT_0		0x01
+#define B_BIT_1		0x02
+#define B_BIT_2		0x04
+#define B_BIT_3		0x08
+#define B_BIT_4		0x10
+#define B_BIT_5		0x20
+#define B_BIT_6		0x40
+#define B_BIT_7		0x80
+
+/** Debug Macro definition*/
+#ifdef	DEBUG_LEVEL4
+#define	PRINTM_INFO(msg...)	printk(KERN_DEBUG msg)
+#ifndef DEBUG_LEVEL3
+#define	DEBUG_LEVEL3
+#endif
+#else
+#define	PRINTM_INFO(msg...)
+#endif
+
+#ifdef	DEBUG_LEVEL3
+#define	PRINTM_WARN(msg...)	printk(KERN_DEBUG msg)
+#ifndef DEBUG_LEVEL2
+#define	DEBUG_LEVEL2
+#endif
+#else
+#define	PRINTM_WARN(msg...)
+#endif
+
+#ifdef	DEBUG_LEVEL2
+#define	PRINTM_FATAL(msg...)	printk(KERN_DEBUG msg)
+#ifndef DEBUG_LEVEL1
+#define	DEBUG_LEVEL1
+#endif
+#else
+#define	PRINTM_FATAL(msg...)
+#endif
+
+#ifdef	DEBUG_LEVEL1
+#define	PRINTM_MSG(msg...)	printk(KERN_ALERT msg)
+#else
+#define	PRINTM_MSG(msg...)
+#endif
+
+#define	PRINTM(level,msg...)	PRINTM_##level(msg)
+
+#define ASSERT(cond)						\
+do {								\
+	if (!(cond))						\
+		PRINTM(INFO, "ASSERT: %s, %s:%i\n",		\
+		       __FUNCTION__, __FILE__, __LINE__);	\
+} while(0)
+#define	ENTER()			PRINTM(INFO, "Enter: %s, %s:%i\n", __FUNCTION__, \
+							__FILE__, __LINE__)
+#define	LEAVE()			PRINTM(INFO, "Leave: %s, %s:%i\n", __FUNCTION__, \
+							__FILE__, __LINE__)
+
+#if defined(DEBUG_LEVEL4) && defined(__KERNEL__)
+static inline void HEXDUMP(char *prompt, u8 * buf, int len)
+{
+	int i = 0;
+
+	printk(KERN_DEBUG "%s: ", prompt);
+	for (i = 1; i <= len; i++) {
+		printk("%02x ", (u8) * buf);
+		buf++;
+	}
+	printk("\n");
+}
+#else
+#define HEXDUMP(x,y,z)
+#endif
+
+#ifndef NELEMENTS
+#define NELEMENTS(x) (sizeof(x)/sizeof(x[0]))
+#endif
+
+/** Buffer Constants */
+
+/*	The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical
+*	addresses of TxPD buffers. Station has only 8 TxPD available, Whereas
+*	driver has more local TxPDs. Each TxPD on the host memory is associated 
+*	with a Tx control node. The driver maintains 8 RxPD descriptors for 
+*	station firmware to store Rx packet information.
+*
+*	Current version of MAC has a 32x6 multicast address buffer.
+*
+*	802.11b can have up to  14 channels, the driver keeps the
+*	BSSID(MAC address) of each APs or Ad hoc stations it has sensed.
+*/
+
+#define MRVDRV_SIZE_OF_PPA		0x00000008
+#define MRVDRV_SIZE_OF_DPA		0x00000008
+#define MRVDRV_NUM_OF_TxPD		0x00000020
+#define MRVDRV_MAX_MULTICAST_LIST_SIZE	32
+#define MRVDRV_NUM_OF_CMD_BUFFER        10
+#define MRVDRV_SIZE_OF_CMD_BUFFER       (2 * 1024)
+#define MRVDRV_MAX_CHANNEL_SIZE		14
+#define MRVDRV_MAX_BSSID_LIST		64
+#define MRVDRV_ASSOCIATION_TIME_OUT	255
+#define MRVDRV_SNAP_HEADER_LEN          8
+
+#define	WLAN_UPLD_SIZE			2312
+#define DEV_NAME_LEN			32
+
+/** Misc constants */
+/* This section defines 802.11 specific contants */
+
+#define MRVDRV_MAX_SSID_LENGTH			32
+#define MRVDRV_MAX_BSS_DESCRIPTS		16
+#define MRVDRV_MAX_REGION_CODE			6
+
+#define MRVDRV_IGNORE_MULTIPLE_DTIM		0xfffe
+#define MRVDRV_MIN_MULTIPLE_DTIM		1
+#define MRVDRV_MAX_MULTIPLE_DTIM		5
+#define MRVDRV_DEFAULT_MULTIPLE_DTIM		1
+
+#define MRVDRV_DEFAULT_LISTEN_INTERVAL		10
+#define MRVDRV_DEFAULT_LOCAL_LISTEN_INTERVAL		0
+
+#define	MRVDRV_CHANNELS_PER_SCAN		4
+#define	MRVDRV_MAX_CHANNELS_PER_SCAN		14
+
+#define	MRVDRV_CHANNELS_PER_ACTIVE_SCAN		14
+
+#define MRVDRV_DEBUG_RX_PATH		0x00000001
+#define MRVDRV_DEBUG_TX_PATH		0x00000002
+
+#define MRVDRV_MIN_BEACON_INTERVAL		20
+#define MRVDRV_MAX_BEACON_INTERVAL		1000
+#define MRVDRV_BEACON_INTERVAL			100
+
+/** TxPD Status */
+
+/*	Station firmware use TxPD status field to report final Tx transmit
+*	result, Bit masks are used to present combined situations.
+*/
+
+#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01
+#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08
+
+/** Tx control node status */
+
+#define MRVDRV_TX_CTRL_NODE_STATUS_IDLE      0x0000
+
+/** RxPD Status */
+
+#define MRVDRV_RXPD_STATUS_OK                0x0001
+#define MRVDRV_RXPD_STATUS_MULTICAST_RX      0x0002
+
+/** RxPD Status - Received packet types */
+
+#define	MRVDRV_RXPD_STATUS_MAXTYPES_RX		6
+
+/* Link spped */
+#define MRVDRV_LINK_SPEED_1mbps          10000	/* in unit of 100bps */
+#define MRVDRV_LINK_SPEED_11mbps         110000
+
+/** RSSI-related defines */
+/*	RSSI constants are used to implement 802.11 RSSI threshold 
+*	indication. if the Rx packet signal got too weak for 5 consecutive
+*	times, miniport driver (driver) will report this event to wrapper
+*/
+
+#define MRVDRV_NF_DEFAULT_SCAN_VALUE		(-96)
+
+/** RTS/FRAG related defines */
+#define MRVDRV_RTS_MIN_VALUE		0
+#define MRVDRV_RTS_MAX_VALUE		2347
+#define MRVDRV_FRAG_MIN_VALUE		256
+#define MRVDRV_FRAG_MAX_VALUE		2346
+
+/* Fixed IE size is 8 bytes time stamp + 2 bytes beacon interval +
+ * 2 bytes cap */
+#define MRVL_FIXED_IE_SIZE      12
+
+/* This is for firmware specific length */
+#define EXTRA_LEN	36
+
+#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \
+	(ETH_FRAME_LEN + sizeof(struct TxPD) + EXTRA_LEN)
+
+#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \
+	(ETH_FRAME_LEN + sizeof(struct RxPD) \
+	 + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN)
+
+#define	CMD_F_HOSTCMD		(1 << 0)
+
+/** WEP list macros & data structures */
+#define MRVL_KEY_BUFFER_SIZE_IN_BYTE  16
+
+/* to resolve CISCO AP extension */
+#define MRVDRV_SCAN_LIST_VAR_IE_SPACE  	256
+#define FW_IS_WPA_ENABLED(_adapter) \
+		(_adapter->fwCapInfo & FW_CAPINFO_WPA)
+
+#define FW_CAPINFO_WPA  	(1 << 0)
+#define WLAN_802_11_AI_REQFI_CAPABILITIES 	1
+#define WLAN_802_11_AI_REQFI_LISTENINTERVAL 	2
+#define WLAN_802_11_AI_REQFI_CURRENTAPADDRESS 	4
+
+#define WLAN_802_11_AI_RESFI_CAPABILITIES 	1
+#define WLAN_802_11_AI_RESFI_STATUSCODE 	2
+#define WLAN_802_11_AI_RESFI_ASSOCIATIONID 	4
+
+/** WPA Key LENGTH*/
+/* Support 4 keys per key set */
+#define MRVL_NUM_WPA_KEY_PER_SET        4
+#define MRVL_MAX_WPA_KEY_LENGTH 	32
+#define MRVL_MAX_KEY_WPA_KEY_LENGTH     32
+
+#define WPA_AES_KEY_LEN 		16
+#define WPA_TKIP_KEY_LEN 		32
+
+/* A few details needed for WEP (Wireless Equivalent Privacy) */
+/* 104 bits */
+#define MAX_WEP_KEY_SIZE		13
+/*40 bits RC4 - WEP*/
+#define MIN_WEP_KEY_SIZE		5
+
+#define RF_ANTENNA_1		0x1
+#define RF_ANTENNA_2		0x2
+#define RF_ANTENNA_AUTO		0xFFFF
+
+#define HOSTCMD_SUPPORTED_RATES G_SUPPORTED_RATES
+
+#define	BAND_B			(0x01)
+#define	BAND_G			(0x02)
+#define ALL_802_11_BANDS	(BAND_B | BAND_G)
+
+#define KEY_INFO_ENABLED	0x01
+
+/* For Wireless Extensions */
+#define		OID_MRVL_MFG_COMMAND	1
+
+#define SNR_BEACON		0
+#define SNR_RXPD		1
+#define NF_BEACON		2
+#define NF_RXPD			3
+
+/** MACRO DEFINITIONS */
+#define CAL_NF(NF)			((s32)(-(s32)(NF)))
+#define CAL_RSSI(SNR, NF) 		((s32)((s32)(SNR) + CAL_NF(NF)))
+#define SCAN_RSSI(RSSI)			(0x100 - ((u8)(RSSI)))
+
+#define DEFAULT_BCN_AVG_FACTOR		8
+#define DEFAULT_DATA_AVG_FACTOR		8
+#define AVG_SCALE			100
+#define CAL_AVG_SNR_NF(AVG, SNRNF, N)         \
+                        (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \
+                        ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \
+                        AVG_SCALE))  / N))
+
+#define WLAN_STATUS_SUCCESS			(0)
+#define WLAN_STATUS_FAILURE			(-1)
+#define WLAN_STATUS_NOT_ACCEPTED                (-2)
+
+#define B_SUPPORTED_RATES		8
+#define G_SUPPORTED_RATES		14
+
+#define	WLAN_SUPPORTED_RATES		14
+#define WLAN_MAX_SSID_LENGTH		32
+
+#define	MAX_LEDS			8
+
+/* S_SWAP : To swap 2 u8 */
+#define S_SWAP(a,b) 	do { \
+				u8  t = SArr[a]; \
+				SArr[a] = SArr[b]; SArr[b] = t; \
+			} while(0)
+
+/* SWAP: swap u8 */
+#define SWAP_U8(a,b)	{u8 t; t=a; a=b; b=t;}
+
+/* SWAP: swap u8 */
+#define SWAP_U16(a,b)	{u16 t; t=a; a=b; b=t;}
+
+#define wlan_le16_to_cpu(x) x
+#define wlan_le32_to_cpu(x) x
+#define wlan_le64_to_cpu(x) x
+#define wlan_cpu_to_le16(x) x
+#define wlan_cpu_to_le32(x) x
+#define wlan_cpu_to_le64(x) x
+
+/** Global Varibale Declaration */
+typedef struct _wlan_private wlan_private;
+typedef struct _wlan_adapter wlan_adapter;
+
+extern spinlock_t libertas_driver_lock;
+extern const char libertas_driver_version[];
+extern u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE];
+
+extern u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES];
+
+extern u8 libertas_supported_rates[G_SUPPORTED_RATES];
+
+extern u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES];
+
+extern u8 libertas_adhoc_rates_b[4];
+
+/** ENUM definition*/
+/** SNRNF_TYPE */
+enum SNRNF_TYPE {
+	TYPE_BEACON = 0,
+	TYPE_RXPD,
+	MAX_TYPE_B
+};
+
+/** SNRNF_DATA*/
+enum SNRNF_DATA {
+	TYPE_NOAVG = 0,
+	TYPE_AVG,
+	MAX_TYPE_AVG
+};
+
+/** WLAN_802_11_AUTH_ALG*/
+enum WLAN_802_11_AUTH_ALG {
+	AUTH_ALG_OPEN_SYSTEM = 1,
+	AUTH_ALG_SHARED_KEY = 2,
+	AUTH_ALG_NETWORK_EAP = 8,
+};
+
+/** WLAN_802_1X_AUTH_ALG */
+enum WLAN_802_1X_AUTH_ALG {
+	WLAN_1X_AUTH_ALG_NONE = 1,
+	WLAN_1X_AUTH_ALG_LEAP = 2,
+	WLAN_1X_AUTH_ALG_TLS = 4,
+	WLAN_1X_AUTH_ALG_TTLS = 8,
+	WLAN_1X_AUTH_ALG_MD5 = 16,
+};
+
+/** WLAN_802_11_ENCRYPTION_MODE */
+enum WLAN_802_11_ENCRYPTION_MODE {
+	CIPHER_NONE,
+	CIPHER_WEP40,
+	CIPHER_TKIP,
+	CIPHER_CCMP,
+	CIPHER_WEP104,
+};
+
+/** WLAN_802_11_POWER_MODE */
+enum WLAN_802_11_POWER_MODE {
+	Wlan802_11PowerModeCAM,
+	Wlan802_11PowerModeMAX_PSP,
+	Wlan802_11PowerModeFast_PSP,
+
+	/*not a real mode, defined as an upper bound */
+	Wlan802_11PowerModeMax
+};
+
+/** PS_STATE */
+enum PS_STATE {
+	PS_STATE_FULL_POWER,
+	PS_STATE_AWAKE,
+	PS_STATE_PRE_SLEEP,
+	PS_STATE_SLEEP
+};
+
+/** DNLD_STATE */
+enum DNLD_STATE {
+	DNLD_RES_RECEIVED,
+	DNLD_DATA_SENT,
+	DNLD_CMD_SENT
+};
+
+/** WLAN_MEDIA_STATE */
+enum WLAN_MEDIA_STATE {
+	WlanMediaStateConnected,
+	WlanMediaStateDisconnected
+};
+
+/** WLAN_802_11_PRIVACY_FILTER */
+enum WLAN_802_11_PRIVACY_FILTER {
+	Wlan802_11PrivFilterAcceptAll,
+	Wlan802_11PrivFilter8021xWEP
+};
+
+/** mv_ms_type */
+enum mv_ms_type {
+	MVMS_DAT = 0,
+	MVMS_CMD = 1,
+	MVMS_TXDONE = 2,
+	MVMS_EVENT
+};
+
+/* Hardware status codes (OID_GEN_HARDWARE_STATUS). */
+/** WLAN_HARDWARE_STATUS */
+enum WLAN_HARDWARE_STATUS {
+	WlanHardwareStatusReady,
+	WlanHardwareStatusInitializing,
+	WlanHardwareStatusReset,
+	WlanHardwareStatusClosing,
+	WlanHardwareStatusNotReady
+};
+
+/** WLAN_802_11_NETWORK_TYPE */
+enum WLAN_802_11_NETWORK_TYPE {
+	Wlan802_11FH,
+	Wlan802_11DS,
+	/*defined as upper bound */
+	Wlan802_11NetworkTypeMax
+};
+
+/** WLAN_802_11_NETWORK_INFRASTRUCTURE */
+enum WLAN_802_11_NETWORK_INFRASTRUCTURE {
+	Wlan802_11IBSS,
+	Wlan802_11Infrastructure,
+	Wlan802_11AutoUnknown,
+	/*defined as upper bound */
+	Wlan802_11InfrastructureMax
+};
+
+/** WLAN_802_11_AUTHENTICATION_MODE */
+enum WLAN_802_11_AUTHENTICATION_MODE {
+	Wlan802_11AuthModeOpen = 0x00,
+	Wlan802_11AuthModeShared = 0x01,
+	Wlan802_11AuthModeNetworkEAP = 0x80,
+};
+
+/** WLAN_802_11_WEP_STATUS */
+enum WLAN_802_11_WEP_STATUS {
+	Wlan802_11WEPEnabled,
+	Wlan802_11WEPDisabled,
+	Wlan802_11WEPKeyAbsent,
+	Wlan802_11WEPNotSupported, Wlan802_11Encryption2Enabled,
+	Wlan802_11Encryption2KeyAbsent,
+	Wlan802_11Encryption3Enabled,
+	Wlan802_11Encryption3KeyAbsent
+};
+
+/** SNMP_MIB_INDEX_e */
+enum SNMP_MIB_INDEX_e {
+	DesiredBssType_i = 0,
+	OpRateSet_i,
+	BcnPeriod_i,
+	DtimPeriod_i,
+	AssocRspTimeOut_i,
+	RtsThresh_i,
+	ShortRetryLim_i,
+	LongRetryLim_i,
+	FragThresh_i,
+	Dot11D_i,
+	Dot11H_i,
+	ManufId_i,
+	ProdId_i,
+	ManufOui_i,
+	ManufName_i,
+	ManufProdName_i,
+	ManufProdVer_i
+};
+
+/** KEY_TYPE_ID */
+enum KEY_TYPE_ID {
+	KEY_TYPE_ID_WEP = 0,
+	KEY_TYPE_ID_TKIP,
+	KEY_TYPE_ID_AES
+};
+
+/** KEY_INFO_WEP*/
+enum KEY_INFO_WEP {
+	KEY_INFO_WEP_DEFAULT_KEY = 0x01
+};
+
+/** KEY_INFO_TKIP */
+enum KEY_INFO_TKIP {
+	KEY_INFO_TKIP_MCAST = 0x01,
+	KEY_INFO_TKIP_UNICAST = 0x02,
+	KEY_INFO_TKIP_ENABLED = 0x04
+};
+
+/** KEY_INFO_AES*/
+enum KEY_INFO_AES {
+	KEY_INFO_AES_MCAST = 0x01,
+	KEY_INFO_AES_UNICAST = 0x02,
+	KEY_INFO_AES_ENABLED = 0x04
+};
+
+/** SNMP_MIB_VALUE_e */
+enum SNMP_MIB_VALUE_e {
+	SNMP_MIB_VALUE_INFRA = 1,
+	SNMP_MIB_VALUE_ADHOC
+};
+
+#endif				/* _WLAN_DEFS_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_dev.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_dev.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_dev.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_dev.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,412 @@
+/** @file wlan_dev.h
+  * @brief This file contains definitions and data structures specific
+  *        to Marvell 802.11 NIC. It contains the Device Information
+  *        structure wlan_adapter.  
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change log:
+	09/26/05: add Doxygen format comments 
+	01/11/06: Conditionalize new scan/join structures.
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+	05/08/06: Remove PermanentAddr from Adapter
+
+ ************************************************************/
+
+#ifndef _WLAN_DEV_H_
+#define _WLAN_DEV_H_
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+
+#include "wlan_defs.h"
+#include "wlan_scan.h"
+#include "wlan_thread.h"
+
+#define	MAX_BSSID_PER_CHANNEL		16
+
+#define NR_TX_QUEUE			3
+
+/* For the extended Scan */
+#define MAX_EXTENDED_SCAN_BSSID_LIST    MAX_BSSID_PER_CHANNEL * \
+						MRVDRV_MAX_CHANNEL_SIZE + 1
+
+#if 0
+typedef struct _PER_CHANNEL_BSSID_LIST_DATA {
+	u8 ucStart;
+	u8 ucNumEntry;
+} PER_CHANNEL_BSSID_LIST_DATA, *PPER_CHANNEL_BSSID_LIST_DATA;
+
+typedef struct _MRV_BSSID_IE_LIST {
+	struct WLAN_802_11_FIXED_IEs FixedIE;
+	u8 VariableIE[MRVDRV_SCAN_LIST_VAR_IE_SPACE];
+} MRV_BSSID_IE_LIST, *PMRV_BSSID_IE_LIST;
+#endif
+
+#define	MAX_REGION_CHANNEL_NUM	2
+
+/** Chan-Freq-TxPower mapping table*/
+struct chan_freq_power {
+	/** Channel Number		*/
+	u16 Channel;
+	/** Frequency of this Channel	*/
+	u32 Freq;
+	/** Max allowed Tx power level	*/
+	u16 MaxTxPower;
+	/** TRUE:channel unsupported;  FLASE:supported*/
+	u8 Unsupported;
+};
+
+/** region-band mapping table*/
+struct region_channel {
+	/** TRUE if this entry is valid		     */
+	u8 Valid;
+	/** Region code for US, Japan ...	     */
+	u8 Region;
+	/** Band B/G/A, used for BAND_CONFIG cmd	     */
+	u8 Band;
+	/** Actual No. of elements in the array below */
+	u8 NrCFP;
+	/** chan-freq-txpower mapping table*/
+	struct chan_freq_power *CFP;
+};
+
+struct wlan_802_11_security {
+	u8 WPAEnabled;
+	u8 WPA2Enabled;
+	enum WLAN_802_11_WEP_STATUS WEPStatus;
+	enum WLAN_802_11_AUTHENTICATION_MODE AuthenticationMode;
+	enum WLAN_802_1X_AUTH_ALG Auth1XAlg;
+	enum WLAN_802_11_ENCRYPTION_MODE EncryptionMode;
+};
+
+/** Current Basic Service Set State Structure */
+struct current_bss_params {
+	struct bss_descriptor BSSDescriptor;
+	/** bssid */
+	u8 bssid[ETH_ALEN];
+	/** ssid */
+	struct WLAN_802_11_SSID ssid;
+
+	/** band */
+	u8 band;
+	/** channel */
+	u8 channel;
+	/** number of rates supported */
+	int NumOfRates;
+	/** supported rates*/
+	u8 DataRates[WLAN_SUPPORTED_RATES];
+};
+
+/** sleep_params */
+struct sleep_params {
+	u16 sp_error;
+	u16 sp_offset;
+	u16 sp_stabletime;
+	u8 sp_calcontrol;
+	u8 sp_extsleepclk;
+	u16 sp_reserved;
+};
+
+/** sleep_period */
+struct sleep_period {
+	u16 period;
+	u16 reserved;
+};
+
+/** Data structure for the Marvell WLAN device */
+typedef struct _wlan_dev {
+	/** device name */
+	char name[DEV_NAME_LEN];
+	/** card pointer */
+	void *card;
+	/** IO port */
+	u32 ioport;
+	/** Upload received */
+	u32 upld_rcv;
+	/** Upload type */
+	u32 upld_typ;
+	/** Upload length */
+	u32 upld_len;
+	/** netdev pointer */
+	struct net_device *netdev;
+	/* Upload buffer */
+	u8 upld_buf[WLAN_UPLD_SIZE];
+	/* Download sent: 
+	   bit0 1/0=data_sent/data_tx_done, 
+	   bit1 1/0=cmd_sent/cmd_tx_done, 
+	   all other bits reserved 0 */
+	u8 dnld_sent;
+} wlan_dev_t, *pwlan_dev_t;
+
+/** Private structure for the MV device */
+struct _wlan_private {
+	int open;
+
+	wlan_adapter *adapter;
+	wlan_dev_t wlan_dev;
+
+	struct net_device_stats stats;
+
+	struct iw_statistics wstats;
+	struct dentry *debugfs_dir;
+	struct dentry *debugfs_devinfo;
+	struct dentry *debugfs_debug;
+	const struct firmware *firmware;
+	struct device *hotplug_device;
+
+	/** thread to service interrupts */
+	struct wlan_thread MainThread;
+
+#ifdef REASSOCIATION
+	/** thread to service mac events */
+	struct wlan_thread ReassocThread;
+#endif				/* REASSOCIATION */
+};
+
+/** Wlan Adapter data structure*/
+struct _wlan_adapter {
+	/** STATUS variables */
+	enum WLAN_HARDWARE_STATUS HardwareStatus;
+	u32 FWReleaseNumber;
+	u32 fwCapInfo;
+
+	u8 TmpTxBuf[WLAN_UPLD_SIZE];
+	u8 chip_rev;
+
+	/** Command-related variables */
+	u16 SeqNum;
+	struct CmdCtrlNode *CmdArray;
+	/** Current Command */
+	struct CmdCtrlNode *CurCmd;
+	int CurCmdRetCode;
+
+	/** Command Queues */
+	/** Free command buffers */
+	struct list_head CmdFreeQ;
+	/** Pending command buffers */
+	struct list_head CmdPendingQ;
+
+	/** Variables brought in from private structure */
+	int irq;
+
+	/** Async and Sync Event variables */
+	u32 IntCounter;
+	u32 IntCounterSaved;	/* save int for DS/PS */
+	u32 EventCause;
+	u8 nodeName[16];	/* nickname */
+
+	/** spin locks */
+	spinlock_t QueueSpinLock;
+
+	/** Timers */
+	struct timer_list command_timer;
+
+#ifdef REASSOCIATION
+	/**Reassociation timer*/
+	struct timer_list reassoc_timer;
+#endif				/* REASSOCIATION */
+
+	/* TX queue used in PS mode */
+	spinlock_t txqueue_lock;
+	struct sk_buff *tx_queue_ps[NR_TX_QUEUE];
+	unsigned int tx_queue_idx;
+
+	/** Event Queues */
+	wait_queue_head_t ds_awake_q;
+
+	u8 HisRegCpy;
+
+	/** current ssid/bssid related parameters*/
+	struct current_bss_params CurBssParams;
+
+	enum WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
+
+	struct bss_descriptor *pAttemptedBSSDesc;
+
+	struct WLAN_802_11_SSID AttemptedSSIDBeforeScan;
+	struct WLAN_802_11_SSID PreviousSSID;
+	u8 PreviousBSSID[ETH_ALEN];
+
+	struct bss_descriptor *ScanTable;
+	u32 NumInScanTable;
+
+	u8 ScanType;
+	u32 ScanMode;
+
+	u16 BeaconPeriod;
+	u8 AdhocCreate;
+
+	/** Capability Info used in Association, start, join */
+	struct IEEEtypes_CapInfo capInfo;
+
+#ifdef REASSOCIATION
+	/** Reassociation on and off */
+	u8 Reassoc_on;
+	struct semaphore ReassocSem;
+#endif				/* REASSOCIATION */
+
+	u8 ATIMEnabled;
+
+	/** MAC address information */
+	u8 CurrentAddr[ETH_ALEN];
+	u8 MulticastList[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN];
+	u32 NumOfMulticastMACAddr;
+
+	/** 802.11 statistics */
+	struct HostCmd_DS_802_11_GET_STAT wlan802_11Stat;
+
+	u8 AdHocCreated;
+	u8 AdHocFailed;
+
+	u16 EnableHwAuto;
+	u16 RateBitmap;
+	/** control G Rates */
+	u8 adhoc_grate_enabled;
+
+	u32 TxAntenna;
+	u32 RxAntenna;
+
+	u8 AdhocChannel;
+	u32 FragThsd;
+	u32 RTSThsd;
+
+	u32 DataRate;
+	u8 Is_DataRate_Auto;
+
+	/** number of association attempts for the current SSID cmd */
+	u32 m_NumAssociationAttemp;
+	u16 ListenInterval;
+	u16 Prescan;
+	u8 TxRetryCount;
+
+	/** Tx-related variables (for single packet tx) */
+	struct sk_buff *CurrentTxSkb;
+	u16 TxLockFlag;
+	u16 gen_null_pkg;
+
+	/** NIC Operation characteristics */
+	u32 LinkSpeed;
+	u16 CurrentPacketFilter;
+	u32 MediaConnectStatus;
+	u16 RegionCode;
+	u16 RegionTableIndex;
+	u16 TxPowerLevel;
+
+	/** POWER MANAGEMENT AND PnP SUPPORT */
+	u8 SurpriseRemoved;
+	u16 AtimWindow;
+
+	u16 PSMode;		/* Wlan802_11PowerModeCAM=disable
+				   Wlan802_11PowerModeMAX_PSP=enable */
+	u16 MultipleDtim;
+	u32 PSState;
+	u8 NeedToWakeup;
+
+	struct PS_CMD_ConfirmSleep libertas_ps_confirm_sleep;
+	u16 LocalListenInterval;
+	u16 NullPktInterval;
+
+	/** Encryption parameter */
+	struct wlan_802_11_security SecInfo;
+
+	struct MRVL_WEP_KEY WepKey[4];
+	u16 CurrentWepKeyIndex;
+	enum WLAN_802_11_WEP_STATUS EncryptionStatus;
+
+	u8 IsGTK_SET;
+
+	/** Encryption Key*/
+	u8 Wpa_ie[256];
+	u8 Wpa_ie_len;
+
+	struct MRVL_WPA_KEY WpaPwkKey, WpaGrpKey;
+
+	struct HostCmd_DS_802_11_KEY_MATERIAL aeskey;
+
+	/* Advanced Encryption Standard */
+
+	u16 RxAntennaMode;
+	u16 TxAntennaMode;
+
+	/** Requested Signal Strength*/
+	u16 bcn_avg_factor;
+	u16 data_avg_factor;
+	u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG];
+	u16 NF[MAX_TYPE_B][MAX_TYPE_AVG];
+	u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG];
+	u8 rawSNR[DEFAULT_DATA_AVG_FACTOR];
+	u8 rawNF[DEFAULT_DATA_AVG_FACTOR];
+	u16 nextSNRNF;
+	u16 numSNRNF;
+	u32 RxPDSNRAge;
+	u16 RxPDRate;
+
+	u8 RadioOn;
+	u32 Preamble;
+
+	/** Multi Bands Parameter*/
+	u8 libertas_supported_rates[G_SUPPORTED_RATES];
+
+	/** Blue Tooth Co-existence Arbitration */
+
+	/** sleep_params */
+	struct sleep_params sp;
+
+	/** sleep_period (Enhanced Power Save) */
+	struct sleep_period sleep_period;
+
+	/** RF calibration data */
+
+#define	MAX_REGION_CHANNEL_NUM	2
+	/** Region Channel data */
+	struct region_channel region_channel[MAX_REGION_CHANNEL_NUM];
+
+	struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM];
+
+	/** 11D and Domain Regulatory Data */
+	struct wlan_802_11d_domain_reg DomainReg;
+	struct parsed_region_chan_11d parsed_region_chan;
+
+	/** FSM variable for 11d support */
+	struct wlan_802_11d_state State11D;
+
+	/**	MISCELLANEOUS */
+	/* Card Information Structure */
+	u8 CisInfoBuf[512];
+	u16 CisInfoLen;
+	u8 *pRdeeprom;
+	struct wlan_offset_value OffsetValue;
+
+	wait_queue_head_t cmd_get_log;
+
+	struct HostCmd_DS_802_11_GET_LOG LogMsg;
+	u16 ScanProbes;
+
+	u32 PktTxCtrl;
+
+	u16 TxRate;
+	u32 linkmode;
+	u32 radiomode;
+	u32 debugmode;
+	u8 fw_ready;
+};
+
+#endif				/* _WLAN_DEV_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_fw.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_fw.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_fw.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_fw.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,442 @@
+/** @file wlan_fw.c
+  * @brief This file contains the initialization for FW and HW 
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	09/28/05: Add Doxygen format comments
+	01/05/06: Add kernel 2.6.x support	
+	01/11/06: Conditionalize new scan/join functions.
+	          Cleanup association response handler initialization.
+	01/06/05: Add FW file read
+	05/08/06: Remove the 2nd GET_HW_SPEC command and TempAddr/PermanentAddr
+
+********************************************************/
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/config.h>
+
+#include <linux/vmalloc.h>
+#include <linux/firmware.h>
+#include <linux/version.h>
+
+#include "host.h"
+#include "sbi.h"
+#include "wlan_defs.h"
+#include "wlan_decl.h"
+#include "wlan_dev.h"
+#include "wlan_fw.h"
+#include "wlan_wext.h"
+
+char *libertas_fw_name = NULL;
+
+module_param_named(fw_name, libertas_fw_name, charp, 0644);
+
+/** 
+ *  @brief This function downloads firmware image, gets
+ *  HW spec from firmware and set basic parameters to
+ *  firmware.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_setup_station_hw(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_FAILURE;
+	wlan_adapter *adapter = priv->adapter;
+
+	ENTER();
+
+	libertas_sbi_disable_host_int(priv);
+
+	if ((ret = request_firmware(&priv->firmware, libertas_fw_name,
+				    priv->hotplug_device)) < 0) {
+		PRINTM(MSG, "request_firmware() failed, error code = %#x\n",
+		       ret);
+		PRINTM(MSG, "%s not found in /lib/firmware\n", libertas_fw_name);
+		goto done;
+	}
+
+	ret = libertas_sbi_prog_firmware(priv);
+
+	release_firmware(priv->firmware);
+
+	if (ret) {
+		PRINTM(INFO, "Bootloader in invalid state!\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* check if the fimware is downloaded successfully or not */
+	if (libertas_sbi_verify_fw_download(priv)) {
+		PRINTM(INFO, "Firmware failed to be active in time!\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+#define RF_REG_OFFSET 0x07
+#define RF_REG_VALUE  0xc8
+
+	libertas_sbi_enable_host_int(priv);
+
+	/*
+	 * Read MAC address from HW
+	 */
+	memset(adapter->CurrentAddr, 0xff, ETH_ALEN);
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_GET_HW_SPEC,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	libertas_set_mac_packet_filter(priv);
+
+	/* Get the supported Data Rates */
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_DATA_RATE,
+				    HostCmd_ACT_GET_TX_RATE,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+
+	return (ret);
+}
+
+/** 
+ *  @brief This function allocates buffer for the member of adapter
+ *  structure like command buffer and BSSID list.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_allocate_adapter(wlan_private * priv)
+{
+	u32 ulBufSize;
+	wlan_adapter *Adapter = priv->adapter;
+
+	struct bss_descriptor *pTempScanTable;
+
+	/* Allocate buffer to store the BSSID list */
+	ulBufSize = sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST;
+	if (!(pTempScanTable = kmalloc(ulBufSize, GFP_KERNEL))) {
+		libertas_free_adapter(priv);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	Adapter->ScanTable = pTempScanTable;
+	memset(Adapter->ScanTable, 0, ulBufSize);
+
+	spin_lock_init(&Adapter->QueueSpinLock);
+
+	/* Allocate the command buffers */
+	libertas_allocate_cmd_buffer(priv);
+
+	memset(&Adapter->libertas_ps_confirm_sleep, 0, sizeof(struct PS_CMD_ConfirmSleep));
+	Adapter->libertas_ps_confirm_sleep.SeqNum = wlan_cpu_to_le16(++Adapter->SeqNum);
+	Adapter->libertas_ps_confirm_sleep.Command =
+	    wlan_cpu_to_le16(HostCmd_CMD_802_11_PS_MODE);
+	Adapter->libertas_ps_confirm_sleep.Size =
+	    wlan_cpu_to_le16(sizeof(struct PS_CMD_ConfirmSleep));
+	Adapter->libertas_ps_confirm_sleep.Result = 0;
+	Adapter->libertas_ps_confirm_sleep.Action =
+	    wlan_cpu_to_le16(HostCmd_SubCmd_Sleep_Confirmed);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function initializes the adapter structure
+ *  and set default value to the member of adapter.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   n/a
+ */
+static void wlan_init_adapter(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int i;
+
+	Adapter->ScanProbes = 0;
+
+	Adapter->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR;
+	Adapter->data_avg_factor = DEFAULT_DATA_AVG_FACTOR;
+
+	/* ATIM params */
+	Adapter->AtimWindow = 0;
+	Adapter->ATIMEnabled = 0;
+
+	Adapter->MediaConnectStatus = WlanMediaStateDisconnected;
+	Adapter->LinkSpeed = MRVDRV_LINK_SPEED_1mbps;
+	memset(Adapter->CurrentAddr, 0xff, ETH_ALEN);
+
+	/* Status variables */
+	Adapter->HardwareStatus = WlanHardwareStatusInitializing;
+
+	/* scan type */
+	Adapter->ScanType = HostCmd_SCAN_TYPE_ACTIVE;
+
+	/* scan mode */
+	Adapter->ScanMode = HostCmd_BSS_TYPE_ANY;
+
+	/* 802.11 specific */
+	Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled;
+	for (i = 0; i < sizeof(Adapter->WepKey) / sizeof(Adapter->WepKey[0]);
+	     i++)
+		memset(&Adapter->WepKey[i], 0, sizeof(struct MRVL_WEP_KEY));
+	Adapter->CurrentWepKeyIndex = 0;
+	Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen;
+	Adapter->SecInfo.Auth1XAlg = WLAN_1X_AUTH_ALG_NONE;
+	Adapter->SecInfo.EncryptionMode = CIPHER_NONE;
+	Adapter->InfrastructureMode = Wlan802_11Infrastructure;
+
+	Adapter->NumInScanTable = 0;
+	Adapter->pAttemptedBSSDesc = NULL;
+#ifdef REASSOCIATION
+	init_MUTEX(&Adapter->ReassocSem);
+#endif
+
+	Adapter->Prescan = CMD_ENABLED;
+
+	memset(&Adapter->CurBssParams, 0, sizeof(Adapter->CurBssParams));
+
+	/* PnP and power profile */
+	Adapter->SurpriseRemoved = 0;
+
+	Adapter->CurrentPacketFilter =
+	    HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON;
+
+	Adapter->RadioOn = RADIO_ON;
+#ifdef REASSOCIATION
+	Adapter->Reassoc_on = 1;
+#endif				/* REASSOCIATION */
+	Adapter->TxAntenna = RF_ANTENNA_2;
+	Adapter->RxAntenna = RF_ANTENNA_AUTO;
+
+	Adapter->Is_DataRate_Auto = 1;
+	Adapter->BeaconPeriod = MRVDRV_BEACON_INTERVAL;
+
+	// set default value of capInfo.
+#define SHORT_PREAMBLE_ALLOWED		1
+	memset(&Adapter->capInfo, 0, sizeof(Adapter->capInfo));
+	Adapter->capInfo.ShortPreamble = SHORT_PREAMBLE_ALLOWED;
+
+	Adapter->AdhocChannel = DEFAULT_AD_HOC_CHANNEL;
+
+	Adapter->PSMode = Wlan802_11PowerModeCAM;
+	Adapter->MultipleDtim = MRVDRV_DEFAULT_MULTIPLE_DTIM;
+
+	Adapter->ListenInterval = MRVDRV_DEFAULT_LISTEN_INTERVAL;
+
+	Adapter->PSState = PS_STATE_FULL_POWER;
+	Adapter->NeedToWakeup = 0;
+	Adapter->LocalListenInterval = 0;	/* default value in firmware will be used */
+
+	Adapter->DataRate = 0;	// Initially indicate the rate as auto 
+
+	Adapter->adhoc_grate_enabled = 0;
+
+	Adapter->IntCounter = Adapter->IntCounterSaved = 0;
+
+	Adapter->EncryptionStatus = Wlan802_11WEPDisabled;
+
+	Adapter->CurrentTxSkb = NULL;
+	Adapter->PktTxCtrl = 0;
+
+	memset(&Adapter->tx_queue_ps, 0, NR_TX_QUEUE*sizeof(struct sk_buff*));
+	Adapter->tx_queue_idx = 0;
+	spin_lock_init(&Adapter->txqueue_lock);
+
+	return;
+}
+
+static void command_timer_fn(unsigned long data);
+
+/** 
+ *  @brief This function initializes firmware
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_init_fw(wlan_private * priv)
+{
+	int ret = WLAN_STATUS_FAILURE;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* Allocate adapter structure */
+	if ((ret = wlan_allocate_adapter(priv)) != WLAN_STATUS_SUCCESS) {
+		goto done;
+	}
+
+	/* init adapter structure */
+	wlan_init_adapter(priv);
+
+	/* init timer etc. */
+	setup_timer(&Adapter->command_timer, command_timer_fn,
+			(unsigned long)priv);
+
+#ifdef REASSOCIATION
+        /* Initialize the timer for the reassociation */
+	setup_timer(&Adapter->reassoc_timer, libertas_reassoc_timer_fn,
+			(unsigned long)priv);	
+#endif                          /* REASSOCIATION */
+
+	/* download fimrware etc. */
+	if ((ret = wlan_setup_station_hw(priv)) != WLAN_STATUS_SUCCESS) {
+		del_timer_sync(&Adapter->command_timer);
+#ifdef REASSOCIATION
+		del_timer_sync(&Adapter->reassoc_timer);
+#endif
+		goto done;
+	}
+
+	/* init 802.11d */
+	libertas_init_11d(priv);
+
+	ret = WLAN_STATUS_SUCCESS;
+done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function frees the structure of adapter
+ *    
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   n/a
+ */
+void libertas_free_adapter(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (!Adapter) {
+		PRINTM(INFO, "Why double free adapter?:)\n");
+		return;
+	}
+
+	PRINTM(INFO, "Free Command buffer\n");
+	libertas_free_cmd_buffer(priv);
+
+	PRINTM(INFO, "Free CommandTimer\n");
+	del_timer(&Adapter->command_timer);
+#ifdef REASSOCIATION
+	PRINTM(INFO, "Free reassoc_timer\n");
+	del_timer(&Adapter->reassoc_timer);
+#endif				/* REASSOCIATION */
+
+	PRINTM(INFO, "Free ScanTable\n");
+	if (Adapter->ScanTable) {
+		kfree(Adapter->ScanTable);
+		Adapter->ScanTable = NULL;
+	}
+
+	PRINTM(INFO, "Free Adapter\n");
+
+	/* Free the adapter object itself */
+	kfree(Adapter);
+	priv->adapter = NULL;
+	LEAVE();
+}
+
+/** 
+ *  @brief This function handles the timeout of command sending.
+ *  It will re-send the same command again.
+ *  
+ *  @param FunctionContext    A pointer to FunctionContext
+ *  @return 	   n/a
+ */
+static void command_timer_fn(unsigned long data)
+{
+	wlan_private *priv = (wlan_private *)data;
+	wlan_adapter *Adapter = priv->adapter;
+	struct CmdCtrlNode *pTempNode;
+	ulong flags;
+
+	ENTER();
+
+	PRINTM(FATAL, "command_timer_fn fired.\n");
+
+	pTempNode = Adapter->CurCmd;
+
+	if (!Adapter->fw_ready)
+		return;
+
+	if (pTempNode == NULL) {
+		PRINTM(INFO, "PTempnode Empty\n");
+		return;
+	}
+
+	spin_lock_irqsave(&Adapter->QueueSpinLock, flags);
+	Adapter->CurCmd = NULL;
+	spin_unlock_irqrestore(&Adapter->QueueSpinLock, flags);
+
+	PRINTM(INFO, "Re-sending same command as it timeout...!\n");
+	libertas_queue_cmd(Adapter, pTempNode, 0);
+
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+	return;
+}
+
+#ifdef REASSOCIATION
+/** 
+ *  @brief This function triggers re-association by waking up
+ *  re-assoc thread.
+ *  
+ *  @param FunctionContext    A pointer to FunctionContext
+ *  @return 	   n/a
+ */
+void libertas_reassoc_timer_fn(unsigned long data)
+{
+	wlan_private *priv = (wlan_private *)data;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	PRINTM(INFO, "reassoc_timer fired.\n");
+	if (Adapter->PSState != PS_STATE_FULL_POWER) {
+		/* wait until Exit_PS command returns */
+		mod_timer(&Adapter->reassoc_timer, jiffies + 1*HZ);
+		PRINTM(INFO, "libertas_reassoc_timer_fn(PSState=%d) waiting"
+		       "for Exit_PS done\n", Adapter->PSState);
+		LEAVE();
+		return;
+	}
+
+	PRINTM(INFO, "Waking Up the Event Thread\n");
+
+	wake_up_interruptible(&priv->ReassocThread.waitQ);
+
+	LEAVE();
+	return;
+}
+#endif				/* REASSOCIATION */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_fw.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_fw.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_fw.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_fw.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,44 @@
+/** @file wlan_fw.h
+  * @brief This header file contains FW interface related definitions.
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change log:
+	09/26/05: add Doxygen format comments 
+ ************************************************************/
+
+#ifndef _WLAN_FW_H_
+#define _WLAN_FW_H_
+
+#ifndef DEV_NAME_LEN
+#define DEV_NAME_LEN            32
+#endif
+
+#define MAXKEYLEN           13
+
+/* The number of times to try when waiting for downloaded firmware to 
+ become active. (polling the scratch register). */
+
+#define MAX_FIRMWARE_POLL_TRIES     100
+
+#define FIRMWARE_TRANSFER_BLOCK_SIZE    1536
+
+int libertas_init_fw(wlan_private * priv);
+
+#endif				/* _WLAN_FW_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_ioctl.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_ioctl.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_ioctl.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_ioctl.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,2817 @@
+/** @file  wlan_wext.c
+  * @brief This file contains ioctl functions
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd.
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+  * (the "License").  You may use, redistribute and/or modify this File in
+  * accordance with the terms and conditions of the License, a copy of which
+  * is available along with the File in the license.txt file or by writing to
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+  * this warranty disclaimer.
+  *
+  */
+
+/*
+ * Editor's comment:
+ *
+ * This whole file is a total mess, the author needs some education
+ * about ioctl handling.
+ *
+ * For now it probably needs to stay in order not to break existing
+ * tools, but we need to come up with some proper replacement for
+ * those calls that are actually needed.
+ *
+ * 	-arnd
+ */
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "radiotap.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+#include "wlan_join.h"
+#include "wlan_wext.h"
+
+#define MAX_SCAN_CELL_SIZE      (IW_EV_ADDR_LEN + \
+				MRVDRV_MAX_SSID_LENGTH + \
+				IW_EV_UINT_LEN + IW_EV_FREQ_LEN + \
+				IW_EV_QUAL_LEN + MRVDRV_MAX_SSID_LENGTH + \
+				IW_EV_PARAM_LEN + 40)	/* 40 for WPAIE */
+
+#define WAIT_FOR_SCAN_RRESULT_MAX_TIME (10 * HZ)
+
+/**
+ *  @brief Set RX Antenna
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param Mode			RF antenna mode
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int SetRxAntenna(wlan_private * priv, int Mode)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+
+	if (Mode != RF_ANTENNA_1 && Mode != RF_ANTENNA_2
+	    && Mode != RF_ANTENNA_AUTO) {
+		return -EINVAL;
+	}
+
+	Adapter->RxAntennaMode = Mode;
+
+	PRINTM(INFO, "SET RX Antenna Mode to 0x%04x\n", Adapter->RxAntennaMode);
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_ANTENNA,
+				    HostCmd_ACT_SET_RX,
+				    HostCmd_OPTION_WAITFORRSP, 0,
+				    &Adapter->RxAntennaMode);
+	return ret;
+}
+
+/**
+ *  @brief Set TX Antenna
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param Mode			RF antenna mode
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int SetTxAntenna(wlan_private * priv, int Mode)
+{
+	int ret = 0;
+	wlan_adapter *Adapter = priv->adapter;
+
+	if ((Mode != RF_ANTENNA_1) && (Mode != RF_ANTENNA_2)
+	    && (Mode != RF_ANTENNA_AUTO)) {
+		return -EINVAL;
+	}
+
+	Adapter->TxAntennaMode = Mode;
+
+	PRINTM(INFO, "SET TX Antenna Mode to 0x%04x\n", Adapter->TxAntennaMode);
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_ANTENNA,
+				    HostCmd_ACT_SET_TX,
+				    HostCmd_OPTION_WAITFORRSP, 0,
+				    &Adapter->TxAntennaMode);
+
+	return ret;
+}
+
+/**
+ *  @brief Get RX Antenna
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param buf			A pointer to recieve antenna mode
+ *  @return 	   		length of buf
+ */
+static int GetRxAntenna(wlan_private * priv, char *buf)
+{
+	int ret = 0;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	// clear it, so we will know if the value
+	// returned below is correct or not.
+	Adapter->RxAntennaMode = 0;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_ANTENNA,
+				    HostCmd_ACT_GET_RX,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	PRINTM(INFO, "Get Rx Antenna Mode:0x%04x\n", Adapter->RxAntennaMode);
+
+	LEAVE();
+
+	return sprintf(buf, "0x%04x", Adapter->RxAntennaMode) + 1;
+}
+
+/**
+ *  @brief Get TX Antenna
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param buf			A pointer to recieve antenna mode
+ *  @return 	   		length of buf
+ */
+static int GetTxAntenna(wlan_private * priv, char *buf)
+{
+	int ret = 0;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	// clear it, so we will know if the value
+	// returned below is correct or not.
+	Adapter->TxAntennaMode = 0;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_ANTENNA,
+				    HostCmd_ACT_GET_TX,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	PRINTM(INFO, "Get Tx Antenna Mode:0x%04x\n", Adapter->TxAntennaMode);
+
+	LEAVE();
+
+	return sprintf(buf, "0x%04x", Adapter->TxAntennaMode) + 1;
+}
+
+/**
+ *  @brief Set Region
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param region_code		region code
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_region(wlan_private * priv, u16 region_code)
+{
+	int i;
+
+	ENTER();
+
+	for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) {
+		// use the region code to search for the index
+		if (region_code == libertas_region_code_to_index[i]) {
+			priv->adapter->RegionTableIndex = (u16) i;
+			priv->adapter->RegionCode = region_code;
+			break;
+		}
+	}
+
+	// if it's unidentified region code
+	if (i >= MRVDRV_MAX_REGION_CODE) {
+		PRINTM(INFO, "Region Code not identified\n");
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	if (libertas_set_regiontable(priv, priv->adapter->RegionCode, 0)) {
+		LEAVE();
+		return -EINVAL;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get/Set Firmware wakeup method
+ *
+ *  @param priv		A pointer to wlan_private structure
+ *  @param wrq	   	A pointer to user data
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+static int wlan_txcontrol(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int data;
+	ENTER();
+
+	if ((int)wrq->u.data.length == 0) {
+		if (copy_to_user
+		    (wrq->u.data.pointer, &Adapter->PktTxCtrl, sizeof(u32))) {
+			PRINTM(MSG, "copy_to_user failed!\n");
+			return -EFAULT;
+		}
+	} else {
+		if ((int)wrq->u.data.length > 1) {
+			PRINTM(MSG, "ioctl too many args!\n");
+			return -EFAULT;
+		}
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		Adapter->PktTxCtrl = (u32) data;
+	}
+
+	wrq->u.data.length = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get/Set NULL Package generation interval
+ *
+ *  @param priv		A pointer to wlan_private structure
+ *  @param wrq	   	A pointer to user data
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+static int wlan_null_pkt_interval(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int data;
+	ENTER();
+
+	if ((int)wrq->u.data.length == 0) {
+		data = Adapter->NullPktInterval;
+
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			PRINTM(MSG, "copy_to_user failed!\n");
+			return -EFAULT;
+		}
+	} else {
+		if ((int)wrq->u.data.length > 1) {
+			PRINTM(MSG, "ioctl too many args!\n");
+			return -EFAULT;
+		}
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		Adapter->NullPktInterval = data;
+	}
+
+	wrq->u.data.length = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief wlan hostcmd ioctl handler
+ *
+ *  @param dev                  A pointer to net_device structure
+ *  @param req		        A pointer to ifreq structure
+ *  @param cmd			command
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_hostcmd_ioctl(struct net_device *dev, struct ifreq *req,
+			      int cmd)
+{
+	u8 *tempResponseBuffer;
+	struct CmdCtrlNode *pCmdNode;
+	struct HostCmd_DS_GEN *gencmd, *pCmdPtr;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	u16 wait_option = 0;
+
+	ENTER();
+
+	/*
+	 * Get a free command control node
+	 */
+	if (!(pCmdNode = libertas_get_free_cmd_ctrl_node(priv))) {
+		PRINTM(INFO, "Failed libertas_get_free_cmd_ctrl_node\n");
+		return -ENOMEM;
+	}
+
+	if (!(tempResponseBuffer = kmalloc(3000, GFP_KERNEL))) {
+		PRINTM(INFO, "ERROR: Failed to allocate response buffer!\n");
+		return -ENOMEM;
+	}
+
+	wait_option |= HostCmd_OPTION_WAITFORRSP;
+
+	libertas_set_cmd_ctrl_node(priv, pCmdNode, 0, wait_option, NULL);
+	init_waitqueue_head(&pCmdNode->cmdwait_q);
+
+	pCmdPtr = (struct HostCmd_DS_GEN *)pCmdNode->BufVirtualAddr;
+	gencmd = (struct HostCmd_DS_GEN *)req->ifr_data;
+
+	/*
+	 * Copy the whole command into the command buffer
+	 */
+	if (copy_from_user(pCmdPtr, req->ifr_data, gencmd->Size)) {
+		PRINTM(INFO, "Copy from user failed\n");
+		kfree(tempResponseBuffer);
+		return -EFAULT;
+	}
+
+	pCmdNode->pdata_buf = tempResponseBuffer;
+	pCmdNode->CmdFlags |= CMD_F_HOSTCMD;
+
+	pCmdPtr->SeqNum = ++priv->adapter->SeqNum;
+	pCmdPtr->Result = 0;
+
+	PRINTM(INFO, "HOSTCMD Command: 0x%04x Size: %d SeqNum: %d\n",
+	       pCmdPtr->Command, pCmdPtr->Size, pCmdPtr->SeqNum);
+	HEXDUMP("Command Data", (u8 *) (pCmdPtr),
+		min_t(u16, 32, pCmdPtr->Size));
+	PRINTM(INFO, "Copying data from : (user)0x%p -> 0x%p(driver)\n",
+	       req->ifr_data, pCmdPtr);
+
+	pCmdNode->CmdWaitQWoken = 0;
+	libertas_queue_cmd(Adapter, pCmdNode, 1);
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	if (wait_option & HostCmd_OPTION_WAITFORRSP) {
+		/* Sleep until response is generated by FW */
+		wait_event_interruptible(pCmdNode->cmdwait_q,
+					 pCmdNode->CmdWaitQWoken);
+	}
+
+	/* Copy the response back to user space */
+	pCmdPtr = (struct HostCmd_DS_GEN *)tempResponseBuffer;
+
+	if (copy_to_user(req->ifr_data, tempResponseBuffer, pCmdPtr->Size))
+		PRINTM(INFO, "ERROR: copy_to_user failed!\n");
+
+	kfree(tempResponseBuffer);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get Rx Info
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wreq		        A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success
+ */
+static int wlan_get_rxinfo(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int data[2];
+	ENTER();
+	data[0] = Adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
+	data[1] = Adapter->RxPDRate;
+	if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return -EFAULT;
+	}
+	wrq->u.data.length = 2;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get SNR
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wreq		        A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_snr(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+	int data[4];
+
+	ENTER();
+	memset(data, 0, sizeof(data));
+	if (wrq->u.data.length) {
+		if (copy_from_user
+		    (data, wrq->u.data.pointer,
+		     min_t(size_t, wrq->u.data.length, 4) * sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+	}
+	if ((wrq->u.data.length == 0) || (data[0] == 0) || (data[0] == 1)) {
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			ret = libertas_prepare_and_send_command(priv,
+						    HostCmd_CMD_802_11_RSSI,
+						    0,
+						    HostCmd_OPTION_WAITFORRSP,
+						    0, NULL);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+
+	if (wrq->u.data.length == 0) {
+		data[0] = Adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
+		data[1] = Adapter->SNR[TYPE_BEACON][TYPE_AVG];
+		data[2] = Adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
+		data[3] = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 4)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = 4;
+	} else if (data[0] == 0) {
+		data[0] = Adapter->SNR[TYPE_BEACON][TYPE_NOAVG];
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = 1;
+	} else if (data[0] == 1) {
+		data[0] = Adapter->SNR[TYPE_BEACON][TYPE_AVG];
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = 1;
+	} else if (data[0] == 2) {
+		data[0] = Adapter->SNR[TYPE_RXPD][TYPE_NOAVG];
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = 1;
+	} else if (data[0] == 3) {
+		data[0] = Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = 1;
+	} else {
+		return -ENOTSUPP;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get/Set Adhoc beacon Interval
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wreq		        A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_beacon_interval(wlan_private * priv, struct iwreq *wrq)
+{
+	int data;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (wrq->u.data.length > 0) {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		PRINTM(INFO, "WLAN SET BEACON INTERVAL: %d\n", data);
+		if ((data > MRVDRV_MAX_BEACON_INTERVAL)
+		    || (data < MRVDRV_MIN_BEACON_INTERVAL))
+			return -ENOTSUPP;
+		Adapter->BeaconPeriod = data;
+	}
+	data = Adapter->BeaconPeriod;
+	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return -EFAULT;
+	}
+
+	wrq->u.data.length = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get RSSI
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wreq		        A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_rssi(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+	int temp;
+	int data = 0;
+	int *val;
+
+	ENTER();
+	data = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	if ((data == 0) || (data == 1)) {
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_RSSI,
+					    0, HostCmd_OPTION_WAITFORRSP,
+					    0, NULL);
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+
+	switch (data) {
+	case 0:
+
+		temp = CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
+				Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+		break;
+	case 1:
+		temp = CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_AVG],
+				Adapter->NF[TYPE_BEACON][TYPE_AVG]);
+		break;
+	case 2:
+		temp = CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
+				Adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
+		break;
+	case 3:
+		temp = CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+				Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+	val = (int *)wrq->u.name;
+	*val = temp;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get NF
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wreq		        A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_nf(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+	int temp;
+	int data = 0;
+	int *val;
+
+	ENTER();
+	data = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	if ((data == 0) || (data == 1)) {
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_RSSI,
+					    0, HostCmd_OPTION_WAITFORRSP,
+					    0, NULL);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+
+	switch (data) {
+	case 0:
+		temp = Adapter->NF[TYPE_BEACON][TYPE_NOAVG];
+		break;
+	case 1:
+		temp = Adapter->NF[TYPE_BEACON][TYPE_AVG];
+		break;
+	case 2:
+		temp = Adapter->NF[TYPE_RXPD][TYPE_NOAVG];
+		break;
+	case 3:
+		temp = Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE;
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	temp = CAL_NF(temp);
+
+	PRINTM(INFO, "***temp = %d\n", temp);
+	val = (int *)wrq->u.name;
+	*val = temp;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get TxRate
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_txrate_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int *pdata;
+	struct iwreq *wrq = (struct iwreq *)req;
+	int ret = WLAN_STATUS_SUCCESS;
+	ENTER();
+	Adapter->TxRate = 0;
+	PRINTM(INFO, "wlan_get_txrate_ioctl\n");
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_TX_RATE_QUERY,
+				    HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP,
+				    0, NULL);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+	pdata = (int *)wrq->u.name;
+	*pdata = (int)Adapter->TxRate;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get Adhoc Status
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_adhoc_status_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	char status[64];
+	wlan_adapter *Adapter = priv->adapter;
+
+	memset(status, 0, sizeof(status));
+
+	switch (Adapter->InfrastructureMode) {
+	case Wlan802_11IBSS:
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			if (Adapter->AdhocCreate)
+				memcpy(&status, "AdhocStarted", sizeof(status));
+			else
+				memcpy(&status, "AdhocJoined", sizeof(status));
+		} else {
+			memcpy(&status, "AdhocIdle", sizeof(status));
+		}
+		break;
+	case Wlan802_11Infrastructure:
+		memcpy(&status, "InfraMode", sizeof(status));
+		break;
+	default:
+		memcpy(&status, "AutoUnknownMode", sizeof(status));
+		break;
+	}
+
+	PRINTM(INFO, "Status = %s\n", status);
+	wrq->u.data.length = strlen(status) + 1;
+
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer,
+				 &status, wrq->u.data.length))
+			return -EFAULT;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get Driver Version
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_version_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int len;
+	char buf[128];
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	libertas_get_version(priv->adapter, buf, sizeof(buf) - 1);
+
+	len = strlen(buf);
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, buf, len)) {
+			PRINTM(INFO, "CopyToUser failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = len;
+	}
+
+	PRINTM(INFO, "wlan version: %s\n", buf);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Read/Write adapter registers
+ *
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_regrdwr_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	wlan_ioctl_regrdwr regrdwr;
+	struct wlan_offset_value offval;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (copy_from_user(&regrdwr, req->ifr_data, sizeof(regrdwr))) {
+		PRINTM(INFO,
+		       "copy of regrdwr for wlan_regrdwr_ioctl from user failed \n");
+		LEAVE();
+		return -EFAULT;
+	}
+
+	if (regrdwr.WhichReg == REG_EEPROM) {
+		PRINTM(MSG, "Inside RDEEPROM\n");
+		Adapter->pRdeeprom =
+		    (char *)kmalloc((regrdwr.NOB + sizeof(regrdwr)),
+				    GFP_KERNEL);
+		if (!Adapter->pRdeeprom)
+			return -ENOMEM;
+		memcpy(Adapter->pRdeeprom, &regrdwr, sizeof(regrdwr));
+		/* +14 is for Action, Offset, and NOB in
+		 * response */
+		PRINTM(INFO, "Action:%d Offset: %x NOB: %02x\n",
+		       regrdwr.Action, regrdwr.Offset, regrdwr.NOB);
+
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_EEPROM_ACCESS,
+					    regrdwr.Action,
+					    HostCmd_OPTION_WAITFORRSP, 0,
+					    &regrdwr);
+
+		if (ret) {
+			if (Adapter->pRdeeprom)
+				kfree(Adapter->pRdeeprom);
+			LEAVE();
+			return ret;
+		}
+
+		mdelay(10);
+
+		/*
+		 * Return the result back to the user
+		 */
+
+		if (regrdwr.Action == HostCmd_ACT_GEN_READ) {
+			if (copy_to_user
+			    (req->ifr_data, Adapter->pRdeeprom,
+			     sizeof(regrdwr) + regrdwr.NOB)) {
+				if (Adapter->pRdeeprom)
+					kfree(Adapter->pRdeeprom);
+				PRINTM(INFO,
+				       "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n");
+				LEAVE();
+				return -EFAULT;
+			}
+		}
+
+		if (Adapter->pRdeeprom)
+			kfree(Adapter->pRdeeprom);
+
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	offval.offset = regrdwr.Offset;
+	offval.value = (regrdwr.Action) ? regrdwr.Value : 0x00;
+
+	PRINTM(INFO, "RegAccess: %02x Action:%d "
+	       "Offset: %04x Value: %04x\n",
+	       regrdwr.WhichReg, regrdwr.Action, offval.offset, offval.value);
+
+	/*
+	 * regrdwr.WhichReg should contain the command that
+	 * corresponds to which register access is to be
+	 * performed HostCmd_CMD_MAC_REG_ACCESS 0x0019
+	 * HostCmd_CMD_BBP_REG_ACCESS 0x001a
+	 * HostCmd_CMD_RF_REG_ACCESS 0x001b
+	 */
+	ret = libertas_prepare_and_send_command(priv, regrdwr.WhichReg,
+				    regrdwr.Action, HostCmd_OPTION_WAITFORRSP,
+				    0, &offval);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	mdelay(10);
+
+	/*
+	 * Return the result back to the user
+	 */
+	regrdwr.Value = Adapter->OffsetValue.value;
+	if (regrdwr.Action == HostCmd_ACT_GEN_READ) {
+		if (copy_to_user(req->ifr_data, &regrdwr, sizeof(regrdwr))) {
+			PRINTM(INFO,
+			       "copy of regrdwr for wlan_regrdwr_ioctl to user failed \n");
+			LEAVE();
+			return -EFAULT;
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set/Get WPA IE
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_setwpaie_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (wrq->u.data.length) {
+		if (wrq->u.data.length > sizeof(Adapter->Wpa_ie)) {
+			PRINTM(INFO, "failed to copy WPA IE, too big \n");
+			return -EFAULT;
+		}
+		if (copy_from_user(Adapter->Wpa_ie, wrq->u.data.pointer,
+				   wrq->u.data.length)) {
+			PRINTM(INFO, "failed to copy WPA IE \n");
+			return -EFAULT;
+		}
+		Adapter->Wpa_ie_len = wrq->u.data.length;
+		PRINTM(INFO, "Set Wpa_ie_len=%d IE=%#x\n", Adapter->Wpa_ie_len,
+		       Adapter->Wpa_ie[0]);
+		HEXDUMP("Wpa_ie", Adapter->Wpa_ie, Adapter->Wpa_ie_len);
+		if (Adapter->Wpa_ie[0] == WPA_IE)
+			Adapter->SecInfo.WPAEnabled = 1;
+		else if (Adapter->Wpa_ie[0] == WPA2_IE)
+			Adapter->SecInfo.WPA2Enabled = 1;
+		else {
+			Adapter->SecInfo.WPAEnabled = 0;
+			Adapter->SecInfo.WPA2Enabled = 0;
+		}
+	} else {
+		memset(Adapter->Wpa_ie, 0, sizeof(Adapter->Wpa_ie));
+		Adapter->Wpa_ie_len = wrq->u.data.length;
+		PRINTM(INFO, "Reset Wpa_ie_len=%d IE=%#x\n",
+		       Adapter->Wpa_ie_len, Adapter->Wpa_ie[0]);
+		Adapter->SecInfo.WPAEnabled = 0;
+		Adapter->SecInfo.WPA2Enabled = 0;
+	}
+
+	// enable/disable RSN in firmware if WPA is enabled/disabled
+	// depending on variable Adapter->SecInfo.WPAEnabled is set or not
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_ENABLE_RSN,
+				    HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP,
+				    0, NULL);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Auto Prescan
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_subcmd_setprescan_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	int data;
+	wlan_adapter *Adapter = priv->adapter;
+	int *val;
+
+	ENTER();
+
+	data = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	PRINTM(INFO, "WLAN_SUBCMD_SET_PRESCAN %d\n", data);
+	switch (data) {
+	case CMD_ENABLED:
+		Adapter->Prescan = 1;
+		break;
+	case CMD_DISABLED:
+		Adapter->Prescan = 0;
+		break;
+	default:
+		break;
+	}
+
+	data = Adapter->Prescan;
+	val = (int *)wrq->u.name;
+	*val = data;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set multiple dtim
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_multiple_dtim_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	u32 mdtim;
+	int idata;
+	int ret = -EINVAL;
+
+	ENTER();
+
+	idata = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	mdtim = (u32) idata;
+	if (((mdtim >= MRVDRV_MIN_MULTIPLE_DTIM)
+	     && (mdtim <= MRVDRV_MAX_MULTIPLE_DTIM))
+	    || (mdtim == MRVDRV_IGNORE_MULTIPLE_DTIM)) {
+		priv->adapter->MultipleDtim = mdtim;
+		ret = WLAN_STATUS_SUCCESS;
+	}
+	if (ret)
+		PRINTM(INFO, "Invalid parameter, MultipleDtim not changed.\n");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set authentication mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_setauthalg_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int alg;
+	struct iwreq *wrq = (struct iwreq *)req;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (wrq->u.data.flags == 0) {
+		//from iwpriv subcmd
+		alg = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	} else {
+		//from wpa_supplicant subcmd
+		if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(alg))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+	}
+
+	PRINTM(INFO, "auth alg is %#x\n", alg);
+
+	switch (alg) {
+	case AUTH_ALG_SHARED_KEY:
+		Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeShared;
+		break;
+	case AUTH_ALG_NETWORK_EAP:
+		Adapter->SecInfo.AuthenticationMode =
+		    Wlan802_11AuthModeNetworkEAP;
+		break;
+	case AUTH_ALG_OPEN_SYSTEM:
+	default:
+		Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen;
+		break;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set 802.1x authentication mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set8021xauthalg_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int alg;
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	if (wrq->u.data.flags == 0) {
+		//from iwpriv subcmd
+		alg = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	} else {
+		//from wpa_supplicant subcmd
+		if (copy_from_user(&alg, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+	}
+	PRINTM(INFO, "802.1x auth alg is %#x\n", alg);
+	priv->adapter->SecInfo.Auth1XAlg = alg;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set Encryption mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_setencryptionmode_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int mode;
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	if (wrq->u.data.flags == 0) {
+		//from iwpriv subcmd
+		mode = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	} else {
+		//from wpa_supplicant subcmd
+		if (copy_from_user(&mode, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+	}
+	PRINTM(INFO, "encryption mode is %#x\n", mode);
+	priv->adapter->SecInfo.EncryptionMode = mode;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+static void adjust_mtu(wlan_private * priv)
+{
+	int mtu_increment = 0;
+
+	if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
+		mtu_increment += sizeof(struct IEEE80211_Hdr);
+
+	if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP)
+		mtu_increment += max(sizeof(struct TxRadiotapHdr),
+				     sizeof(struct RxRadiotapHdr));
+	priv->wlan_dev.netdev->mtu = ETH_FRAME_LEN
+	    - sizeof(struct EthII_Hdr)
+	    + mtu_increment;
+}
+
+/**
+ *  @brief Set Link-Layer Layer mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_linkmode_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int mode;
+
+	ENTER();
+
+	mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
+
+	switch (mode) {
+	case WLAN_LINKMODE_802_3:
+		priv->adapter->linkmode = mode;
+		break;
+	case WLAN_LINKMODE_802_11:
+		priv->adapter->linkmode = mode;
+		break;
+	default:
+		PRINTM(FATAL, "usb8388-5: invalid link-layer mode (%#x)\n",
+		       mode);
+		return WLAN_STATUS_NOT_ACCEPTED;
+		break;
+	}
+	PRINTM(INFO, "usb8388-5: link-layer mode is %#x\n", mode);
+
+	adjust_mtu(priv);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set Radio Header mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_radiomode_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int mode;
+
+	ENTER();
+
+	mode = (int)((struct ifreq *)((u8 *) req + 4))->ifr_data;
+
+	switch (mode) {
+	case WLAN_RADIOMODE_NONE:
+		priv->adapter->radiomode = mode;
+		break;
+	case WLAN_RADIOMODE_RADIOTAP:
+		priv->adapter->radiomode = mode;
+		break;
+	default:
+		PRINTM(INFO, "usb8388-5: invalid radio header mode (%#x)\n",
+		       mode);
+		return WLAN_STATUS_NOT_ACCEPTED;
+		break;
+	}
+	PRINTM(INFO, "usb8388-5: radio-header mode is %#x\n", mode);
+
+	adjust_mtu(priv);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set Debug Header mode
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_debugmode_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	ENTER();
+	priv->adapter->debugmode = (int)((struct ifreq *)
+					 ((u8 *) req + 4))->ifr_data;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get Rx antenna
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_subcmd_getrxantenna_ioctl(wlan_private * priv,
+					  struct ifreq *req)
+{
+	int len;
+	char buf[8];
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	PRINTM(INFO, "WLAN_SUBCMD_GETRXANTENNA\n");
+	len = GetRxAntenna(priv, buf);
+
+	wrq->u.data.length = len;
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
+			PRINTM(INFO, "CopyToUser failed\n");
+			return -EFAULT;
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get Tx antenna
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_subcmd_gettxantenna_ioctl(wlan_private * priv,
+					  struct ifreq *req)
+{
+	int len;
+	char buf[8];
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	PRINTM(INFO, "WLAN_SUBCMD_GETTXANTENNA\n");
+	len = GetTxAntenna(priv, buf);
+
+	wrq->u.data.length = len;
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, &buf, len)) {
+			PRINTM(INFO, "CopyToUser failed\n");
+			return -EFAULT;
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Get the MAC TSF value from the firmware
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param wrq          A pointer to iwreq structure containing buffer
+ *                      space to store a TSF value retrieved from the firmware
+ *
+ *  @return             0 if successful; IOCTL error code otherwise
+ */
+static int wlan_get_tsf_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	u64 tsfVal;
+	int ret;
+
+	ENTER();
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_GET_TSF,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, &tsfVal);
+
+	PRINTM(INFO, "IOCTL: Get TSF = 0x%016llx\n", tsfVal);
+
+	if (ret != WLAN_STATUS_SUCCESS) {
+		PRINTM(INFO, "IOCTL: Get TSF; Command exec failed\n");
+		ret = -EFAULT;
+	} else {
+		if (copy_to_user(wrq->u.data.pointer,
+				 &tsfVal,
+				 min_t(size_t, wrq->u.data.length,
+				     sizeof(tsfVal))) != 0) {
+
+			PRINTM(INFO, "IOCTL: Get TSF; Copy to user failed\n");
+			ret = -EFAULT;
+		} else {
+			ret = 0;
+		}
+	}
+
+	LEAVE();
+
+	return ret;
+}
+
+/**
+ *  @brief Get/Set sleep period
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_sleep_period(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret;
+	int data;
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_SLEEP_PERIOD sleeppd;
+
+	ENTER();
+
+	if (wrq->u.data.length > 1)
+		return -ENOTSUPP;
+
+	memset(&sleeppd, 0, sizeof(sleeppd));
+	memset(&Adapter->sleep_period, 0, sizeof(struct sleep_period));
+
+	if (wrq->u.data.length == 0) {
+		sleeppd.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_GET);
+	} else {
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		/* sleep period is between 0 or 10 ... 60 */
+		if ((data <= 60 && data >= 10) || (data == 0)) {
+			sleeppd.Action = wlan_cpu_to_le16(HostCmd_ACT_GEN_SET);
+			sleeppd.Period = data;
+		} else
+			return -EINVAL;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SLEEP_PERIOD,
+				    0, HostCmd_OPTION_WAITFORRSP,
+				    0, (void *)&sleeppd);
+
+	data = (int)Adapter->sleep_period.period;
+	if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return -EFAULT;
+	}
+	wrq->u.data.length = 1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set adapt rate
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_adapt_rateset(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret;
+	wlan_adapter *Adapter = priv->adapter;
+	int data[2];
+
+	ENTER();
+	memset(data, 0, sizeof(data));
+	if (!wrq->u.data.length) {
+		PRINTM(INFO, "Get ADAPT RATE SET\n");
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_RATE_ADAPT_RATESET,
+					    HostCmd_ACT_GEN_GET,
+					    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+		data[0] = Adapter->EnableHwAuto;
+		data[1] = Adapter->RateBitmap;
+		if (copy_to_user(wrq->u.data.pointer, data, sizeof(int) * 2)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+#define GET_TWO_INT	2
+		wrq->u.data.length = GET_TWO_INT;
+	} else {
+		PRINTM(INFO, "Set ADAPT RATE SET\n");
+		if (wrq->u.data.length > 2)
+			return -EINVAL;
+		if (copy_from_user
+		    (data, wrq->u.data.pointer,
+		     sizeof(int) * wrq->u.data.length)) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		Adapter->EnableHwAuto = data[0];
+		Adapter->RateBitmap = data[1];
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_RATE_ADAPT_RATESET,
+					    HostCmd_ACT_GEN_SET,
+					    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set inactivity timeout
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_inactivity_timeout(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret;
+	int data = 0;
+	u16 timeout = 0;
+
+	ENTER();
+	if (wrq->u.data.length > 1)
+		return -ENOTSUPP;
+
+	if (wrq->u.data.length == 0) {
+		/* Get */
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_INACTIVITY_TIMEOUT,
+					    HostCmd_ACT_GET,
+					    HostCmd_OPTION_WAITFORRSP, 0,
+					    &timeout);
+		data = timeout;
+		if (copy_to_user(wrq->u.data.pointer, &data, sizeof(int))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+	} else {
+		/* Set */
+		if (copy_from_user(&data, wrq->u.data.pointer, sizeof(int))) {
+			PRINTM(INFO, "Copy from user failed\n");
+			return -EFAULT;
+		}
+
+		timeout = data;
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_INACTIVITY_TIMEOUT,
+					    HostCmd_ACT_SET,
+					    HostCmd_OPTION_WAITFORRSP, 0,
+					    &timeout);
+	}
+
+	wrq->u.data.length = 1;
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get LOG
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param wrq			A pointer to iwreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_do_getlog_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret;
+	char buf[GETLOG_BUFSIZE - 1];
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	PRINTM(INFO, " GET STATS\n");
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_GET_LOG,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	if (wrq->u.data.pointer) {
+		sprintf(buf, "\n  mcasttxframe %u failed %u retry %u "
+			"multiretry %u framedup %u "
+			"rtssuccess %u rtsfailure %u ackfailure %u\n"
+			"rxfrag %u mcastrxframe %u fcserror %u "
+			"txframe %u wepundecryptable %u ",
+			Adapter->LogMsg.mcasttxframe,
+			Adapter->LogMsg.failed,
+			Adapter->LogMsg.retry,
+			Adapter->LogMsg.multiretry,
+			Adapter->LogMsg.framedup,
+			Adapter->LogMsg.rtssuccess,
+			Adapter->LogMsg.rtsfailure,
+			Adapter->LogMsg.ackfailure,
+			Adapter->LogMsg.rxfrag,
+			Adapter->LogMsg.mcastrxframe,
+			Adapter->LogMsg.fcserror,
+			Adapter->LogMsg.txframe,
+			Adapter->LogMsg.wepundecryptable);
+		wrq->u.data.length = strlen(buf) + 1;
+		if (copy_to_user(wrq->u.data.pointer, buf, wrq->u.data.length)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief config sleep parameters
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_sleep_params_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	int ret;
+	wlan_adapter *Adapter = priv->adapter;
+	wlan_ioctl_sleep_params_config sp;
+
+	ENTER();
+
+	memset(&sp, 0, sizeof(sp));
+
+	if (copy_from_user(&sp, wrq->u.data.pointer,
+			   min_t(size_t, sizeof(sp), wrq->u.data.length))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return -EFAULT;
+	}
+
+	memcpy(&Adapter->sp, &sp.Error, sizeof(struct sleep_params));
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SLEEP_PARAMS,
+				    sp.Action, HostCmd_OPTION_WAITFORRSP,
+				    0, NULL);
+
+	if (!ret && !sp.Action && wrq->u.data.pointer) {
+		memcpy(&sp.Error, &Adapter->sp, sizeof(struct sleep_params));
+		if (copy_to_user(wrq->u.data.pointer, &sp, sizeof(sp))) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = sizeof(sp);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Read the CIS Table
+ *  @param priv                 A pointer to wlan_private structure
+ *  @param req			A pointer to ifreq structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_do_getcis_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	struct iwreq *wrq = (struct iwreq *)req;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (wrq->u.data.pointer) {
+		if (copy_to_user(wrq->u.data.pointer, Adapter->CisInfoBuf,
+				 Adapter->CisInfoLen)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			return -EFAULT;
+		}
+		wrq->u.data.length = Adapter->CisInfoLen;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set scan type
+ *
+ *  @param priv		A pointer to wlan_private structure
+ *  @param wrq	   	A pointer to user data
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+static int wlan_scan_type_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	u8 buf[12];
+	u8 *option[] = { "active", "passive", "get", };
+	int i, max_options = (sizeof(option) / sizeof(option[0]));
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (libertas_get_state_11d(priv) == ENABLE_11D) {
+		PRINTM(INFO, "11D: Cannot set scantype when 11D enabled\n");
+		return -EFAULT;
+	}
+
+	memset(buf, 0, sizeof(buf));
+
+	if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
+							 wrq->u.data.length))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return -EFAULT;
+	}
+
+	PRINTM(INFO, "Scan Type Option = %s\n", buf);
+
+	buf[sizeof(buf) - 1] = '\0';
+
+	for (i = 0; i < max_options; i++) {
+		if (!strcmp(buf, option[i]))
+			break;
+	}
+
+	switch (i) {
+	case 0:
+		Adapter->ScanType = HostCmd_SCAN_TYPE_ACTIVE;
+		break;
+	case 1:
+		Adapter->ScanType = HostCmd_SCAN_TYPE_PASSIVE;
+		break;
+	case 2:
+		wrq->u.data.length = strlen(option[Adapter->ScanType]) + 1;
+
+		if (copy_to_user(wrq->u.data.pointer,
+				 option[Adapter->ScanType],
+				 wrq->u.data.length)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+
+		break;
+	default:
+		PRINTM(INFO, "Invalid Scan Type Ioctl Option\n");
+		ret = -EINVAL;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set scan mode
+ *
+ *  @param priv		A pointer to wlan_private structure
+ *  @param wrq	   	A pointer to user data
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+static int wlan_scan_mode_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	u8 buf[12];
+	u8 *option[] = { "bss", "ibss", "any", "get" };
+	int i, max_options = (sizeof(option) / sizeof(option[0]));
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	memset(buf, 0, sizeof(buf));
+
+	if (copy_from_user(buf, wrq->u.data.pointer, min_t(size_t, sizeof(buf),
+							 wrq->u.data.length))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return -EFAULT;
+	}
+
+	PRINTM(INFO, "Scan Mode Option = %s\n", buf);
+
+	buf[sizeof(buf) - 1] = '\0';
+
+	for (i = 0; i < max_options; i++) {
+		if (!strcmp(buf, option[i]))
+			break;
+	}
+
+	switch (i) {
+
+	case 0:
+		Adapter->ScanMode = HostCmd_BSS_TYPE_BSS;
+		break;
+	case 1:
+		Adapter->ScanMode = HostCmd_BSS_TYPE_IBSS;
+		break;
+	case 2:
+		Adapter->ScanMode = HostCmd_BSS_TYPE_ANY;
+		break;
+	case 3:
+
+		wrq->u.data.length = strlen(option[Adapter->ScanMode - 1]) + 1;
+
+		PRINTM(INFO, "Get Scan Mode Option = %s\n",
+		       option[Adapter->ScanMode - 1]);
+
+		PRINTM(INFO, "Scan Mode Length %d\n", wrq->u.data.length);
+
+		if (copy_to_user(wrq->u.data.pointer,
+				 option[Adapter->ScanMode - 1],
+				 wrq->u.data.length)) {
+			PRINTM(INFO, "Copy to user failed\n");
+			ret = -EFAULT;
+		}
+		PRINTM(INFO, "GET Scan Type Option after copy = %s\n",
+		       (char *)wrq->u.data.pointer);
+
+		break;
+
+	default:
+		PRINTM(INFO, "Invalid Scan Mode Ioctl Option\n");
+		ret = -EINVAL;
+		break;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Get/Set Adhoc G Rate
+ *
+ *  @param priv		A pointer to wlan_private structure
+ *  @param wrq	   	A pointer to user data
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+static int wlan_do_set_grate_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int data, data1;
+	int *val;
+
+	ENTER();
+
+	data1 = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+	switch (data1) {
+	case 0:
+		Adapter->adhoc_grate_enabled = 0;
+		break;
+	case 1:
+		Adapter->adhoc_grate_enabled = 1;
+		break;
+	case 2:
+		break;
+	default:
+		return -EINVAL;
+	}
+	data = Adapter->adhoc_grate_enabled;
+	val = (int *)wrq->u.name;
+	*val = data;
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+static inline int hex2int(char c)
+{
+	if (c >= '0' && c <= '9')
+		return (c - '0');
+	if (c >= 'a' && c <= 'f')
+		return (c - 'a' + 10);
+	if (c >= 'A' && c <= 'F')
+		return (c - 'A' + 10);
+	return -1;
+}
+
+/* Convert a string representation of a MAC address ("xx:xx:xx:xx:xx:xx")
+   into binary format (6 bytes).
+
+   This function expects that each byte is represented with 2 characters
+   (e.g., 11:2:11:11:11:11 is invalid)
+
+ */
+static char *eth_str2addr(char *ethstr, u8 * addr)
+{
+	int i, val, val2;
+	char *pos = ethstr;
+
+	/* get rid of initial blanks */
+	while (*pos == ' ' || *pos == '\t')
+		++pos;
+
+	for (i = 0; i < 6; i++) {
+		val = hex2int(*pos++);
+		if (val < 0)
+			return NULL;
+		val2 = hex2int(*pos++);
+		if (val2 < 0)
+			return NULL;
+		addr[i] = (val * 16 + val2) & 0xff;
+
+		if (i < 5 && *pos++ != ':')
+			return NULL;
+	}
+	return pos;
+}
+
+/* this writes xx:xx:xx:xx:xx:xx into ethstr
+   (ethstr must have space for 18 chars) */
+static int eth_addr2str(u8 * addr, char *ethstr)
+{
+	int i;
+	char *pos = ethstr;
+
+	for (i = 0; i < 6; i++) {
+		sprintf(pos, "%02x", addr[i] & 0xff);
+		pos += 2;
+		if (i < 5)
+			*pos++ = ':';
+	}
+	return 17;
+}
+
+/**
+ *  @brief          Add an entry to the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_add_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	char ethaddrs_str[36];
+	char *pos;
+	u8 ethaddrs[2 * ETH_ALEN];
+#define ethaddr1 (ethaddrs+0)
+#define ethaddr2 (ethaddrs+6)
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr1)) == NULL) {
+		PRINTM(FATAL, "DFT_ADD: Invalid MAC address 1\n");
+		return -EINVAL;
+	}
+
+	if (eth_str2addr(pos, ethaddr2) == NULL) {
+		PRINTM(FATAL, "DFT_ADD: Invalid MAC address 2\n");
+		return -EINVAL;
+	}
+#ifdef DEBUG_LEVEL4
+	{
+		char ethaddr1_str[18], ethaddr2_str[18];
+		PRINTM(INFO, "DFT: adding %s\n", ethaddrs_str);
+		eth_addr2str(ethaddr1, ethaddr1_str);
+		eth_addr2str(ethaddr2, ethaddr2_str);
+		PRINTM(INFO, "DFT: adding (%s,%s)\n", ethaddr1_str,
+		       ethaddr2_str);
+	}
+#endif
+
+	LEAVE();
+	return (libertas_prepare_and_send_command(priv, HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_DFT_ACCESS_ADD,
+				      HostCmd_OPTION_WAITFORRSP, 0, ethaddrs));
+}
+
+/**
+ *  @brief          Delete an entry from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_del_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	char ethaddrs_str[18];
+	u8 ethaddr[ETH_ALEN];
+	char *pos;
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "Invalid MAC address\n");
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "DFT: deleting %s\n", ethaddrs_str);
+
+	LEAVE();
+	return (libertas_prepare_and_send_command(priv,
+				      HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_DFT_ACCESS_DEL,
+				      HostCmd_OPTION_WAITFORRSP, 0, ethaddr));
+}
+
+/**
+ *  @brief          Reset all entries from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_reset_ioctl(wlan_private * priv)
+{
+	ENTER();
+
+	PRINTM(MSG, "DFT: resetting\n");
+
+	LEAVE();
+	return (libertas_prepare_and_send_command(priv,
+				      HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_DFT_ACCESS_RESET,
+				      HostCmd_OPTION_WAITFORRSP, 0, NULL));
+}
+
+/**
+ *  @brief          List an entry from the DFT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_dft_list_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int pos;
+	char *addr1, *addr2;
+	struct iwreq *wrq = (struct iwreq *)req;
+	/* used to pass id and store the dft entry returned by the FW */
+	union {
+		int id;
+		char addr1addr2[2 * ETH_ALEN];
+	} param;
+	static char outstr[64];
+	char *pbuf = outstr;
+	int ret;
+
+	ENTER();
+
+	if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	param.id = simple_strtoul(outstr, NULL, 10);
+	pos = sprintf(pbuf, "%d: ", param.id);
+	pbuf += pos;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_DFT_ACCESS,
+				    HostCmd_ACT_DFT_ACCESS_LIST,
+				    HostCmd_OPTION_WAITFORRSP, 0,
+				    (char *)&param);
+
+	if (ret == WLAN_STATUS_SUCCESS) {
+		addr1 = param.addr1addr2;
+		addr2 = param.addr1addr2 + ETH_ALEN;
+
+		pos = sprintf(pbuf, "da ");
+		pbuf += pos;
+		pos = eth_addr2str(addr1, pbuf);
+		pbuf += pos;
+		pos = sprintf(pbuf, "    next hop ");
+		pbuf += pos;
+		pos = eth_addr2str(addr2, pbuf);
+		pbuf += pos;
+	} else {
+		sprintf(pbuf, "(null)");
+		pbuf += pos;
+	}
+	wrq->u.data.length = strlen(outstr);
+	if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
+			 wrq->u.data.length)) {
+		PRINTM(INFO, "DFT_LIST: Copy to user failed!\n");
+		return -EFAULT;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Add an entry to the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_add_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	char ethaddrs_str[18];
+	char *pos;
+	u8 ethaddr[ETH_ALEN];
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "BT_ADD: Invalid MAC address\n");
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "BT: adding %s\n", ethaddrs_str);
+	LEAVE();
+	return (libertas_prepare_and_send_command(priv, HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_BT_ACCESS_ADD,
+				      HostCmd_OPTION_WAITFORRSP, 0, ethaddr));
+}
+
+/**
+ *  @brief          Delete an entry from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_del_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct iwreq *wrq = (struct iwreq *)req;
+	char ethaddrs_str[18];
+	u8 ethaddr[ETH_ALEN];
+	char *pos;
+
+	ENTER();
+	if (copy_from_user(ethaddrs_str, wrq->u.data.pointer,
+			   sizeof(ethaddrs_str)))
+		return -EFAULT;
+
+	if ((pos = eth_str2addr(ethaddrs_str, ethaddr)) == NULL) {
+		PRINTM(FATAL, "Invalid MAC address\n");
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "BT: deleting %s\n", ethaddrs_str);
+
+	return (libertas_prepare_and_send_command(priv,
+				      HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_BT_ACCESS_DEL,
+				      HostCmd_OPTION_WAITFORRSP, 0, ethaddr));
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          Reset all entries from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_reset_ioctl(wlan_private * priv)
+{
+	ENTER();
+
+	PRINTM(MSG, "BT: resetting\n");
+
+	return (libertas_prepare_and_send_command(priv,
+				      HostCmd_CMD_DFT_ACCESS,
+				      HostCmd_ACT_BT_ACCESS_RESET,
+				      HostCmd_OPTION_WAITFORRSP, 0, NULL));
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief          List an entry from the BT table
+ *  @param priv     A pointer to wlan_private structure
+ *  @param req      A pointer to ifreq structure
+ *  @return         WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_bt_list_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	int pos;
+	char *addr1;
+	struct iwreq *wrq = (struct iwreq *)req;
+	/* used to pass id and store the bt entry returned by the FW */
+	union {
+		int id;
+		char addr1addr2[2 * ETH_ALEN];
+	} param;
+	static char outstr[64];
+	char *pbuf = outstr;
+	int ret;
+
+	ENTER();
+
+	if (copy_from_user(outstr, wrq->u.data.pointer, sizeof(outstr))) {
+		PRINTM(INFO, "Copy from user failed\n");
+		return WLAN_STATUS_FAILURE;
+	}
+	param.id = simple_strtoul(outstr, NULL, 10);
+	pos = sprintf(pbuf, "%d: ", param.id);
+	pbuf += pos;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_DFT_ACCESS,
+				    HostCmd_ACT_BT_ACCESS_LIST,
+				    HostCmd_OPTION_WAITFORRSP, 0,
+				    (char *)&param);
+
+	if (ret == WLAN_STATUS_SUCCESS) {
+		addr1 = param.addr1addr2;
+
+		pos = sprintf(pbuf, "ignoring traffic from ");
+		pbuf += pos;
+		pos = eth_addr2str(addr1, pbuf);
+		pbuf += pos;
+	} else {
+		sprintf(pbuf, "(null)");
+		pbuf += pos;
+	}
+
+	wrq->u.data.length = strlen(outstr);
+	if (copy_to_user(wrq->u.data.pointer, (char *)outstr,
+			 wrq->u.data.length)) {
+		PRINTM(INFO, "BT_LIST: Copy to user failed!\n");
+		return -EFAULT;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+#ifdef REASSOCIATION
+/** 
+ *  @brief Set Auto Reassociation On
+ *   
+ *  @param priv                 A pointer to wlan_private structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail 
+ */
+static int reassociation_on(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	Adapter->Reassoc_on = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set Auto Reassociation Off
+ *   
+ *  @param priv                 A pointer to wlan_private structure
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail 
+ */
+static int reassociation_off(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	del_timer(&Adapter->reassoc_timer);
+
+	Adapter->Reassoc_on = 0;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+#endif				/* REASSOCIATION */
+
+/**
+ *  @brief ioctl function - entry point
+ *
+ *  @param dev		A pointer to net_device structure
+ *  @param req	   	A pointer to ifreq structure
+ *  @param cmd 		command
+ *  @return 	   	WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
+{
+	int subcmd = 0;
+	int idata = 0;
+	int *pdata;
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct iwreq *wrq = (struct iwreq *)req;
+
+	ENTER();
+
+	PRINTM(INFO, "libertas_do_ioctl: ioctl cmd = 0x%x\n", cmd);
+	switch (cmd) {
+	case WLANEXTSCAN:
+		ret = libertas_extscan_ioctl(priv, req);
+		break;
+	case WLANHOSTCMD:
+		ret = wlan_hostcmd_ioctl(dev, req, cmd);
+		break;
+
+	case WLANCISDUMP:	/* Read CIS Table  */
+		ret = wlan_do_getcis_ioctl(priv, req);
+		break;
+
+	case WLANSCAN_TYPE:
+		PRINTM(INFO, "Scan Type Ioctl\n");
+		ret = wlan_scan_type_ioctl(priv, wrq);
+		break;
+
+	case WLANREGRDWR:	/* Register read write command */
+		ret = wlan_regrdwr_ioctl(priv, req);
+		break;
+
+	/* FIXME: this really should be handled by wireless extensions
+		  already, so it can probably be dropped here. */
+	case SIOCSIWENCODE:	/* set encoding token & mode for WPA */
+		ret = wlan_set_encode(dev, NULL, &(wrq->u.data),
+				      wrq->u.data.pointer);
+		break;
+
+	case WLAN_SETNONE_GETNONE:	/* set WPA mode on/off ioctl #20 */
+		switch (wrq->u.data.flags) {
+		case WLANDEAUTH:
+			PRINTM(INFO, "Deauth\n");
+			libertas_send_deauth(priv);
+			break;
+
+		case WLANADHOCSTOP:
+			PRINTM(INFO, "Adhoc stop\n");
+			ret = libertas_do_adhocstop_ioctl(priv);
+			break;
+
+		case WLANRADIOON:
+			wlan_radio_ioctl(priv, RADIO_ON);
+			break;
+
+		case WLANRADIOOFF:
+			wlan_radio_ioctl(priv, RADIO_OFF);
+			break;
+#ifdef REASSOCIATION
+		case WLANREASSOCIATIONAUTO:
+			reassociation_on(priv);
+			break;
+		case WLANREASSOCIATIONUSER:
+			reassociation_off(priv);
+			break;
+#endif				/* REASSOCIATION */
+		case WLANWLANIDLEON:
+			libertas_idle_on(priv);
+			break;
+		case WLANWLANIDLEOFF:
+			libertas_idle_off(priv);
+			break;
+		case WLAN_SUBCMD_DFT_RESET:	/* dft_reset */
+			wlan_dft_reset_ioctl(priv);
+			break;
+		case WLAN_SUBCMD_BT_RESET:	/* bt_reset */
+			wlan_bt_reset_ioctl(priv);
+			break;
+		}		/* End of switch */
+		break;
+
+	case WLAN_SETWORDCHAR_GETNONE:
+		switch (wrq->u.data.flags) {
+		}
+		break;
+
+	case WLAN_SETNONE_GETWORDCHAR:
+		switch (wrq->u.data.flags) {
+		case WLANVERSION:	/* Get driver version */
+			ret = wlan_version_ioctl(priv, req);
+			break;
+		}
+		break;
+	case WLANSETWPAIE:
+		ret = wlan_setwpaie_ioctl(priv, req);
+		break;
+	case WLAN_SETINT_GETINT:
+		/* The first 4 bytes of req->ifr_data is sub-ioctl number
+		 * after 4 bytes sits the payload.
+		 */
+		subcmd = (int)req->ifr_data;	//from iwpriv subcmd
+		switch (subcmd) {
+		case WLANNF:
+			ret = wlan_get_nf(priv, wrq);
+			break;
+		case WLANRSSI:
+			ret = wlan_get_rssi(priv, wrq);
+			break;
+		case WLANENABLE11D:
+			ret = libertas_cmd_enable_11d(priv, wrq);
+			break;
+		case WLANADHOCGRATE:
+			ret = wlan_do_set_grate_ioctl(priv, wrq);
+			break;
+		case WLAN_SUBCMD_SET_PRESCAN:
+			ret = wlan_subcmd_setprescan_ioctl(priv, wrq);
+			break;
+		}
+		break;
+
+	case WLAN_SETONEINT_GETONEINT:
+		switch (wrq->u.data.flags) {
+		case WLAN_BEACON_INTERVAL:
+			ret = wlan_beacon_interval(priv, wrq);
+			break;
+
+		case WLAN_LISTENINTRVL:
+			if (!wrq->u.data.length) {
+				int data;
+				PRINTM(INFO, "Get LocalListenInterval Value\n");
+#define GET_ONE_INT	1
+				data = Adapter->LocalListenInterval;
+				if (copy_to_user(wrq->u.data.pointer,
+						 &data, sizeof(int))) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				wrq->u.data.length = GET_ONE_INT;
+			} else {
+				int data;
+				if (copy_from_user
+				    (&data, wrq->u.data.pointer, sizeof(int))) {
+					PRINTM(INFO, "Copy from user failed\n");
+					return -EFAULT;
+				}
+
+				PRINTM(INFO, "Set LocalListenInterval = %d\n",
+				       data);
+#define MAX_U16_VAL	65535
+				if (data > MAX_U16_VAL) {
+					PRINTM(INFO, "Exceeds U16 value\n");
+					return -EINVAL;
+				}
+				Adapter->LocalListenInterval = data;
+			}
+			break;
+		case WLAN_TXCONTROL:
+			ret = wlan_txcontrol(priv, wrq);	//adds for txcontrol ioctl
+			break;
+
+		case WLAN_NULLPKTINTERVAL:
+			ret = wlan_null_pkt_interval(priv, wrq);
+			break;
+
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+		break;
+
+	case WLAN_SETONEINT_GETNONE:
+		/* The first 4 bytes of req->ifr_data is sub-ioctl number
+		 * after 4 bytes sits the payload.
+		 */
+		subcmd = wrq->u.data.flags;	//from wpa_supplicant subcmd
+
+		if (!subcmd)
+			subcmd = (int)req->ifr_data;	//from iwpriv subcmd
+
+		switch (subcmd) {
+		case WLAN_SUBCMD_SETRXANTENNA:	/* SETRXANTENNA */
+			idata = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			ret = SetRxAntenna(priv, idata);
+			break;
+		case WLAN_SUBCMD_SETTXANTENNA:	/* SETTXANTENNA */
+			idata = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			ret = SetTxAntenna(priv, idata);
+			break;
+		case WLAN_SET_ATIM_WINDOW:
+			Adapter->AtimWindow =
+			    *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			Adapter->AtimWindow = min_t(__u16, Adapter->AtimWindow, 50);
+			break;
+		case WLANSETBCNAVG:
+			Adapter->bcn_avg_factor =
+			    *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			if (Adapter->bcn_avg_factor == 0)
+				Adapter->bcn_avg_factor =
+				    DEFAULT_BCN_AVG_FACTOR;
+			if (Adapter->bcn_avg_factor > DEFAULT_BCN_AVG_FACTOR)
+				Adapter->bcn_avg_factor =
+				    DEFAULT_BCN_AVG_FACTOR;
+			break;
+		case WLANSETDATAAVG:
+			Adapter->data_avg_factor =
+			    *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			if (Adapter->data_avg_factor == 0)
+				Adapter->data_avg_factor =
+				    DEFAULT_DATA_AVG_FACTOR;
+			if (Adapter->data_avg_factor > DEFAULT_DATA_AVG_FACTOR)
+				Adapter->data_avg_factor =
+				    DEFAULT_DATA_AVG_FACTOR;
+			break;
+		case WLANSETREGION:
+			idata = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			ret = wlan_set_region(priv, (u16) idata);
+			break;
+
+		case WLAN_SET_LISTEN_INTERVAL:
+			idata = *((int *)(wrq->u.name + SUBCMD_OFFSET));
+			Adapter->ListenInterval = (u16) idata;
+			break;
+
+		case WLAN_SET_MULTIPLE_DTIM:
+			ret = wlan_set_multiple_dtim_ioctl(priv, req);
+			break;
+
+		case WLANSETAUTHALG:
+			ret = wlan_setauthalg_ioctl(priv, req);
+			break;
+
+		case WLANSET8021XAUTHALG:
+			ret = wlan_set8021xauthalg_ioctl(priv, req);
+			break;
+
+		case WLANSETENCRYPTIONMODE:
+			ret = wlan_setencryptionmode_ioctl(priv, req);
+			break;
+
+		case WLAN_SET_LINKMODE:
+			ret = wlan_set_linkmode_ioctl(priv, req);
+			break;
+
+		case WLAN_SET_RADIOMODE:
+			ret = wlan_set_radiomode_ioctl(priv, req);
+			break;
+
+		case WLAN_SET_DEBUGMODE:
+			ret = wlan_set_debugmode_ioctl(priv, req);
+			break;
+
+		default:
+			ret = -EOPNOTSUPP;
+			break;
+		}
+
+		break;
+
+	case WLAN_SETNONE_GETTWELVE_CHAR:	/* Get Antenna settings */
+		/*
+		 * We've not used IW_PRIV_TYPE_FIXED so sub-ioctl number is
+		 * in flags of iwreq structure, otherwise it will be in
+		 * mode member of iwreq structure.
+		 */
+		switch ((int)wrq->u.data.flags) {
+		case WLAN_SUBCMD_GETRXANTENNA:	/* Get Rx Antenna */
+			ret = wlan_subcmd_getrxantenna_ioctl(priv, req);
+			break;
+
+		case WLAN_SUBCMD_GETTXANTENNA:	/* Get Tx Antenna */
+			ret = wlan_subcmd_gettxantenna_ioctl(priv, req);
+			break;
+
+		case WLAN_GET_TSF:
+			ret = wlan_get_tsf_ioctl(priv, wrq);
+			break;
+		}
+		break;
+
+	case WLAN_SET64CHAR_GET64CHAR:
+		switch ((int)wrq->u.data.flags) {
+
+		case WLANSLEEPPARAMS:
+			ret = wlan_sleep_params_ioctl(priv, wrq);
+			break;
+
+		case WLANSCAN_MODE:
+			PRINTM(INFO, "Scan Mode Ioctl\n");
+			ret = wlan_scan_mode_ioctl(priv, wrq);
+			break;
+
+		case WLAN_GET_ADHOC_STATUS:
+			ret = wlan_get_adhoc_status_ioctl(priv, wrq);
+			break;
+		case WLAN_SUBCMD_DFT_ADD:
+			ret = wlan_dft_add_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_DFT_DEL:
+			ret = wlan_dft_del_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_DFT_LIST:
+			ret = wlan_dft_list_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_ADD:
+			ret = wlan_bt_add_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_DEL:
+			ret = wlan_bt_del_ioctl(priv, req);
+			break;
+		case WLAN_SUBCMD_BT_LIST:
+			ret = wlan_bt_list_ioctl(priv, req);
+			break;
+		}
+		break;
+
+	case WLAN_SETCONF_GETCONF:
+		PRINTM(INFO, "The WLAN_SETCONF_GETCONF=0x%x is %d\n",
+		       WLAN_SETCONF_GETCONF, *(u8 *) req->ifr_data);
+		switch (*(u8 *) req->ifr_data) {
+
+		}
+		break;
+
+	case WLAN_SETNONE_GETONEINT:
+		switch ((int)req->ifr_data) {
+		case WLANGETBCNAVG:
+			pdata = (int *)wrq->u.name;
+			*pdata = (int)Adapter->bcn_avg_factor;
+			break;
+
+		case WLANGETREGION:
+			pdata = (int *)wrq->u.name;
+			*pdata = (int)Adapter->RegionCode;
+			break;
+
+		case WLAN_GET_LISTEN_INTERVAL:
+			pdata = (int *)wrq->u.name;
+			*pdata = (int)Adapter->ListenInterval;
+			break;
+
+		case WLAN_GET_LINKMODE:
+			req->ifr_data = (char *)((u32) Adapter->linkmode);
+			break;
+
+		case WLAN_GET_RADIOMODE:
+			req->ifr_data = (char *)((u32) Adapter->radiomode);
+			break;
+
+		case WLAN_GET_DEBUGMODE:
+			req->ifr_data = (char *)((u32) Adapter->debugmode);
+			break;
+
+		case WLAN_GET_MULTIPLE_DTIM:
+			pdata = (int *)wrq->u.name;
+			*pdata = (int)Adapter->MultipleDtim;
+			break;
+		case WLAN_GET_TX_RATE:
+			ret = wlan_get_txrate_ioctl(priv, req);
+			break;
+		default:
+			ret = -EOPNOTSUPP;
+
+		}
+
+		break;
+
+	case WLAN_SETTENCHAR_GETNONE:
+		switch ((int)wrq->u.data.flags) {
+
+		}
+		break;
+
+	case WLAN_SETNONE_GETTENCHAR:
+		switch ((int)wrq->u.data.flags) {
+		}
+		break;
+
+	case WLANGETLOG:
+		ret = wlan_do_getlog_ioctl(priv, wrq);
+		break;
+
+	case WLAN_SET_GET_SIXTEEN_INT:
+		switch ((int)wrq->u.data.flags) {
+		case WLAN_TPCCFG:
+			{
+				int data[5];
+				struct HostCmd_DS_802_11_TPC_CFG cfg;
+				memset(&cfg, 0, sizeof(cfg));
+				if ((wrq->u.data.length > 1)
+				    && (wrq->u.data.length != 5))
+					return WLAN_STATUS_FAILURE;
+
+				if (wrq->u.data.length == 0) {
+					cfg.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_GET);
+				} else {
+					if (copy_from_user
+					    (data, wrq->u.data.pointer,
+					     sizeof(int) * 5)) {
+						PRINTM(INFO,
+						       "Copy from user failed\n");
+						return -EFAULT;
+					}
+
+					cfg.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_SET);
+					cfg.Enable = data[0];
+					cfg.UseSNR = data[1];
+					cfg.P0 = data[2];
+					cfg.P1 = data[3];
+					cfg.P2 = data[4];
+				}
+
+				ret =
+				    libertas_prepare_and_send_command(priv,
+							  HostCmd_CMD_802_11_TPC_CFG,
+							  0,
+							  HostCmd_OPTION_WAITFORRSP,
+							  0, (void *)&cfg);
+
+				data[0] = cfg.Enable;
+				data[1] = cfg.UseSNR;
+				data[2] = cfg.P0;
+				data[3] = cfg.P1;
+				data[4] = cfg.P2;
+				if (copy_to_user
+				    (wrq->u.data.pointer, data,
+				     sizeof(int) * 5)) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				wrq->u.data.length = 5;
+			}
+			break;
+
+		case WLAN_POWERCFG:
+			{
+				int data[4];
+				struct HostCmd_DS_802_11_PWR_CFG cfg;
+				memset(&cfg, 0, sizeof(cfg));
+				if ((wrq->u.data.length > 1)
+				    && (wrq->u.data.length != 4))
+					return WLAN_STATUS_FAILURE;
+				if (wrq->u.data.length == 0) {
+					cfg.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_GET);
+				} else {
+					if (copy_from_user
+					    (data, wrq->u.data.pointer,
+					     sizeof(int) * 4)) {
+						PRINTM(INFO,
+						       "Copy from user failed\n");
+						return -EFAULT;
+					}
+
+					cfg.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_SET);
+					cfg.Enable = data[0];
+					cfg.PA_P0 = data[1];
+					cfg.PA_P1 = data[2];
+					cfg.PA_P2 = data[3];
+				}
+				ret =
+				    libertas_prepare_and_send_command(priv,
+							  HostCmd_CMD_802_11_PWR_CFG,
+							  0,
+							  HostCmd_OPTION_WAITFORRSP,
+							  0, (void *)&cfg);
+				data[0] = cfg.Enable;
+				data[1] = cfg.PA_P0;
+				data[2] = cfg.PA_P1;
+				data[3] = cfg.PA_P2;
+				if (copy_to_user
+				    (wrq->u.data.pointer, data,
+				     sizeof(int) * 4)) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				wrq->u.data.length = 4;
+			}
+			break;
+		case WLAN_AUTO_FREQ_SET:
+			{
+				int data[3];
+				struct HostCmd_DS_802_11_AFC afc;
+				memset(&afc, 0, sizeof(afc));
+				if (wrq->u.data.length != 3)
+					return WLAN_STATUS_FAILURE;
+				if (copy_from_user
+				    (data, wrq->u.data.pointer,
+				     sizeof(int) * 3)) {
+					PRINTM(INFO, "Copy from user failed\n");
+					return -EFAULT;
+				}
+				afc.afc_auto = data[0];
+
+				if (afc.afc_auto != 0) {
+					afc.afc_thre = data[1];
+					afc.afc_period = data[2];
+				} else {
+					afc.afc_toff = data[1];
+					afc.afc_foff = data[2];
+				}
+				ret =
+				    libertas_prepare_and_send_command(priv,
+							  HostCmd_CMD_802_11_SET_AFC,
+							  0,
+							  HostCmd_OPTION_WAITFORRSP,
+							  0, (void *)&afc);
+			}
+			break;
+		case WLAN_AUTO_FREQ_GET:
+			{
+				int data[3];
+				struct HostCmd_DS_802_11_AFC afc;
+				memset(&afc, 0, sizeof(afc));
+				ret =
+				    libertas_prepare_and_send_command(priv,
+							  HostCmd_CMD_802_11_GET_AFC,
+							  0,
+							  HostCmd_OPTION_WAITFORRSP,
+							  0, (void *)&afc);
+				data[0] = afc.afc_auto;
+				data[1] = afc.afc_toff;
+				data[2] = afc.afc_foff;
+				if (copy_to_user
+				    (wrq->u.data.pointer, data,
+				     sizeof(int) * 3)) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				wrq->u.data.length = 3;
+			}
+			break;
+		case WLAN_SCANPROBES:
+			{
+				int data;
+				if (wrq->u.data.length > 0) {
+					if (copy_from_user
+					    (&data, wrq->u.data.pointer,
+					     sizeof(int))) {
+						PRINTM(INFO,
+						       "Copy from user failed\n");
+						return -EFAULT;
+					}
+
+					Adapter->ScanProbes = data;
+				} else {
+					data = Adapter->ScanProbes;
+					if (copy_to_user
+					    (wrq->u.data.pointer, &data,
+					     sizeof(int))) {
+						PRINTM(INFO,
+						       "Copy to user failed\n");
+						return -EFAULT;
+					}
+				}
+				wrq->u.data.length = 1;
+			}
+			break;
+		case WLAN_LED_GPIO_CTRL:
+			{
+				int i;
+				int data[16];
+
+				struct HostCmd_DS_802_11_LED_CTRL ctrl;
+				struct MrvlIEtypes_LedGpio *gpio =
+				    (struct MrvlIEtypes_LedGpio *) ctrl.data;
+
+				memset(&ctrl, 0, sizeof(ctrl));
+				if (wrq->u.data.length > MAX_LEDS * 2)
+					return -ENOTSUPP;
+				if ((wrq->u.data.length % 2) != 0)
+					return -ENOTSUPP;
+				if (wrq->u.data.length == 0) {
+					ctrl.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_GET);
+				} else {
+					if (copy_from_user
+					    (data, wrq->u.data.pointer,
+					     sizeof(int) *
+					     wrq->u.data.length)) {
+						PRINTM(INFO,
+						       "Copy from user failed\n");
+						return -EFAULT;
+					}
+
+					ctrl.Action =
+					    wlan_cpu_to_le16
+					    (HostCmd_ACT_GEN_SET);
+					ctrl.NumLed = wlan_cpu_to_le16(0);
+					gpio->Header.Type =
+					    wlan_cpu_to_le16(TLV_TYPE_LED_GPIO);
+					gpio->Header.Len = wrq->u.data.length;
+					for (i = 0; i < wrq->u.data.length;
+					     i += 2) {
+						gpio->LedPin[i / 2].Led =
+						    data[i];
+						gpio->LedPin[i / 2].Pin =
+						    data[i + 1];
+					}
+				}
+				ret =
+				    libertas_prepare_and_send_command(priv,
+							  HostCmd_CMD_802_11_LED_GPIO_CTRL,
+							  0,
+							  HostCmd_OPTION_WAITFORRSP,
+							  0, (void *)&ctrl);
+				for (i = 0; i < gpio->Header.Len; i += 2) {
+					data[i] = gpio->LedPin[i / 2].Led;
+					data[i + 1] = gpio->LedPin[i / 2].Pin;
+				}
+				if (copy_to_user(wrq->u.data.pointer, data,
+						 sizeof(int) *
+						 gpio->Header.Len)) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				wrq->u.data.length = gpio->Header.Len;
+			}
+			break;
+		case WLAN_SLEEP_PERIOD:
+			ret = wlan_sleep_period(priv, wrq);
+			break;
+		case WLAN_ADAPT_RATESET:
+			ret = wlan_adapt_rateset(priv, wrq);
+			break;
+		case WLAN_INACTIVITY_TIMEOUT:
+			ret = wlan_inactivity_timeout(priv, wrq);
+			break;
+		case WLANSNR:
+			ret = wlan_get_snr(priv, wrq);
+			break;
+		case WLAN_GET_RXINFO:
+			ret = wlan_get_rxinfo(priv, wrq);
+		}
+		break;
+
+	case WLAN_SET_GET_2K:
+		switch ((int)wrq->u.data.flags) {
+		case WLAN_SET_USER_SCAN:
+			ret = libertas_set_user_scan_ioctl(priv, wrq);
+			break;
+		case WLAN_GET_SCAN_TABLE:
+			ret = libertas_get_scan_table_ioctl(priv, wrq);
+			break;
+
+		default:
+			ret = -EOPNOTSUPP;
+		}
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	LEAVE();
+	return ret;
+}
+
+
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_join.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_join.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_join.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_join.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,1602 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
+
+/** @file wlan_join.c
+  *
+  *  @brief Functions implementing wlan infrastructure and adhoc join routines
+  *
+  *  IOCTL handlers as well as command preperation and response routines
+  *   for sending adhoc start, adhoc join, and association commands
+  *   to the firmware.
+  *
+  *  @sa wlan_join.h
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    01/11/06: Initial revision. Match new scan code, relocate related functions
+    01/19/06: Fix failure to save adhoc ssid as current after adhoc start
+    03/16/06: Add a semaphore to protect reassociation thread
+
+************************************************************/
+
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "wlan_decl.h"
+#include "wlan_join.h"
+#include "wlan_dev.h"
+
+static int wlan_associate(wlan_private * priv, struct bss_descriptor * pBSSDesc);
+
+/**
+ *  @brief This function finds out the common rates between rate1 and rate2.
+ *
+ * It will fill common rates in rate1 as output if found.
+ *
+ * NOTE: Setting the MSB of the basic rates need to be taken
+ *   care, either before or after calling this function
+ *
+ *  @param Adapter     A pointer to wlan_adapter structure
+ *  @param rate1       the buffer which keeps input and output
+ *  @param rate1_size  the size of rate1 buffer
+ *  @param rate2       the buffer which keeps rate2
+ *  @param rate2_size  the size of rate2 buffer.
+ *
+ *  @return            WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int get_common_rates(wlan_adapter * Adapter, u8 * rate1,
+			    int rate1_size, u8 * rate2, int rate2_size)
+{
+	u8 *ptr = rate1;
+	int ret = WLAN_STATUS_SUCCESS;
+	u8 tmp[30];
+	int i;
+
+	memset(&tmp, 0, sizeof(tmp));
+	memcpy(&tmp, rate1, min_t(size_t, rate1_size, sizeof(tmp)));
+	memset(rate1, 0, rate1_size);
+
+	/* Mask the top bit of the original values */
+	for (i = 0; tmp[i] && i < sizeof(tmp); i++)
+		tmp[i] &= 0x7F;
+
+	for (i = 0; rate2[i] && i < rate2_size; i++) {
+		/* Check for Card Rate in tmp, excluding the top bit */
+		if (strchr(tmp, rate2[i] & 0x7F)) {
+			/* Values match, so copy the Card Rate to rate1 */
+			*rate1++ = rate2[i];
+		}
+	}
+
+	HEXDUMP("rate1 (AP) Rates:", tmp, sizeof(tmp));
+	HEXDUMP("rate2 (Card) Rates:", rate2, rate2_size);
+	HEXDUMP("Common Rates:", ptr, rate1_size);
+	PRINTM(INFO, "Tx DataRate is set to 0x%X\n", Adapter->DataRate);
+
+	if (!Adapter->Is_DataRate_Auto) {
+		while (*ptr) {
+			if ((*ptr & 0x7f) == Adapter->DataRate) {
+				ret = WLAN_STATUS_SUCCESS;
+				goto done;
+			}
+			ptr++;
+		}
+		PRINTM(MSG, "Previously set fixed data rate %#x isn't "
+		       "compatible with the network.\n", Adapter->DataRate);
+
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	return ret;
+}
+
+/**
+ *  @brief Send Deauth Request
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @return          WLAN_STATUS_SUCCESS--success, otherwise fail
+ */
+int libertas_send_deauth(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (Adapter->InfrastructureMode == Wlan802_11Infrastructure &&
+	    Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+
+		ret = libertas_send_deauthentication(priv);
+
+	} else {
+		LEAVE();
+		return -ENOTSUPP;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Stop Adhoc Network
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_do_adhocstop_ioctl(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (Adapter->InfrastructureMode == Wlan802_11IBSS &&
+	    Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+
+		ret = libertas_stop_adhoc_network(priv);
+
+	} else {
+		LEAVE();
+		return -ENOTSUPP;
+	}
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Set essid
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *  @return             WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int libertas_set_essid(struct net_device *dev, struct iw_request_info *info,
+		   struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	struct WLAN_802_11_SSID reqSSID;
+	int i;
+
+	ENTER();
+
+#ifdef REASSOCIATION
+	// cancel re-association timer if there's one
+    del_timer(&Adapter->reassoc_timer);
+
+	if (down_interruptible(&Adapter->ReassocSem)) {
+		PRINTM(FATAL, "Acquire semaphore error, libertas_set_essid\n");
+		return -EBUSY;
+	}
+#endif				/* REASSOCIATION */
+
+	/* Check the size of the string */
+	if (dwrq->length > IW_ESSID_MAX_SIZE + 1) {
+		ret = -E2BIG;
+		goto setessid_ret;
+	}
+
+	memset(&reqSSID, 0, sizeof(struct WLAN_802_11_SSID));
+
+	/*
+	 * Check if we asked for `any' or 'particular'
+	 */
+	if (!dwrq->flags) {
+		if (libertas_find_best_network_SSID(priv, &reqSSID)) {
+			PRINTM(INFO, "Could not find best network\n");
+			ret = WLAN_STATUS_SUCCESS;
+			goto setessid_ret;
+		}
+	} else {
+		/* Set the SSID */
+		memcpy(reqSSID.Ssid, extra, dwrq->length);
+		reqSSID.SsidLength = dwrq->length - 1;
+	}
+
+	PRINTM(INFO, "Requested new SSID = %s\n",
+	       (reqSSID.SsidLength > 0) ? (char *)reqSSID.Ssid : "NULL");
+
+	if (!reqSSID.SsidLength || reqSSID.Ssid[0] < 0x20) {
+		PRINTM(INFO, "Invalid SSID - aborting set_essid\n");
+		ret = -EINVAL;
+		goto setessid_ret;
+	}
+
+	/* If the requested SSID is not a NULL string, join */
+
+	if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+		/* infrastructure mode */
+		PRINTM(INFO, "SSID requested = %s\n", reqSSID.Ssid);
+
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			PRINTM(INFO, "Already Connected ..\n");
+			ret = libertas_send_deauthentication(priv);
+
+			if (ret) {
+				goto setessid_ret;
+			}
+		}
+		if (Adapter->Prescan)
+			libertas_send_specific_SSID_scan(priv, &reqSSID, 1);
+		i = libertas_find_SSID_in_list(Adapter, &reqSSID, NULL,
+				   Wlan802_11Infrastructure);
+		if (i >= 0) {
+			PRINTM(INFO,
+			       "SSID found in scan list ... associating...\n");
+
+			ret = wlan_associate(priv, &Adapter->ScanTable[i]);
+
+			if (ret) {
+				goto setessid_ret;
+			}
+		} else {	/* i >= 0 */
+			ret = i;	/* return -ENETUNREACH, passed from libertas_find_SSID_in_list */
+			goto setessid_ret;
+		}
+	} else {
+		/* ad hoc mode */
+		/* If the requested SSID matches current SSID return */
+		if (!libertas_SSID_cmp(&Adapter->CurBssParams.ssid, &reqSSID)) {
+			ret = WLAN_STATUS_SUCCESS;
+			goto setessid_ret;
+		}
+
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			/*
+			 * Exit Adhoc mode
+			 */
+			PRINTM(INFO, "Sending Adhoc Stop\n");
+			ret = libertas_stop_adhoc_network(priv);
+
+			if (ret) {
+				goto setessid_ret;
+			}
+
+		}
+
+		/* Scan for the network, do not save previous results.  Stale
+		 *   scan data will cause us to join a non-existant adhoc network
+		 */
+		libertas_send_specific_SSID_scan(priv, &reqSSID, 0);
+
+		/* Search for the requested SSID in the scan table */
+		i = libertas_find_SSID_in_list(Adapter, &reqSSID, NULL, Wlan802_11IBSS);
+
+		if (i >= 0) {
+			PRINTM(INFO, "SSID found at %d in List, so join\n", i);
+			libertas_join_adhoc_network(priv, &Adapter->ScanTable[i]);
+		} else {
+			/* else send START command */
+			PRINTM(INFO, "SSID not found in list, "
+			       "so creating adhoc with ssid = %s\n",
+			       reqSSID.Ssid);
+
+			libertas_start_adhoc_network(priv, &reqSSID);
+		}		/* end of else (START command) */
+	}			/* end of else (Ad hoc mode) */
+
+	/*
+	 * The MediaConnectStatus change can be removed later when
+	 *   the ret code is being properly returned.
+	 */
+	/* Check to see if we successfully connected */
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		ret = WLAN_STATUS_SUCCESS;
+	} else {
+		ret = -ENETDOWN;
+	}
+
+      setessid_ret:
+#ifdef REASSOCIATION
+	up(&Adapter->ReassocSem);
+#endif
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Connect to the AP or Ad-hoc Network with specific bssid
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param awrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_set_wap(struct net_device *dev, struct iw_request_info *info,
+		 struct sockaddr *awrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	const u8 bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 };
+	u8 reqBSSID[ETH_ALEN];
+	int i;
+
+	ENTER();
+
+//Application should call scan before call this function.    
+
+	if (awrq->sa_family != ARPHRD_ETHER)
+		return -EINVAL;
+
+	PRINTM(INFO, "ASSOC: WAP: sa_data: %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       (u8) awrq->sa_data[0], (u8) awrq->sa_data[1],
+	       (u8) awrq->sa_data[2], (u8) awrq->sa_data[3],
+	       (u8) awrq->sa_data[4], (u8) awrq->sa_data[5]);
+
+#ifdef REASSOCIATION
+	// cancel re-association timer if there's one
+	del_timer(&Adapter->reassoc_timer);
+#endif				/* REASSOCIATION */
+
+	if (!memcmp(bcast, awrq->sa_data, ETH_ALEN)) {
+		i = libertas_find_best_SSID_in_list(Adapter);
+	} else {
+		memcpy(reqBSSID, awrq->sa_data, ETH_ALEN);
+
+		PRINTM(INFO,
+		       "ASSOC: WAP: Bssid = %02x:%02x:%02x:%02x:%02x:%02x\n",
+		       reqBSSID[0], reqBSSID[1], reqBSSID[2], reqBSSID[3],
+		       reqBSSID[4], reqBSSID[5]);
+
+		/* Search for index position in list for requested MAC */
+		i = libertas_find_BSSID_in_list(Adapter, reqBSSID,
+				    Adapter->InfrastructureMode);
+	}
+
+	if (i < 0) {
+		PRINTM(INFO,
+		       "ASSOC: WAP: MAC address not found in BSSID List\n");
+		return -ENETUNREACH;
+	}
+
+	if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			ret = libertas_send_deauthentication(priv);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		}
+		ret = wlan_associate(priv, &Adapter->ScanTable[i]);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	} else {
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			/* Exit Adhoc mode */
+			ret = libertas_stop_adhoc_network(priv);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		}
+
+		libertas_join_adhoc_network(priv, &Adapter->ScanTable[i]);
+	}
+
+	/* Check to see if we successfully connected */
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		ret = WLAN_STATUS_SUCCESS;
+	} else {
+		ret = -ENETDOWN;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Associated to a specific BSS discovered in a scan
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @param pBSSDesc  Pointer to the BSS descriptor to associate with.
+ *
+ *  @return          WLAN_STATUS_SUCCESS-success, otherwise fail
+ */
+static int wlan_associate(wlan_private * priv, struct bss_descriptor * pBSSDesc)
+{
+	int ret;
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_AUTHENTICATE,
+				    0, HostCmd_OPTION_WAITFORRSP,
+				    0, pBSSDesc->MacAddress);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_ASSOCIATE,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, pBSSDesc);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Start an Adhoc Network
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param AdhocSSID    The ssid of the Adhoc Network
+ *  @return             WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+int libertas_start_adhoc_network(wlan_private * priv, struct WLAN_802_11_SSID *AdhocSSID)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	Adapter->AdhocCreate = 1;
+
+	if (!Adapter->capInfo.ShortPreamble) {
+		PRINTM(INFO, "AdhocStart: Long Preamble\n");
+		Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE;
+	} else {
+		PRINTM(INFO, "AdhocStart: Short Preamble\n");
+		Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE;
+	}
+
+	libertas_set_radio_control(priv);
+
+	PRINTM(INFO, "Adhoc Channel = %d\n", Adapter->AdhocChannel);
+	PRINTM(INFO, "CurBssParams.channel = %d\n",
+	       Adapter->CurBssParams.channel);
+	PRINTM(INFO, "CurBssParams.band = %d\n", Adapter->CurBssParams.band);
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_AD_HOC_START,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, AdhocSSID);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Join an adhoc network found in a previous scan
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param pBSSDesc     Pointer to a BSS descriptor found in a previous scan
+ *                      to attempt to join
+ *
+ *  @return             WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor * pBSSDesc)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	PRINTM(INFO, "libertas_join_adhoc_network: CurBss.ssid =%s\n",
+	       Adapter->CurBssParams.ssid.Ssid);
+	PRINTM(INFO, "libertas_join_adhoc_network: CurBss.ssid_len =%u\n",
+	       Adapter->CurBssParams.ssid.SsidLength);
+	PRINTM(INFO, "libertas_join_adhoc_network: ssid =%s\n", pBSSDesc->Ssid.Ssid);
+	PRINTM(INFO, "libertas_join_adhoc_network: ssid len =%u\n",
+	       pBSSDesc->Ssid.SsidLength);
+
+	/* check if the requested SSID is already joined */
+	if (Adapter->CurBssParams.ssid.SsidLength
+	    && !libertas_SSID_cmp(&pBSSDesc->Ssid, &Adapter->CurBssParams.ssid)
+	    && (Adapter->CurBssParams.BSSDescriptor.InfrastructureMode ==
+		Wlan802_11IBSS)) {
+
+		PRINTM(INFO,
+		       "ADHOC_J_CMD: New ad-hoc SSID is the same as current, "
+		       "not attempting to re-join");
+
+		return WLAN_STATUS_FAILURE;
+	}
+
+	/*Use ShortPreamble only when both creator and card supports
+	   short preamble */
+	if (!pBSSDesc->Cap.ShortPreamble || !Adapter->capInfo.ShortPreamble) {
+		PRINTM(INFO, "AdhocJoin: Long Preamble\n");
+		Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE;
+	} else {
+		PRINTM(INFO, "AdhocJoin: Short Preamble\n");
+		Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE;
+	}
+
+	libertas_set_radio_control(priv);
+
+	PRINTM(INFO, "CurBssParams.channel = %d\n",
+	       Adapter->CurBssParams.channel);
+	PRINTM(INFO, "CurBssParams.band = %c\n", Adapter->CurBssParams.band);
+
+	Adapter->AdhocCreate = 0;
+
+	// store the SSID info temporarily
+	memset(&Adapter->AttemptedSSIDBeforeScan, 0,
+	       sizeof(struct WLAN_802_11_SSID));
+	memcpy(&Adapter->AttemptedSSIDBeforeScan, &pBSSDesc->Ssid,
+	       sizeof(struct WLAN_802_11_SSID));
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_AD_HOC_JOIN,
+				    0, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_SSID, pBSSDesc);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Stop the Adhoc Network
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @return          WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+int libertas_stop_adhoc_network(wlan_private * priv)
+{
+	return libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_AD_HOC_STOP,
+				     0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+}
+
+/**
+ *  @brief Send Deauthentication Request
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @return          WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+int libertas_send_deauthentication(wlan_private * priv)
+{
+	return libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_DEAUTHENTICATE,
+				     0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+}
+
+/**
+ *  @brief Set Idle Off
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_idle_off(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	const u8 zeroMac[] = { 0, 0, 0, 0, 0, 0 };
+	int i;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
+		if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+			if (memcmp(Adapter->PreviousBSSID, zeroMac,
+				   sizeof(zeroMac)) != 0) {
+
+				PRINTM(INFO, "Previous SSID = %s\n",
+				       Adapter->PreviousSSID.Ssid);
+				PRINTM(INFO, "Previous BSSID = "
+				       "%02x:%02x:%02x:%02x:%02x:%02x:\n",
+				       Adapter->PreviousBSSID[0],
+				       Adapter->PreviousBSSID[1],
+				       Adapter->PreviousBSSID[2],
+				       Adapter->PreviousBSSID[3],
+				       Adapter->PreviousBSSID[4],
+				       Adapter->PreviousBSSID[5]);
+
+				i = libertas_find_SSID_in_list(Adapter,
+						   &Adapter->PreviousSSID,
+						   Adapter->PreviousBSSID,
+						   Adapter->InfrastructureMode);
+
+				if (i < 0) {
+					libertas_send_specific_BSSID_scan(priv,
+							      Adapter->
+							      PreviousBSSID,
+							      1);
+					i = libertas_find_SSID_in_list(Adapter,
+							   &Adapter->
+							   PreviousSSID,
+							   Adapter->
+							   PreviousBSSID,
+							   Adapter->
+							   InfrastructureMode);
+				}
+
+				if (i < 0) {
+					/* If the BSSID could not be found, try just the SSID */
+					i = libertas_find_SSID_in_list(Adapter,
+							   &Adapter->
+							   PreviousSSID, NULL,
+							   Adapter->
+							   InfrastructureMode);
+				}
+
+				if (i < 0) {
+					libertas_send_specific_SSID_scan(priv,
+							     &Adapter->
+							     PreviousSSID,
+							     1);
+					i = libertas_find_SSID_in_list(Adapter,
+							   &Adapter->
+							   PreviousSSID, NULL,
+							   Adapter->
+							   InfrastructureMode);
+				}
+
+				if (i >= 0) {
+					ret =
+					    wlan_associate(priv,
+							   &Adapter->
+							   ScanTable[i]);
+				}
+			}
+		} else if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
+			ret = libertas_prepare_and_send_command(priv,
+						    HostCmd_CMD_802_11_AD_HOC_START,
+						    0,
+						    HostCmd_OPTION_WAITFORRSP,
+						    0, &Adapter->PreviousSSID);
+		}
+	}
+	/* else it is connected */
+
+	PRINTM(INFO, "\nwlanidle is off");
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Set Idle On
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_idle_on(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+			PRINTM(INFO, "Previous SSID = %s\n",
+			       Adapter->PreviousSSID.Ssid);
+			memmove(&Adapter->PreviousSSID,
+				&Adapter->CurBssParams.ssid,
+				sizeof(struct WLAN_802_11_SSID));
+			libertas_send_deauth(priv);
+
+		} else if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
+			ret = libertas_stop_adhoc_network(priv);
+		}
+
+	}
+#ifdef REASSOCIATION
+		del_timer(&Adapter->reassoc_timer);
+#endif				/* REASSOCIATION */
+
+	PRINTM(INFO, "\nwlanidle is on");
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of authenticate.
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @param cmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf Void cast of pointer to a BSSID to authenticate with
+ *
+ *  @return         WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_authenticate(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *cmd,
+				 void *pdata_buf)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_AUTHENTICATE *pAuthenticate =
+	    &cmd->params.auth;
+	u8 *bssid = (u8 *) pdata_buf;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AUTHENTICATE);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_AUTHENTICATE)
+			     + S_DS_GEN);
+
+	pAuthenticate->AuthType = Adapter->SecInfo.AuthenticationMode;
+	memcpy(pAuthenticate->MacAddr, bssid, ETH_ALEN);
+
+	PRINTM(INFO, "AUTH_CMD: Bssid is : %x:%x:%x:%x:%x:%x\n",
+	       bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of deauthenticat.
+ *
+ *  @param priv     A pointer to wlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @return         WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_deauthenticate(wlan_private * priv,
+				   struct HostCmd_DS_COMMAND *cmd)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_DEAUTHENTICATE *dauth = &cmd->params.deauth;
+
+	ENTER();
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_DEAUTHENTICATE) +
+			     S_DS_GEN);
+
+	/* set AP MAC address */
+	memmove(dauth->MacAddr, Adapter->CurBssParams.bssid,
+		ETH_ALEN);
+
+	/* Reason code 3 = Station is leaving */
+#define REASON_CODE_STA_LEAVING 3
+	dauth->ReasonCode = wlan_cpu_to_le16(REASON_CODE_STA_LEAVING);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of association.
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @param cmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf Void cast of BSSDescriptor_t from the scan table to assoc
+ *  @return          WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_associate(wlan_private * priv,
+			      struct HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_ASSOCIATE *pAsso = &cmd->params.associate;
+	int ret = WLAN_STATUS_SUCCESS;
+	struct bss_descriptor *pBSSDesc;
+	u8 *card_rates;
+	u8 *pos;
+	int card_rates_size;
+	u16 TmpCap;
+	struct MrvlIEtypes_SsIdParamSet *ssid;
+	struct MrvlIEtypes_PhyParamSet *phy;
+	struct MrvlIEtypes_SsParamSet *ss;
+	struct MrvlIEtypes_RatesParamSet *rates;
+	struct MrvlIEtypes_RsnParamSet *rsn;
+
+	ENTER();
+
+	pBSSDesc = (struct bss_descriptor *) pdata_buf;
+	pos = (u8 *) pAsso;
+
+	if (!Adapter) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE);
+
+	/* Save so we know which BSS Desc to use in the response handler */
+	Adapter->pAttemptedBSSDesc = pBSSDesc;
+
+	memcpy(pAsso->PeerStaAddr,
+	       pBSSDesc->MacAddress, sizeof(pAsso->PeerStaAddr));
+	pos += sizeof(pAsso->PeerStaAddr);
+
+	/* set preamble to firmware */
+	if (Adapter->capInfo.ShortPreamble && pBSSDesc->Cap.ShortPreamble) {
+		Adapter->Preamble = HostCmd_TYPE_SHORT_PREAMBLE;
+	} else {
+		Adapter->Preamble = HostCmd_TYPE_LONG_PREAMBLE;
+	}
+
+	libertas_set_radio_control(priv);
+
+	/* set the listen interval */
+	pAsso->ListenInterval = Adapter->ListenInterval;
+
+	pos += sizeof(pAsso->CapInfo);
+	pos += sizeof(pAsso->ListenInterval);
+	pos += sizeof(pAsso->BcnPeriod);
+	pos += sizeof(pAsso->DtimPeriod);
+
+	ssid = (struct MrvlIEtypes_SsIdParamSet *) pos;
+	ssid->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+	ssid->Header.Len = pBSSDesc->Ssid.SsidLength;
+	memcpy(ssid->SsId, pBSSDesc->Ssid.Ssid, ssid->Header.Len);
+	pos += sizeof(ssid->Header) + ssid->Header.Len;
+	ssid->Header.Len = wlan_cpu_to_le16(ssid->Header.Len);
+
+	phy = (struct MrvlIEtypes_PhyParamSet *) pos;
+	phy->Header.Type = wlan_cpu_to_le16(TLV_TYPE_PHY_DS);
+	phy->Header.Len = sizeof(phy->fh_ds.DsParamSet);
+	memcpy(&phy->fh_ds.DsParamSet,
+	       &pBSSDesc->PhyParamSet.DsParamSet.CurrentChan,
+	       sizeof(phy->fh_ds.DsParamSet));
+	pos += sizeof(phy->Header) + phy->Header.Len;
+	phy->Header.Len = wlan_cpu_to_le16(phy->Header.Len);
+
+	ss = (struct MrvlIEtypes_SsParamSet *) pos;
+	ss->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CF);
+	ss->Header.Len = sizeof(ss->cf_ibss.CfParamSet);
+	pos += sizeof(ss->Header) + ss->Header.Len;
+	ss->Header.Len = wlan_cpu_to_le16(ss->Header.Len);
+
+	rates = (struct MrvlIEtypes_RatesParamSet *) pos;
+	rates->Header.Type = wlan_cpu_to_le16(TLV_TYPE_RATES);
+
+	memcpy(&rates->Rates, &pBSSDesc->libertas_supported_rates, WLAN_SUPPORTED_RATES);
+
+	card_rates = libertas_supported_rates;
+	card_rates_size = sizeof(libertas_supported_rates);
+
+	if (get_common_rates(Adapter, rates->Rates, WLAN_SUPPORTED_RATES,
+			     card_rates, card_rates_size)) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	rates->Header.Len = min_t(size_t, strlen(rates->Rates), WLAN_SUPPORTED_RATES);
+	Adapter->CurBssParams.NumOfRates = rates->Header.Len;
+
+	pos += sizeof(rates->Header) + rates->Header.Len;
+	rates->Header.Len = wlan_cpu_to_le16(rates->Header.Len);
+
+	if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled) {
+		rsn = (struct MrvlIEtypes_RsnParamSet *) pos;
+		rsn->Header.Type = (u16) Adapter->Wpa_ie[0];	/* WPA_IE or WPA2_IE */
+		rsn->Header.Type = wlan_cpu_to_le16(rsn->Header.Type);
+		rsn->Header.Len = (u16) Adapter->Wpa_ie[1];
+		memcpy(rsn->RsnIE, &Adapter->Wpa_ie[2], rsn->Header.Len);
+		HEXDUMP("ASSOC_CMD: RSN IE", (u8 *) rsn,
+			sizeof(rsn->Header) + rsn->Header.Len);
+		pos += sizeof(rsn->Header) + rsn->Header.Len;
+		rsn->Header.Len = wlan_cpu_to_le16(rsn->Header.Len);
+	}
+
+	/* update CurBssParams */
+	Adapter->CurBssParams.channel =
+	    (pBSSDesc->PhyParamSet.DsParamSet.CurrentChan);
+
+	/* Copy the infra. association rates into Current BSS state structure */
+	memcpy(&Adapter->CurBssParams.DataRates, &rates->Rates,
+	       min_t(size_t, sizeof(Adapter->CurBssParams.DataRates), rates->Header.Len));
+
+	PRINTM(INFO, "ASSOC_CMD: rates->Header.Len = %d\n", rates->Header.Len);
+
+	/* set IBSS field */
+	if (pBSSDesc->InfrastructureMode == Wlan802_11Infrastructure) {
+#define CAPINFO_ESS_MODE 1
+		pAsso->CapInfo.Ess = CAPINFO_ESS_MODE;
+	}
+
+	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->Size = wlan_cpu_to_le16((u16) (pos - (u8 *) pAsso) + S_DS_GEN);
+
+	/* set the Capability info at last */
+	memcpy(&TmpCap, &pBSSDesc->Cap, sizeof(pAsso->CapInfo));
+	TmpCap &= CAPINFO_MASK;
+	PRINTM(INFO, "ASSOC_CMD: TmpCap=%4X CAPINFO_MASK=%4X\n",
+	       TmpCap, CAPINFO_MASK);
+	TmpCap = wlan_cpu_to_le16(TmpCap);
+	memcpy(&pAsso->CapInfo, &TmpCap, sizeof(pAsso->CapInfo));
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_start.
+ *
+ *  @param priv     A pointer to wlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @param pssid    A pointer to WLAN_802_11_SSID structure
+ *  @return         WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *cmd, void *pssid)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_AD_HOC_START *adhs = &cmd->params.ads;
+	int ret = WLAN_STATUS_SUCCESS;
+	int cmdAppendSize = 0;
+	int i;
+	u16 TmpCap;
+	struct bss_descriptor *pBSSDesc;
+
+	ENTER();
+
+	if (!Adapter) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START);
+
+	pBSSDesc = &Adapter->CurBssParams.BSSDescriptor;
+	Adapter->pAttemptedBSSDesc = pBSSDesc;
+
+	/*
+	 * Fill in the parameters for 2 data structures:
+	 *   1. HostCmd_DS_802_11_AD_HOC_START Command
+	 *   2. Adapter->ScanTable[i]
+	 *
+	 * Driver will fill up SSID, BSSType,IBSS param, Physical Param,
+	 *   probe delay, and Cap info.
+	 *
+	 * Firmware will fill up beacon period, DTIM, Basic rates
+	 *   and operational rates.
+	 */
+
+	memset(adhs->SSID, 0, MRVDRV_MAX_SSID_LENGTH);
+
+	memcpy(adhs->SSID, ((struct WLAN_802_11_SSID *)pssid)->Ssid,
+	       ((struct WLAN_802_11_SSID *)pssid)->SsidLength);
+
+	PRINTM(INFO, "ADHOC_S_CMD: SSID = %s\n", adhs->SSID);
+
+	memset(pBSSDesc->Ssid.Ssid, 0, MRVDRV_MAX_SSID_LENGTH);
+	memcpy(pBSSDesc->Ssid.Ssid,
+	       ((struct WLAN_802_11_SSID *)pssid)->Ssid,
+	       ((struct WLAN_802_11_SSID *)pssid)->SsidLength);
+
+	pBSSDesc->Ssid.SsidLength =
+	    ((struct WLAN_802_11_SSID *)pssid)->SsidLength;
+
+	/* set the BSS type */
+	adhs->BSSType = HostCmd_BSS_TYPE_IBSS;
+	pBSSDesc->InfrastructureMode = Wlan802_11IBSS;
+	adhs->BeaconPeriod = Adapter->BeaconPeriod;
+
+	/* set Physical param set */
+#define DS_PARA_IE_ID   3
+#define DS_PARA_IE_LEN  1
+
+	adhs->PhyParamSet.DsParamSet.ElementId = DS_PARA_IE_ID;
+	adhs->PhyParamSet.DsParamSet.Len = DS_PARA_IE_LEN;
+
+	ASSERT(Adapter->AdhocChannel);
+
+	PRINTM(INFO, "ADHOC_S_CMD: Creating ADHOC on Channel %d\n",
+	       Adapter->AdhocChannel);
+
+	Adapter->CurBssParams.channel = Adapter->AdhocChannel;
+
+	pBSSDesc->Channel = Adapter->AdhocChannel;
+	adhs->PhyParamSet.DsParamSet.CurrentChan = Adapter->AdhocChannel;
+
+	memcpy(&pBSSDesc->PhyParamSet,
+	       &adhs->PhyParamSet, sizeof(union IEEEtypes_PhyParamSet));
+
+	pBSSDesc->NetworkTypeInUse = Wlan802_11DS;
+
+	/* set IBSS param set */
+#define IBSS_PARA_IE_ID   6
+#define IBSS_PARA_IE_LEN  2
+
+	adhs->SsParamSet.IbssParamSet.ElementId = IBSS_PARA_IE_ID;
+	adhs->SsParamSet.IbssParamSet.Len = IBSS_PARA_IE_LEN;
+	adhs->SsParamSet.IbssParamSet.AtimWindow = Adapter->AtimWindow;
+	memcpy(&pBSSDesc->SsParamSet,
+	       &adhs->SsParamSet, sizeof(union IEEEtypes_SsParamSet));
+
+	/* set Capability info */
+	adhs->Cap.Ess = 0;
+	adhs->Cap.Ibss = 1;
+	pBSSDesc->Cap.Ibss = 1;
+
+	/* ProbeDelay */
+	adhs->ProbeDelay = wlan_cpu_to_le16(HostCmd_SCAN_PROBE_DELAY_TIME);
+
+	/* set up privacy in Adapter->ScanTable[i] */
+	if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) {
+
+#define AD_HOC_CAP_PRIVACY_ON 1
+		PRINTM(INFO, "ADHOC_S_CMD: WEPStatus set, Privacy to WEP\n");
+		pBSSDesc->Privacy = Wlan802_11PrivFilter8021xWEP;
+		adhs->Cap.Privacy = AD_HOC_CAP_PRIVACY_ON;
+	} else {
+		PRINTM(INFO, "ADHOC_S_CMD: WEPStatus NOT set, Setting "
+		       "Privacy to ACCEPT ALL\n");
+		pBSSDesc->Privacy = Wlan802_11PrivFilterAcceptAll;
+	}
+
+	memset(adhs->DataRate, 0, sizeof(adhs->DataRate));
+
+	if (Adapter->adhoc_grate_enabled) {
+		memcpy(adhs->DataRate, libertas_adhoc_rates_g,
+		       min(sizeof(adhs->DataRate), sizeof(libertas_adhoc_rates_g)));
+	} else {
+		memcpy(adhs->DataRate, libertas_adhoc_rates_b,
+		       min(sizeof(adhs->DataRate), sizeof(libertas_adhoc_rates_b)));
+	}
+
+	/* Find the last non zero */
+	for (i = 0; i < sizeof(adhs->DataRate) && adhs->DataRate[i]; i++) ;
+
+	Adapter->CurBssParams.NumOfRates = i;
+
+	/* Copy the ad-hoc creating rates into Current BSS state structure */
+	memcpy(&Adapter->CurBssParams.DataRates,
+	       &adhs->DataRate, Adapter->CurBssParams.NumOfRates);
+
+	PRINTM(INFO, "ADHOC_S_CMD: Rates=%02x %02x %02x %02x \n",
+	       adhs->DataRate[0], adhs->DataRate[1],
+	       adhs->DataRate[2], adhs->DataRate[3]);
+
+	PRINTM(INFO, "ADHOC_S_CMD: AD HOC Start command is ready\n");
+
+	if (libertas_create_dnld_countryinfo_11d(priv)) {
+		PRINTM(INFO, "ADHOC_S_CMD: dnld_countryinfo_11d failed\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_AD_HOC_START)
+			     + S_DS_GEN + cmdAppendSize);
+
+	memcpy(&TmpCap, &adhs->Cap, sizeof(u16));
+	TmpCap = wlan_cpu_to_le16(TmpCap);
+	memcpy(&adhs->Cap, &TmpCap, sizeof(u16));
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_stop.
+ *
+ *  @param priv     A pointer to wlan_private structure
+ *  @param cmd      A pointer to HostCmd_DS_COMMAND structure
+ *  @return         WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *cmd)
+{
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP);
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_AD_HOC_STOP)
+			     + S_DS_GEN);
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function prepares command of ad_hoc_join.
+ *
+ *  @param priv      A pointer to wlan_private structure
+ *  @param cmd       A pointer to HostCmd_DS_COMMAND structure
+ *  @param pdata_buf Void cast of BSSDescriptor_t from the scan table to join
+ *
+ *  @return          WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_AD_HOC_JOIN *pAdHocJoin = &cmd->params.adj;
+	struct bss_descriptor *pBSSDesc = (struct bss_descriptor *) pdata_buf;
+	int cmdAppendSize = 0;
+	int ret = WLAN_STATUS_SUCCESS;
+	u8 *card_rates;
+	int card_rates_size;
+	u16 TmpCap;
+	int i;
+
+	ENTER();
+
+	Adapter->pAttemptedBSSDesc = pBSSDesc;
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN);
+
+	pAdHocJoin->BssDescriptor.BSSType = HostCmd_BSS_TYPE_IBSS;
+
+	pAdHocJoin->BssDescriptor.BeaconPeriod = pBSSDesc->BeaconPeriod;
+
+	memcpy(&pAdHocJoin->BssDescriptor.BSSID,
+	       &pBSSDesc->MacAddress, ETH_ALEN);
+
+	memcpy(&pAdHocJoin->BssDescriptor.SSID,
+	       &pBSSDesc->Ssid.Ssid, pBSSDesc->Ssid.SsidLength);
+
+	memcpy(&pAdHocJoin->BssDescriptor.PhyParamSet,
+	       &pBSSDesc->PhyParamSet, sizeof(union IEEEtypes_PhyParamSet));
+
+	memcpy(&pAdHocJoin->BssDescriptor.SsParamSet,
+	       &pBSSDesc->SsParamSet, sizeof(union IEEEtypes_SsParamSet));
+
+	memcpy(&TmpCap, &pBSSDesc->Cap, sizeof(struct IEEEtypes_CapInfo));
+
+	TmpCap &= CAPINFO_MASK;
+
+	PRINTM(INFO, "ADHOC_J_CMD: TmpCap=%4X CAPINFO_MASK=%4X\n",
+	       TmpCap, CAPINFO_MASK);
+	memcpy(&pAdHocJoin->BssDescriptor.Cap, &TmpCap,
+	       sizeof(struct IEEEtypes_CapInfo));
+
+	/* information on BSSID descriptor passed to FW */
+	PRINTM(INFO,
+	       "ADHOC_J_CMD: BSSID = %2x-%2x-%2x-%2x-%2x-%2x, SSID = %s\n",
+	       pAdHocJoin->BssDescriptor.BSSID[0],
+	       pAdHocJoin->BssDescriptor.BSSID[1],
+	       pAdHocJoin->BssDescriptor.BSSID[2],
+	       pAdHocJoin->BssDescriptor.BSSID[3],
+	       pAdHocJoin->BssDescriptor.BSSID[4],
+	       pAdHocJoin->BssDescriptor.BSSID[5],
+	       pAdHocJoin->BssDescriptor.SSID);
+
+	PRINTM(INFO, "ADHOC_J_CMD: Data Rate = %x\n",
+	       (u32) pAdHocJoin->BssDescriptor.DataRates);
+
+	/* FailTimeOut */
+	pAdHocJoin->FailTimeOut = wlan_cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT);
+
+	/* ProbeDelay */
+	pAdHocJoin->ProbeDelay =
+	    wlan_cpu_to_le16(HostCmd_SCAN_PROBE_DELAY_TIME);
+
+	/* Copy Data Rates from the Rates recorded in scan response */
+	memset(pAdHocJoin->BssDescriptor.DataRates, 0,
+	       sizeof(pAdHocJoin->BssDescriptor.DataRates));
+	memcpy(pAdHocJoin->BssDescriptor.DataRates, pBSSDesc->DataRates,
+	       min(sizeof(pAdHocJoin->BssDescriptor.DataRates),
+		   sizeof(pBSSDesc->DataRates)));
+
+	card_rates = libertas_supported_rates;
+	card_rates_size = sizeof(libertas_supported_rates);
+
+	Adapter->CurBssParams.channel = pBSSDesc->Channel;
+
+	if (get_common_rates(Adapter, pAdHocJoin->BssDescriptor.DataRates,
+			     sizeof(pAdHocJoin->BssDescriptor.DataRates),
+			     card_rates, card_rates_size)) {
+		PRINTM(INFO, "ADHOC_J_CMD: get_common_rates returns error.\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	/* Find the last non zero */
+	for (i = 0; i < sizeof(pAdHocJoin->BssDescriptor.DataRates)
+	     && pAdHocJoin->BssDescriptor.DataRates[i]; i++) ;
+
+	Adapter->CurBssParams.NumOfRates = i;
+
+	/*
+	 * Copy the adhoc joining rates to Current BSS State structure
+	 */
+	memcpy(Adapter->CurBssParams.DataRates,
+	       pAdHocJoin->BssDescriptor.DataRates,
+	       Adapter->CurBssParams.NumOfRates);
+
+	pAdHocJoin->BssDescriptor.SsParamSet.IbssParamSet.AtimWindow =
+	    wlan_cpu_to_le16(pBSSDesc->ATIMWindow);
+
+	if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) {
+		pAdHocJoin->BssDescriptor.Cap.Privacy = AD_HOC_CAP_PRIVACY_ON;
+	}
+
+	if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) {
+		/* wake up first */
+		enum WLAN_802_11_POWER_MODE LocalPSMode;
+
+		LocalPSMode = Wlan802_11PowerModeCAM;
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_PS_MODE,
+					    HostCmd_ACT_GEN_SET,
+					    0, 0, &LocalPSMode);
+
+		if (ret) {
+			ret = WLAN_STATUS_FAILURE;
+			goto done;
+		}
+	}
+
+	if (libertas_parse_dnld_countryinfo_11d(priv)) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	cmd->Size =
+	    wlan_cpu_to_le16(sizeof(struct HostCmd_DS_802_11_AD_HOC_JOIN)
+			     + S_DS_GEN + cmdAppendSize);
+
+	memcpy(&TmpCap, &pAdHocJoin->BssDescriptor.Cap,
+	       sizeof(struct IEEEtypes_CapInfo));
+	TmpCap = wlan_cpu_to_le16(TmpCap);
+
+	memcpy(&pAdHocJoin->BssDescriptor.Cap,
+	       &TmpCap, sizeof(struct IEEEtypes_CapInfo));
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of authenticate
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_authenticate(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp)
+{
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of associate
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_associate(wlan_private * priv,
+			      struct HostCmd_DS_COMMAND *resp)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	union iwreq_data wrqu;
+	struct IEEEtypes_AssocRsp *pAssocRsp;
+	struct bss_descriptor *pBSSDesc;
+
+	ENTER();
+
+	pAssocRsp = (struct IEEEtypes_AssocRsp *) & resp->params;
+
+	if (pAssocRsp->StatusCode) {
+
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			libertas_mac_event_disconnected(priv);
+		}
+
+		PRINTM(INFO,
+		       "ASSOC_RESP: Association Failed, status code = %d\n",
+		       pAssocRsp->StatusCode);
+
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	HEXDUMP("ASSOC_RESP:", (void *)&resp->params,
+		wlan_le16_to_cpu(resp->Size) - S_DS_GEN);
+
+	/* Send a Media Connected event, according to the Spec */
+	Adapter->MediaConnectStatus = WlanMediaStateConnected;
+	Adapter->LinkSpeed = MRVDRV_LINK_SPEED_11mbps;
+
+	/* Set the attempted BSSID Index to current */
+	pBSSDesc = Adapter->pAttemptedBSSDesc;
+
+	PRINTM(INFO, "ASSOC_RESP: %s\n", pBSSDesc->Ssid.Ssid);
+
+	/* Set the new SSID to current SSID */
+	memcpy(&Adapter->CurBssParams.ssid,
+	       &pBSSDesc->Ssid, sizeof(struct WLAN_802_11_SSID));
+
+	/* Set the new BSSID (AP's MAC address) to current BSSID */
+	memcpy(Adapter->CurBssParams.bssid,
+	       pBSSDesc->MacAddress, ETH_ALEN);
+
+	/* Make a copy of current BSSID descriptor */
+	memcpy(&Adapter->CurBssParams.BSSDescriptor,
+	       pBSSDesc, sizeof(struct bss_descriptor));
+
+	PRINTM(INFO, "ASSOC_RESP: CurrentPacketFilter is %x\n",
+	       Adapter->CurrentPacketFilter);
+
+	Adapter->MediaConnectStatus = WlanMediaStateConnected;
+
+	if (Adapter->SecInfo.WPAEnabled || Adapter->SecInfo.WPA2Enabled)
+		Adapter->IsGTK_SET = 0;
+
+	Adapter->SNR[TYPE_RXPD][TYPE_AVG] = 0;
+	Adapter->NF[TYPE_RXPD][TYPE_AVG] = 0;
+
+	memset(Adapter->rawSNR, 0x00, sizeof(Adapter->rawSNR));
+	memset(Adapter->rawNF, 0x00, sizeof(Adapter->rawNF));
+	Adapter->nextSNRNF = 0;
+	Adapter->numSNRNF = 0;
+
+	{
+		netif_carrier_on(priv->wlan_dev.netdev);
+		netif_wake_queue(priv->wlan_dev.netdev);
+	}
+
+	PRINTM(INFO, "ASSOC_RESP: Associated \n");
+
+	memcpy(wrqu.ap_addr.sa_data, Adapter->CurBssParams.bssid, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of disassociate
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_disassociate(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp)
+{
+	ENTER();
+
+	libertas_mac_event_disconnected(priv);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of ad_hoc_start
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
+				 struct HostCmd_DS_COMMAND *resp)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	u16 Command = wlan_le16_to_cpu(resp->Command);
+	u16 Result = wlan_le16_to_cpu(resp->Result);
+	struct HostCmd_DS_802_11_AD_HOC_RESULT *pAdHocResult;
+	union iwreq_data wrqu;
+	struct bss_descriptor *pBSSDesc;
+
+	ENTER();
+
+	pAdHocResult = &resp->params.result;
+
+	PRINTM(INFO, "ADHOC_S_RESP: Size = %d\n", wlan_le16_to_cpu(resp->Size));
+	PRINTM(INFO, "ADHOC_S_RESP: Command = %x\n", Command);
+	PRINTM(INFO, "ADHOC_S_RESP: Result = %x\n", Result);
+
+	pBSSDesc = Adapter->pAttemptedBSSDesc;
+
+	/*
+	 * Join result code 0 --> SUCCESS
+	 */
+	if (Result) {
+		PRINTM(INFO, "ADHOC_RESP Failed\n");
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			libertas_mac_event_disconnected(priv);
+		}
+
+		memset(&Adapter->CurBssParams.BSSDescriptor,
+		       0x00, sizeof(Adapter->CurBssParams.BSSDescriptor));
+
+		Adapter->AdHocFailed = 1;
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	/*
+	 * Now the join cmd should be successful
+	 * If BSSID has changed use SSID to compare instead of BSSID
+	 */
+	PRINTM(INFO, "ADHOC_J_RESP  %s\n", pBSSDesc->Ssid.Ssid);
+
+	/* Send a Media Connected event, according to the Spec */
+	Adapter->MediaConnectStatus = WlanMediaStateConnected;
+	Adapter->LinkSpeed = MRVDRV_LINK_SPEED_11mbps;
+
+	if (Command == HostCmd_RET_802_11_AD_HOC_START) {
+		Adapter->AdHocCreated = 1;
+
+		/* Update the created network descriptor with the new BSSID */
+		memcpy(pBSSDesc->MacAddress,
+		       pAdHocResult->BSSID, ETH_ALEN);
+	} else {
+
+		/* Make a copy of current BSSID descriptor, only needed for join since
+		 *   the current descriptor is already being used for adhoc start
+		 */
+		memmove(&Adapter->CurBssParams.BSSDescriptor,
+			pBSSDesc, sizeof(struct bss_descriptor));
+	}
+
+	/* Set the BSSID from the joined/started descriptor */
+	memcpy(&Adapter->CurBssParams.bssid,
+	       pBSSDesc->MacAddress, ETH_ALEN);
+
+	/* Set the new SSID to current SSID */
+	memcpy(&Adapter->CurBssParams.ssid,
+	       &pBSSDesc->Ssid, sizeof(struct WLAN_802_11_SSID));
+
+	netif_carrier_on(priv->wlan_dev.netdev);
+	netif_wake_queue(priv->wlan_dev.netdev);
+
+	memset(&wrqu, 0, sizeof(wrqu));
+	memcpy(wrqu.ap_addr.sa_data, Adapter->CurBssParams.bssid, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+
+	PRINTM(INFO, "ADHOC_RESP: - Joined/Started Ad Hoc\n");
+	PRINTM(INFO, "ADHOC_RESP: Channel = %d\n", Adapter->AdhocChannel);
+	PRINTM(INFO, "ADHOC_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
+	       pAdHocResult->BSSID[0], pAdHocResult->BSSID[1],
+	       pAdHocResult->BSSID[2], pAdHocResult->BSSID[3],
+	       pAdHocResult->BSSID[4], pAdHocResult->BSSID[5]);
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief This function handles the command response of ad_hoc_stop
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp)
+{
+	ENTER();
+
+	libertas_mac_event_disconnected(priv);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+#ifdef REASSOCIATION
+/**
+ *  @brief This function handles re-association. it is triggered
+ *  by re-assoc timer.
+ *
+ *  @param data    A pointer to wlan_thread structure
+ *  @return        WLAN_STATUS_SUCCESS
+ */
+int libertas_reassociation_thread(void *data)
+{
+	struct wlan_thread *thread = data;
+	wlan_private *priv = thread->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	wait_queue_t wait;
+	int i;
+
+	ENTER();
+
+	wlan_activate_thread(thread);
+	init_waitqueue_entry(&wait, current);
+
+	for (;;) {
+		add_wait_queue(&thread->waitQ, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		PRINTM(INFO, "Reassoc: Thread sleeping...\n");
+
+		schedule();
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		try_to_freeze();
+
+		if (Adapter->SurpriseRemoved) {
+			break;
+		}
+
+		if (kthread_should_stop()) {
+			break;
+		}
+
+		PRINTM(INFO, "Reassoc: Thread waking up...\n");
+
+		if (Adapter->InfrastructureMode != Wlan802_11Infrastructure) {
+			PRINTM(MSG,
+			       "Reassoc: non infra mode is not supported\n");
+			continue;
+		}
+
+		/* The semaphore is used to avoid reassociation thread and 
+		   libertas_set_scan/libertas_set_essid interrupting each other.
+		   Reassociation should be disabled completely by application if 
+		   libertas_set_user_scan_ioctl/libertas_set_wap is used.
+		 */
+		if (down_interruptible(&Adapter->ReassocSem)) {
+			PRINTM(FATAL,
+			       "Acquire semaphore error, reassociation thread\n");
+			goto settimer;
+		}
+
+		if (Adapter->MediaConnectStatus != WlanMediaStateDisconnected) {
+			up(&Adapter->ReassocSem);
+			PRINTM(MSG,
+			       "Reassoc: Adapter->MediaConnectStatus is wrong\n");
+			continue;
+		}
+
+		PRINTM(INFO, "Reassoc: Required ESSID: %s\n",
+		       Adapter->PreviousSSID.Ssid);
+
+		PRINTM(INFO, "Reassoc: Performing Active Scan @ %lu\n",
+		       jiffies);
+
+		libertas_send_specific_SSID_scan(priv, &Adapter->PreviousSSID, 1);
+
+		/* Try to find the specific BSSID we were associated to first */
+		i = libertas_find_SSID_in_list(Adapter,
+				   &Adapter->PreviousSSID,
+				   Adapter->PreviousBSSID,
+				   Adapter->InfrastructureMode);
+
+		if (i < 0) {
+			/* If the BSSID could not be found, try just the SSID */
+			i = libertas_find_SSID_in_list(Adapter,
+					   &Adapter->PreviousSSID,
+					   NULL, Adapter->InfrastructureMode);
+		}
+
+		if (i >= 0) {
+			wlan_associate(priv, &Adapter->ScanTable[i]);
+		}
+
+		up(&Adapter->ReassocSem);
+
+	      settimer:
+		if (Adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
+			PRINTM(INFO, "Reassoc: No AP found or assoc failed."
+			       "Restarting re-assoc Timer @ %lu\n", jiffies);
+
+            mod_timer(&Adapter->reassoc_timer, jiffies + 10*HZ); /* 10s */
+		}
+	}
+
+	wlan_deactivate_thread(thread);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+#endif				/* REASSOCIATION */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_join.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_join.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_join.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_join.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,99 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
+
+/** @file wlan_join.h
+  *
+  * @brief Interface for the wlan infrastructure and adhoc join routines
+  *
+  * Driver interface functions and type declarations for the join module
+  *   implemented in wlan_join.c.  Process all start/join requests for
+  *   both adhoc and infrastructure networks
+  *
+  * @sa wlan_join.c
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    01/11/06: Initial revision. Match new scan code, relocate related functions
+
+************************************************************/
+
+#ifndef _WLAN_JOIN_H
+#define _WLAN_JOIN_H
+
+#include "wlan_defs.h"
+
+//! Size of buffer allocated to store the association response from firmware
+#define MRVDRV_ASSOC_RSP_BUF_SIZE 500
+
+struct HostCmd_DS_COMMAND;
+extern int libertas_cmd_80211_authenticate(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *cmd,
+					void *pdata_buf);
+extern int libertas_cmd_80211_ad_hoc_join(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *cmd,
+				       void *pdata_buf);
+extern int libertas_cmd_80211_ad_hoc_stop(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *cmd);
+extern int libertas_cmd_80211_ad_hoc_start(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *cmd,
+					void *pssid);
+extern int libertas_cmd_80211_deauthenticate(wlan_private * priv,
+					  struct HostCmd_DS_COMMAND *cmd);
+extern int libertas_cmd_80211_associate(wlan_private * priv,
+				     struct HostCmd_DS_COMMAND *cmd,
+				     void *pdata_buf);
+
+extern int libertas_ret_80211_authenticate(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp);
+extern int libertas_ret_80211_ad_hoc_start(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp);
+extern int libertas_ret_80211_ad_hoc_stop(wlan_private * priv,
+				       struct HostCmd_DS_COMMAND *resp);
+extern int libertas_ret_80211_disassociate(wlan_private * priv,
+					struct HostCmd_DS_COMMAND *resp);
+extern int libertas_ret_80211_associate(wlan_private * priv,
+				     struct HostCmd_DS_COMMAND *resp);
+
+extern int libertas_idle_on(wlan_private * priv);
+extern int libertas_idle_off(wlan_private * priv);
+
+extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
+extern int libertas_reassociation_thread(void *data);
+
+struct WLAN_802_11_SSID;
+struct bss_descriptor;
+
+extern int libertas_start_adhoc_network(wlan_private * priv,
+			     struct WLAN_802_11_SSID *AdhocSSID);
+extern int libertas_join_adhoc_network(wlan_private * priv, struct bss_descriptor *pBSSDesc);
+extern int libertas_stop_adhoc_network(wlan_private * priv);
+
+extern int libertas_send_deauthentication(wlan_private * priv);
+extern int libertas_send_deauth(wlan_private * priv);
+
+extern int libertas_do_adhocstop_ioctl(wlan_private * priv);
+
+#ifdef __KERNEL__
+struct iw_request_info;
+extern int libertas_set_wap(struct net_device *dev, struct iw_request_info *info,
+			struct sockaddr *awrq, char *extra);
+#endif
+
+#endif
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_main.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_main.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_main.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_main.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,1163 @@
+/** @file wlan_main.c
+  *  
+  * @brief This file contains the major functions in WLAN
+  * driver. It includes init, exit, open, close and main
+  * thread etc..
+  * 
+  */
+/**
+  * @mainpage M-WLAN Linux Driver
+  *
+  * @section overview_sec Overview
+  *
+  * The M-WLAN is a Linux reference driver for Marvell
+  * 802.11 (a/b/g) WLAN chipset.
+  * 
+  * @section copyright_sec Copyright
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	09/30/05: Add Doxygen format comments
+	12/09/05: Add TX_QUEUE support	
+	01/05/06: Add kernel 2.6.x support	
+	01/11/06: Change compile flag BULVERDE_SDIO to SD to support
+	          Monahans/Zylonite
+	01/11/06: Conditionalize new scan/join functions.
+	01/12/06: Add TxLockFlag for UAPSD power save mode 
+	          and Proprietary Periodic sleep support
+	02/13/06: Add a patch for USB interoperability issue
+********************************************************/
+
+#include <linux/delay.h>
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "sbi.h"
+#include "wlan_decl.h"
+#include "wlan_dev.h"
+#include "wlan_fw.h"
+#include "wlan_wext.h"
+#include "wlan_debugfs.h"
+
+#ifdef REASSOCIATION
+#include "wlan_join.h"
+#endif
+
+#ifdef ENABLE_PM
+static struct pm_dev *wlan_pm_dev = NULL;
+#endif
+
+DEFINE_SPINLOCK(libertas_driver_lock);
+
+#define WLAN_TX_PWR_DEFAULT		20	/*100mW */
+#define WLAN_TX_PWR_US_DEFAULT		20	/*100mW */
+#define WLAN_TX_PWR_JP_DEFAULT		16	/*50mW */
+#define WLAN_TX_PWR_FR_DEFAULT		20	/*100mW */
+#define WLAN_TX_PWR_EMEA_DEFAULT	20	/*100mW */
+
+/* Format { Channel, Frequency (MHz), MaxTxPower } */
+/* Band: 'B/G', Region: USA FCC/Canada IC */
+static struct chan_freq_power channel_freq_power_US_BG[] = {
+	{1, 2412, WLAN_TX_PWR_US_DEFAULT},
+	{2, 2417, WLAN_TX_PWR_US_DEFAULT},
+	{3, 2422, WLAN_TX_PWR_US_DEFAULT},
+	{4, 2427, WLAN_TX_PWR_US_DEFAULT},
+	{5, 2432, WLAN_TX_PWR_US_DEFAULT},
+	{6, 2437, WLAN_TX_PWR_US_DEFAULT},
+	{7, 2442, WLAN_TX_PWR_US_DEFAULT},
+	{8, 2447, WLAN_TX_PWR_US_DEFAULT},
+	{9, 2452, WLAN_TX_PWR_US_DEFAULT},
+	{10, 2457, WLAN_TX_PWR_US_DEFAULT},
+	{11, 2462, WLAN_TX_PWR_US_DEFAULT}
+};
+
+/* Band: 'B/G', Region: Europe ETSI */
+static struct chan_freq_power channel_freq_power_EU_BG[] = {
+	{1, 2412, WLAN_TX_PWR_EMEA_DEFAULT},
+	{2, 2417, WLAN_TX_PWR_EMEA_DEFAULT},
+	{3, 2422, WLAN_TX_PWR_EMEA_DEFAULT},
+	{4, 2427, WLAN_TX_PWR_EMEA_DEFAULT},
+	{5, 2432, WLAN_TX_PWR_EMEA_DEFAULT},
+	{6, 2437, WLAN_TX_PWR_EMEA_DEFAULT},
+	{7, 2442, WLAN_TX_PWR_EMEA_DEFAULT},
+	{8, 2447, WLAN_TX_PWR_EMEA_DEFAULT},
+	{9, 2452, WLAN_TX_PWR_EMEA_DEFAULT},
+	{10, 2457, WLAN_TX_PWR_EMEA_DEFAULT},
+	{11, 2462, WLAN_TX_PWR_EMEA_DEFAULT},
+	{12, 2467, WLAN_TX_PWR_EMEA_DEFAULT},
+	{13, 2472, WLAN_TX_PWR_EMEA_DEFAULT}
+};
+
+/* Band: 'B/G', Region: Spain */
+static struct chan_freq_power channel_freq_power_SPN_BG[] = {
+	{10, 2457, WLAN_TX_PWR_DEFAULT},
+	{11, 2462, WLAN_TX_PWR_DEFAULT}
+};
+
+/* Band: 'B/G', Region: France */
+static struct chan_freq_power channel_freq_power_FR_BG[] = {
+	{10, 2457, WLAN_TX_PWR_FR_DEFAULT},
+	{11, 2462, WLAN_TX_PWR_FR_DEFAULT},
+	{12, 2467, WLAN_TX_PWR_FR_DEFAULT},
+	{13, 2472, WLAN_TX_PWR_FR_DEFAULT}
+};
+
+/* Band: 'B/G', Region: Japan */
+static struct chan_freq_power channel_freq_power_JPN_BG[] = {
+	{1, 2412, WLAN_TX_PWR_JP_DEFAULT},
+	{2, 2417, WLAN_TX_PWR_JP_DEFAULT},
+	{3, 2422, WLAN_TX_PWR_JP_DEFAULT},
+	{4, 2427, WLAN_TX_PWR_JP_DEFAULT},
+	{5, 2432, WLAN_TX_PWR_JP_DEFAULT},
+	{6, 2437, WLAN_TX_PWR_JP_DEFAULT},
+	{7, 2442, WLAN_TX_PWR_JP_DEFAULT},
+	{8, 2447, WLAN_TX_PWR_JP_DEFAULT},
+	{9, 2452, WLAN_TX_PWR_JP_DEFAULT},
+	{10, 2457, WLAN_TX_PWR_JP_DEFAULT},
+	{11, 2462, WLAN_TX_PWR_JP_DEFAULT},
+	{12, 2467, WLAN_TX_PWR_JP_DEFAULT},
+	{13, 2472, WLAN_TX_PWR_JP_DEFAULT},
+	{14, 2484, WLAN_TX_PWR_JP_DEFAULT}
+};
+
+/**
+ * the structure for channel, frequency and power
+ */
+struct region_cfp_table {
+	u8 region;
+	struct chan_freq_power *cfp_BG;
+	int cfp_no_BG;
+};
+
+/**
+ * the structure for the mapping between region and CFP
+ */
+static struct region_cfp_table region_cfp_table[] = {
+	{0x10,			/*US FCC */
+	 channel_freq_power_US_BG,
+	 sizeof(channel_freq_power_US_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+	{0x20,			/*CANADA IC */
+	 channel_freq_power_US_BG,
+	 sizeof(channel_freq_power_US_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+	{0x30, /*EU*/ channel_freq_power_EU_BG,
+	 sizeof(channel_freq_power_EU_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+	{0x31, /*SPAIN*/ channel_freq_power_SPN_BG,
+	 sizeof(channel_freq_power_SPN_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+	{0x32, /*FRANCE*/ channel_freq_power_FR_BG,
+	 sizeof(channel_freq_power_FR_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+	{0x40, /*JAPAN*/ channel_freq_power_JPN_BG,
+	 sizeof(channel_freq_power_JPN_BG) / sizeof(struct chan_freq_power),
+	 }
+	,
+/*Add new region here */
+};
+
+/**
+ * the rates supported by the card
+ */
+u8 libertas_wlan_data_rates[WLAN_SUPPORTED_RATES] =
+    { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12,
+	0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00
+};
+
+/**
+ * the rates supported
+ */
+u8 libertas_supported_rates[G_SUPPORTED_RATES] =
+    { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
+0 };
+
+/**
+ * the rates supported for ad-hoc G mode
+ */
+u8 libertas_adhoc_rates_g[G_SUPPORTED_RATES] =
+    { 0x82, 0x84, 0x8b, 0x96, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c,
+0 };
+
+/**
+ * the rates supported for ad-hoc B mode
+ */
+u8 libertas_adhoc_rates_b[4] = { 0x82, 0x84, 0x8b, 0x96 };
+
+/**
+ * the global variable of a pointer to wlan_private
+ * structure variable
+ */
+static wlan_private *wlanpriv = NULL;
+
+/**
+ * the table to keep region code
+ */
+u16 libertas_region_code_to_index[MRVDRV_MAX_REGION_CODE] =
+    { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 };
+
+static u8 *default_fw_name = "usb8388.bin";
+extern u8 *libertas_fw_name;
+
+/** 
+ *  @brief This function opens the network device
+ *  
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   WLAN_STATUS_SUCCESS
+ */
+static int wlan_open(struct net_device *dev)
+{
+	wlan_private *priv = (wlan_private *) dev->priv;
+	wlan_adapter *adapter = priv->adapter;
+	int i = 0;
+
+	ENTER();
+
+	/* For USB adapter, on some systems the device open handler will be 
+	 * called before FW ready. Use the following flag check and wait 
+	 * function to work around the issue.
+	 */
+	while (!adapter->fw_ready && i < 20) {
+		i++;
+		msleep_interruptible(100);
+	}
+	if (!adapter->fw_ready) {
+		PRINTM(FATAL,
+		       "FW not ready, wlan_open() return failure\n");
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	priv->open = 1;
+
+	if (adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		netif_carrier_on(priv->wlan_dev.netdev);
+		netif_wake_queue(priv->wlan_dev.netdev);
+	} else
+		netif_carrier_off(priv->wlan_dev.netdev);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function closes the network device
+ *  
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   WLAN_STATUS_SUCCESS
+ */
+static int wlan_close(struct net_device *dev)
+{
+	wlan_private *priv = dev->priv;
+
+	ENTER();
+
+	netif_stop_queue(priv->wlan_dev.netdev);
+	netif_carrier_off(priv->wlan_dev.netdev);
+
+	priv->open = 0;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+#ifdef ENABLE_PM
+
+/** 
+ *  @brief This function is a callback function. it is called by
+ *  kernel to enter or exit power saving mode.
+ *  
+ *  @param pmdev   A pointer to pm_dev
+ *  @param pmreq   pm_request_t
+ *  @param pmdata  A pointer to pmdata
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_pm_callback(struct pm_dev *pmdev, pm_request_t pmreq,
+			    void *pmdata)
+{
+	wlan_private *priv = wlanpriv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct net_device *dev = priv->wlan_dev.netdev;
+
+	PRINTM(INFO, "WPRM_PM_CALLBACK: pmreq = %d.\n", pmreq);
+
+	switch (pmreq) {
+	case PM_SUSPEND:
+		PRINTM(INFO, "WPRM_PM_CALLBACK: enter PM_SUSPEND.\n");
+
+		/* in associated mode */
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			if ((Adapter->PSState != PS_STATE_SLEEP)
+			    ) {
+				PRINTM(INFO,
+				       "wlan_pm_callback: can't enter sleep mode\n");
+				return WLAN_STATUS_FAILURE;
+			} else {
+
+				/*
+				 * Detach the network interface
+				 * if the network is running
+				 */
+				if (netif_running(dev)) {
+					netif_device_detach(dev);
+					PRINTM(INFO,
+					       "netif_device_detach().\n");
+				}
+				libertas_sbi_suspend(priv);
+			}
+			break;
+		}
+
+		/* in non associated mode */
+
+		/*
+		 * Detach the network interface 
+		 * if the network is running
+		 */
+		if (netif_running(dev))
+			netif_device_detach(dev);
+
+		/* 
+		 * Storing and restoring of the regs be taken care 
+		 * at the driver rest will be done at wlan driver
+		 * this makes driver independent of the card
+		 */
+
+		libertas_sbi_suspend(priv);
+
+		break;
+
+	case PM_RESUME:
+		/* in associated mode */
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+			{
+				/*
+				 * Bring the inteface up first
+				 * This case should not happen still ...
+				 */
+				libertas_sbi_resume(priv);
+
+				/*
+				 * Attach the network interface
+				 * if the network is running
+				 */
+				if (netif_running(dev)) {
+					netif_device_attach(dev);
+					PRINTM(INFO,
+					       "after netif_device_attach().\n");
+				}
+				PRINTM(INFO,
+				       "After netif attach, in associated mode.\n");
+			}
+			break;
+		}
+
+		/* in non associated mode */
+
+		/*
+		 * Bring the inteface up first 
+		 * This case should not happen still ...
+		 */
+
+		libertas_sbi_resume(priv);
+
+		if (netif_running(dev))
+			netif_device_attach(dev);
+
+		PRINTM(INFO, "after netif attach, in NON associated mode.\n");
+		break;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+#endif				/* ENABLE_PM */
+
+/** 
+ *  @brief This function handles packet transmission
+ *  
+ *  @param skb     A pointer to sk_buff structure
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	int ret = 0;
+	wlan_private *priv = dev->priv;
+
+	ENTER();
+
+	if (priv->wlan_dev.dnld_sent || priv->adapter->TxLockFlag) {
+		priv->stats.tx_dropped++;
+		goto done;
+	}
+
+	netif_stop_queue(priv->wlan_dev.netdev);
+
+	if (libertas_process_tx(priv, skb) == 0)
+		dev->trans_start = jiffies;
+done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function handles the timeout of packet
+ *  transmission
+ *  
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   n/a
+ */
+static void wlan_tx_timeout(struct net_device *dev)
+{
+	wlan_private *priv = (wlan_private *) dev->priv;
+
+	ENTER();
+
+	PRINTM(FATAL, "tx watch dog timeout!\n");
+
+	priv->wlan_dev.dnld_sent = DNLD_RES_RECEIVED;
+	dev->trans_start = jiffies;
+
+	if (priv->adapter->CurrentTxSkb) {
+		if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
+			/* If we are here, we have not received feedback from
+			   the previous packet.  Assume TX_FAIL and move on. */
+			priv->adapter->EventCause = 0x01000000;
+			libertas_send_tx_feedback(priv);
+		} else
+			wake_up_interruptible(&priv->MainThread.waitQ);
+	} else if (priv->adapter->MediaConnectStatus == WlanMediaStateConnected)
+		netif_wake_queue(priv->wlan_dev.netdev);
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function returns the network statistics
+ *  
+ *  @param dev     A pointer to wlan_private structure
+ *  @return 	   A pointer to net_device_stats structure
+ */
+static struct net_device_stats *wlan_get_stats(struct net_device *dev)
+{
+	wlan_private *priv = (wlan_private *) dev->priv;
+
+	return &priv->stats;
+}
+
+/** 
+ *  @brief This function sets the MAC address to firmware.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param pRxPD   A pointer to RxPD structure of received packet
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_set_mac_address(struct net_device *dev, void *addr)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = (wlan_private *) dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct sockaddr *pHwAddr = (struct sockaddr *)addr;
+
+	ENTER();
+
+	memset(Adapter->CurrentAddr, 0, ETH_ALEN);
+
+	/* dev->dev_addr is 8 bytes */
+	HEXDUMP("dev->dev_addr:", dev->dev_addr, ETH_ALEN);
+
+	HEXDUMP("addr:", pHwAddr->sa_data, ETH_ALEN);
+	memcpy(Adapter->CurrentAddr, pHwAddr->sa_data, ETH_ALEN);
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_MAC_ADDRESS,
+				    HostCmd_ACT_SET,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		PRINTM(INFO, "set mac address failed.\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	HEXDUMP("Adapter->MacAddr:", Adapter->CurrentAddr, ETH_ALEN);
+	memcpy(dev->dev_addr, Adapter->CurrentAddr, ETH_ALEN);
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+static int wlan_copy_multicast_address(wlan_adapter * Adapter,
+				     struct net_device *dev)
+{
+	int i = 0;
+	struct dev_mc_list *mcptr = dev->mc_list;
+
+	for (i = 0; i < dev->mc_count; i++) {
+		memcpy(&Adapter->MulticastList[i], mcptr->dmi_addr, ETH_ALEN);
+		mcptr = mcptr->next;
+	}
+
+	return i;
+
+}
+
+/** 
+ *  @brief This function sets multicast addresses to firmware
+ *  
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   n/a
+ */
+static void wlan_set_multicast_list(struct net_device *dev)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int OldPacketFilter;
+
+	ENTER();
+
+	OldPacketFilter = Adapter->CurrentPacketFilter;
+
+	if (dev->flags & IFF_PROMISC) {
+		PRINTM(INFO, "Enable Promiscuous mode\n");
+		Adapter->CurrentPacketFilter |=
+		    HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+		Adapter->CurrentPacketFilter &=
+		    ~(HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE |
+		      HostCmd_ACT_MAC_MULTICAST_ENABLE);
+	} else {
+		/* Multicast */
+		Adapter->CurrentPacketFilter &=
+		    ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
+
+		if (dev->flags & IFF_ALLMULTI || dev->mc_count >
+		    MRVDRV_MAX_MULTICAST_LIST_SIZE) {
+			PRINTM(INFO, "Enabling All Multicast!\n");
+			Adapter->CurrentPacketFilter |=
+			    HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+			Adapter->CurrentPacketFilter &=
+			    ~HostCmd_ACT_MAC_MULTICAST_ENABLE;
+		} else {
+			Adapter->CurrentPacketFilter &=
+			    ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE;
+
+			if (!dev->mc_count) {
+				PRINTM(INFO, "No multicast addresses - "
+				       "disabling multicast!\n");
+				Adapter->CurrentPacketFilter &=
+				    ~HostCmd_ACT_MAC_MULTICAST_ENABLE;
+			} else {
+				int i;
+
+				Adapter->CurrentPacketFilter |=
+				    HostCmd_ACT_MAC_MULTICAST_ENABLE;
+
+				Adapter->NumOfMulticastMACAddr =
+				    wlan_copy_multicast_address(Adapter, dev);
+
+				PRINTM(INFO, "Multicast addresses: %d\n",
+				       dev->mc_count);
+
+				for (i = 0; i < dev->mc_count; i++) {
+					PRINTM(INFO, "Multicast address %d:"
+					       "%x %x %x %x %x %x\n", i,
+					       Adapter->MulticastList[i][0],
+					       Adapter->MulticastList[i][1],
+					       Adapter->MulticastList[i][2],
+					       Adapter->MulticastList[i][3],
+					       Adapter->MulticastList[i][4],
+					       Adapter->MulticastList[i][5]);
+				}
+				/* set multicast addresses to firmware */
+				libertas_prepare_and_send_command(priv,
+						      HostCmd_CMD_MAC_MULTICAST_ADR,
+						      HostCmd_ACT_GEN_SET, 0, 0,
+						      NULL);
+			}
+		}
+	}
+
+	if (Adapter->CurrentPacketFilter != OldPacketFilter) {
+		libertas_set_mac_packet_filter(priv);
+	}
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function hanldes the major job in WLAN driver.
+ *  it handles the event generated by firmware, rx data received
+ *  from firmware and tx data sent from kernel.
+ *  
+ *  @param data    A pointer to wlan_thread structure
+ *  @return 	   WLAN_STATUS_SUCCESS
+ */
+static int wlan_service_main_thread(void *data)
+{
+	unsigned long flags;
+	struct wlan_thread *thread = data;
+	wlan_private *priv = thread->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	wait_queue_t wait;
+	u8 ireg = 0;
+
+	ENTER();
+
+	wlan_activate_thread(thread);
+
+	init_waitqueue_entry(&wait, current);
+
+	for (;;) {
+		PRINTM(INFO, "main-thread 111: IntCounter=%d "
+		       "CurrentTxSkb=%p dnld_sent=%d\n",
+		       Adapter->IntCounter,
+		       Adapter->CurrentTxSkb, priv->wlan_dev.dnld_sent);
+
+		add_wait_queue(&thread->waitQ, &wait);
+		set_current_state(TASK_INTERRUPTIBLE);
+
+		if ((Adapter->PSState == PS_STATE_SLEEP) ||
+		    (!Adapter->IntCounter
+		     && (priv->wlan_dev.dnld_sent || Adapter->CurCmd ||
+			 list_empty(&Adapter->CmdPendingQ))
+		    )
+		    ) {
+			PRINTM(INFO,
+			       "main-thread sleeping... Conn=%d IntC=%d PS_Mode=%d PS_State=%d\n",
+			       Adapter->MediaConnectStatus, Adapter->IntCounter,
+			       Adapter->PSMode, Adapter->PSState);
+
+			schedule();
+		}
+
+		PRINTM(INFO,
+		       "main-thread 222 (waking up): IntCounter=%d CurrentTxSkb=%p "
+		       "dnld_sent=%d\n", Adapter->IntCounter,
+		       Adapter->CurrentTxSkb, priv->wlan_dev.dnld_sent);
+
+		set_current_state(TASK_RUNNING);
+		remove_wait_queue(&thread->waitQ, &wait);
+		try_to_freeze();
+
+		PRINTM(INFO, "main-thread 333: IntCounter=%d CurrentTxSkb=%p "
+		       "dnld_sent=%d\n",
+		       Adapter->IntCounter,
+		       Adapter->CurrentTxSkb, priv->wlan_dev.dnld_sent);
+
+		if (kthread_should_stop()
+		    || Adapter->SurpriseRemoved) {
+			PRINTM(INFO,
+			       "main-thread: break from main thread: SurpriseRemoved=0x%x\n",
+			       Adapter->SurpriseRemoved);
+			break;
+		}
+
+		if (Adapter->IntCounter) {
+			u8 int_status;
+
+			spin_lock_irqsave(&libertas_driver_lock, flags);
+			Adapter->IntCounter = 0;
+			int_status = libertas_sbi_get_int_status(priv, &ireg);
+			spin_unlock_irqrestore(&libertas_driver_lock, flags);
+
+			if (int_status) {
+				PRINTM(INFO,
+				       "main-thread: reading HOST_INT_STATUS_REG failed\n");
+				continue;
+			}
+			spin_lock_irqsave(&libertas_driver_lock, flags);
+			Adapter->HisRegCpy |= ireg;
+			spin_unlock_irqrestore(&libertas_driver_lock, flags);
+		}
+
+		PRINTM(INFO, "main-thread 444: IntCounter=%d CurrentTxSkb=%p "
+		       "dnld_sent=%d\n",
+		       Adapter->IntCounter,
+		       Adapter->CurrentTxSkb, priv->wlan_dev.dnld_sent);
+
+		/* Command response? */
+		if (Adapter->HisRegCpy & HIS_CmdUpLdRdy) {
+			PRINTM(INFO, "main-thread: Cmd response ready.\n");
+
+			spin_lock_irqsave(&libertas_driver_lock, flags);
+			Adapter->HisRegCpy &= ~HIS_CmdUpLdRdy;
+			spin_unlock_irqrestore(&libertas_driver_lock, flags);
+
+			libertas_process_rx_command(priv);
+		}
+
+		/* Any Card Event */
+		if (Adapter->HisRegCpy & HIS_CardEvent) {
+			PRINTM(INFO, "main-thread: Card Event Activity.\n");
+
+			spin_lock_irqsave(&libertas_driver_lock, flags);
+			Adapter->HisRegCpy &= ~HIS_CardEvent;
+			spin_unlock_irqrestore(&libertas_driver_lock, flags);
+
+			if (libertas_sbi_read_event_cause(priv)) {
+				PRINTM(MSG,
+				       "main-thread: libertas_sbi_read_event_cause failed.\n");
+				continue;
+			}
+			libertas_process_event(priv);
+		}
+
+		/* Check if we need to confirm Sleep Request received previously */
+		if (Adapter->PSState == PS_STATE_PRE_SLEEP) {
+			if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) {
+				if (Adapter->MediaConnectStatus ==
+				    WlanMediaStateConnected) {
+					PRINTM(INFO,
+					       "main_thread: PRE_SLEEP--IntCounter=%d CurrentTxSkb=%p "
+					       "dnld_sent=%d CurCmd=%p, confirm now\n",
+					       Adapter->IntCounter,
+					       Adapter->CurrentTxSkb,
+					       priv->wlan_dev.dnld_sent,
+					       Adapter->CurCmd);
+
+					libertas_ps_confirm_sleep(priv,
+						       (u16) Adapter->PSMode);
+				} else {
+					/* workaround for firmware sending deauth/linkloss event
+					   immediately after sleep request, remove this after
+					   firmware fixes it */
+					Adapter->PSState = PS_STATE_AWAKE;
+					PRINTM(MSG,
+					       "main-thread: ignore PS_SleepConfirm in non-connected state\n");
+				}
+			}
+		}
+
+		/* The PS state is changed during processing of Sleep Request event above */
+		if ((priv->adapter->PSState == PS_STATE_SLEEP)
+		    || (priv->adapter->PSState == PS_STATE_PRE_SLEEP)
+		    ) {
+			continue;
+		}
+
+		/* Execute the next command */
+		if (!priv->wlan_dev.dnld_sent && !Adapter->CurCmd) {
+			libertas_execute_next_command(priv);
+		}
+
+		libertas_tx_runqueue(priv);
+
+	}
+
+	wlan_deactivate_thread(thread);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ * @brief This function adds the card. it will probe the
+ * card, allocate the wlan_priv and initialize the device. 
+ *  
+ *  @param card    A pointer to card
+ *  @return 	   A pointer to wlan_private structure
+ */
+static wlan_private *wlan_add_card(void *card)
+{
+	struct net_device *dev = NULL;
+	wlan_private *priv = NULL;
+
+	ENTER();
+
+	/* probe the card */
+	if (libertas_sbi_probe_card(card) < 0) {
+		PRINTM(MSG, "NO card found!\n");
+		return NULL;
+	}
+
+	/* Allocate an Ethernet device and register it */
+	if (!(dev = alloc_etherdev(sizeof(wlan_private)))) {
+		PRINTM(MSG, "Init ethernet device failed!\n");
+		return NULL;
+	}
+
+	priv = dev->priv;
+
+	/* allocate buffer for wlan_adapter */
+	if (!(priv->adapter = kmalloc(sizeof(wlan_adapter), GFP_KERNEL))) {
+		PRINTM(MSG, "Allocate buffer for wlan_adapter failed!\n");
+		goto err_kmalloc;
+	}
+
+	/* init wlan_adapter */
+	memset(priv->adapter, 0, sizeof(wlan_adapter));
+
+	priv->wlan_dev.netdev = dev;
+	priv->wlan_dev.card = card;
+	wlanpriv = priv;
+
+	SET_MODULE_OWNER(dev);
+
+	/* Setup the OS Interface to our functions */
+	dev->open = wlan_open;
+	dev->hard_start_xmit = wlan_hard_start_xmit;
+	dev->stop = wlan_close;
+	dev->do_ioctl = libertas_do_ioctl;
+	dev->set_mac_address = wlan_set_mac_address;
+
+#define	WLAN_WATCHDOG_TIMEOUT	(5 * HZ)
+
+	dev->tx_timeout = wlan_tx_timeout;
+	dev->get_stats = wlan_get_stats;
+	dev->watchdog_timeo = WLAN_WATCHDOG_TIMEOUT;
+
+#ifdef	WIRELESS_EXT
+	dev->wireless_handlers = (struct iw_handler_def *)&libertas_handler_def;
+#endif
+#define NETIF_F_DYNALLOC 16
+	dev->features |= NETIF_F_DYNALLOC;
+	dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
+	dev->set_multicast_list = wlan_set_multicast_list;
+
+	init_waitqueue_head(&priv->adapter->ds_awake_q);
+
+	INIT_LIST_HEAD(&priv->adapter->CmdFreeQ);
+	INIT_LIST_HEAD(&priv->adapter->CmdPendingQ);
+
+	PRINTM(INFO, "Starting kthread...\n");
+	priv->MainThread.priv = priv;
+	wlan_create_thread(wlan_service_main_thread,
+			   &priv->MainThread, "wlan_main_service");
+
+#ifdef REASSOCIATION
+	priv->ReassocThread.priv = priv;
+	wlan_create_thread(libertas_reassociation_thread,
+			   &priv->ReassocThread, "wlan_reassoc_service");
+#endif				/* REASSOCIATION */
+
+	/*
+	 * Register the device. Fillup the private data structure with
+	 * relevant information from the card and request for the required
+	 * IRQ. 
+	 */
+	if (libertas_sbi_register_dev(priv) < 0) {
+		PRINTM(FATAL, "Failed to register wlan device!\n");
+		goto err_registerdev;
+	}
+
+	/* Get the CIS Table */
+	libertas_sbi_get_cis_info(priv);
+
+	/* init FW and HW */
+	if (libertas_init_fw(priv)) {
+		PRINTM(INFO, "Firmware Init Failed\n");
+		goto err_registerdev;
+	}
+
+	if (register_netdev(dev)) {
+		printk(KERN_ERR "Cannot register network device!\n");
+		goto err_init_fw;
+	}
+
+	PRINTM(WARN, "%s: Marvell Wlan 802.11 Adapter "
+	       "revision 0x%02X at IRQ %i\n", dev->name,
+	       priv->adapter->chip_rev, dev->irq);
+
+	libertas_debugfs_init_one(priv, dev);
+
+#ifdef ENABLE_PM
+	if (!(wlan_pm_dev = pm_register(PM_UNKNOWN_DEV, 0, wlan_pm_callback)))
+		PRINTM(MSG, "Failed to register PM callback\n");
+#endif
+
+	LEAVE();
+	return priv;
+
+err_init_fw:
+	libertas_sbi_unregister_dev(priv);
+err_registerdev:
+	/* Stop the thread servicing the interrupts */
+	wake_up_interruptible(&priv->MainThread.waitQ);
+	wlan_terminate_thread(&priv->MainThread);
+#ifdef REASSOCIATION
+	wake_up_interruptible(&priv->ReassocThread.waitQ);
+	wlan_terminate_thread(&priv->ReassocThread);
+#endif				/* REASSOCIATION */
+	kfree(priv->adapter);
+err_kmalloc:
+	free_netdev(dev);
+	wlanpriv = NULL;
+
+	LEAVE();
+	return NULL;
+}
+
+/** 
+ *  @brief This function removes the card.
+ *  
+ *  @param priv    A pointer to card
+ *  @return 	   WLAN_STATUS_SUCCESS
+ */
+static int wlan_remove_card(void *card)
+{
+	wlan_private *priv = wlanpriv;
+	wlan_adapter *Adapter;
+	struct net_device *dev;
+	union iwreq_data wrqu;
+
+	ENTER();
+
+	if (!priv) {
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	Adapter = priv->adapter;
+
+	if (!Adapter) {
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	dev = priv->wlan_dev.netdev;
+
+	wake_up_interruptible(&Adapter->ds_awake_q);
+
+	if (Adapter->CurCmd) {
+		PRINTM(INFO, "Wake up current cmdwait_q\n");
+		wake_up_interruptible(&Adapter->CurCmd->cmdwait_q);
+	}
+
+	Adapter->CurCmd = NULL;
+
+	if (Adapter->PSMode == Wlan802_11PowerModeMAX_PSP) {
+		Adapter->PSMode = Wlan802_11PowerModeCAM;
+		libertas_ps_wakeup(priv, HostCmd_OPTION_WAITFORRSP);
+	}
+
+	memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN);
+	wrqu.ap_addr.sa_family = ARPHRD_ETHER;
+	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWAP, &wrqu, NULL);
+
+	/* Disable interrupts on the card as we cannot handle them after RESET */
+	libertas_sbi_disable_host_int(priv);
+
+	libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RESET,
+			      HostCmd_ACT_HALT, 0, 0, NULL);
+
+	msleep_interruptible(200);
+
+#ifdef ENABLE_PM
+	pm_unregister(wlan_pm_dev);
+#endif
+
+	netif_stop_queue(priv->wlan_dev.netdev);
+	netif_carrier_off(priv->wlan_dev.netdev);
+
+	Adapter->SurpriseRemoved = 1;
+
+	/* Stop the thread servicing the interrupts */
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+#ifdef REASSOCIATION
+	wake_up_interruptible(&priv->ReassocThread.waitQ);
+#endif				/* REASSOCIATION */
+
+	libertas_debugfs_remove_one(priv);
+
+	PRINTM(INFO, "unregister dev\n");
+	libertas_sbi_unregister_dev(priv);
+
+	PRINTM(INFO, "Free Adapter\n");
+	libertas_free_adapter(priv);
+
+	/* Last reference is our one */
+	PRINTM(INFO, "refcnt = %d\n", atomic_read(&dev->refcnt));
+
+	msleep(10);
+
+	PRINTM(INFO, "netdev_finish_unregister: %s%s.\n", dev->name,
+	       (dev->features & NETIF_F_DYNALLOC) ? "" : ", old style");
+
+	unregister_netdev(dev);
+
+	PRINTM(INFO, "Unregister finish\n");
+
+	priv->wlan_dev.netdev = NULL;
+	free_netdev(dev);
+	wlanpriv = NULL;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function finds the CFP in 
+ *  region_cfp_table based on region and band parameter.
+ *  
+ *  @param region  The region code
+ *  @param band	   The band
+ *  @param cfp_no  A pointer to CFP number
+ *  @return 	   A pointer to CFP
+ */
+struct chan_freq_power *libertas_get_region_cfp_table(u8 region, u8 band, int *cfp_no)
+{
+	int i, end;
+
+	ENTER();
+
+	end = sizeof(region_cfp_table)/sizeof(struct region_cfp_table);
+
+	for (i = 0; i < end ; i++) {
+		PRINTM(INFO, "region_cfp_table[i].region=%d\n",
+			region_cfp_table[i].region);
+		if (region_cfp_table[i].region == region) {
+			*cfp_no = region_cfp_table[i].cfp_no_BG;
+			LEAVE();
+			return region_cfp_table[i].cfp_BG;
+		}
+	}
+
+	LEAVE();
+	return NULL;
+}
+
+/** 
+ *  @brief This function sets region table. 
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param region  The region code
+ *  @param band	   The band
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_set_regiontable(wlan_private * priv, u8 region, u8 band)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int i = 0;
+
+	struct chan_freq_power *cfp;
+	int cfp_no;
+
+	ENTER();
+
+	memset(Adapter->region_channel, 0, sizeof(Adapter->region_channel));
+
+	{
+		cfp = libertas_get_region_cfp_table(region, band, &cfp_no);
+		if (cfp != NULL) {
+			Adapter->region_channel[i].NrCFP = cfp_no;
+			Adapter->region_channel[i].CFP = cfp;
+		} else {
+			PRINTM(INFO, "wrong region code %#x in Band B-G\n",
+			       region);
+			return WLAN_STATUS_FAILURE;
+		}
+		Adapter->region_channel[i].Valid = 1;
+		Adapter->region_channel[i].Region = region;
+		Adapter->region_channel[i].Band = band;
+		i++;
+	}
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief This function handles the interrupt. it will change PS
+ *  state if applicable. it will wake up main_thread to handle
+ *  the interrupt event as well.
+ *  
+ *  @param dev     A pointer to net_device structure
+ *  @return 	   n/a
+ */
+void libertas_interrupt(struct net_device *dev)
+{
+	wlan_private *priv = dev->priv;
+
+	ENTER();
+
+	PRINTM(INFO, "libertas_interrupt: IntCounter=%d\n",
+	       priv->adapter->IntCounter);
+
+	priv->adapter->IntCounter++;
+
+	if (priv->adapter->PSState == PS_STATE_SLEEP) {
+		priv->adapter->PSState = PS_STATE_AWAKE;
+		netif_wake_queue(dev);
+	}
+
+	wake_up_interruptible(&priv->MainThread.waitQ);
+
+	LEAVE();
+}
+
+/** 
+ *  @brief This function initializes module.
+ *  
+ *  @param	   n/a    A pointer to wlan_private structure
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int wlan_init_module(void)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+
+	if (libertas_fw_name == NULL) {
+		libertas_fw_name = default_fw_name;
+	}
+
+	if (libertas_sbi_register(wlan_add_card, wlan_remove_card, NULL) == NULL) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	libertas_debugfs_init();
+
+done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function cleans module
+ *  
+ *  @param priv    n/a
+ *  @return 	   n/a
+ */
+static void wlan_cleanup_module(void)
+{
+	ENTER();
+
+	libertas_sbi_unregister();
+	libertas_debugfs_remove();
+
+	LEAVE();
+}
+
+module_init(wlan_init_module);
+module_exit(wlan_cleanup_module);
+
+MODULE_DESCRIPTION("M-WLAN Driver");
+MODULE_AUTHOR("Marvell International Ltd.");
+MODULE_LICENSE("GPL");
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_rx.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_rx.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_rx.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_rx.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,482 @@
+/** @file wlan_rx.c
+  * @brief This file contains the handling of RX in wlan driver.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	09/28/05: Add Doxygen format comments
+	12/09/05: ADD Sliding window SNR/NF Average Calculation support
+	
+********************************************************/
+
+#include <linux/etherdevice.h>
+#include <linux/types.h>
+
+#include "hostcmd.h"
+#include "radiotap.h"
+#include "wlan_decl.h"
+#include "wlan_dev.h"
+#include "wlan_wext.h"
+
+struct Eth803Hdr {
+	u8 dest_addr[6];
+	u8 src_addr[6];
+	u16 h803_len;
+} __attribute__ ((packed));
+
+struct Rfc1042Hdr {
+	u8 llc_dsap;
+	u8 llc_ssap;
+	u8 llc_ctrl;
+	u8 snap_oui[3];
+	u16 snap_type;
+} __attribute__ ((packed));
+
+struct RxPacketHdr {
+	struct RxPD rx_pd;
+	struct Eth803Hdr eth803_hdr;
+	struct Rfc1042Hdr rfc1042_hdr;
+} __attribute__ ((packed));
+
+struct Rx80211PacketHdr {
+	struct RxPD rx_pd;
+	void *eth80211_hdr;
+} __attribute__ ((packed));
+
+static int ProcessRxed_802_11_Packet(wlan_private * priv, struct sk_buff *skb);
+
+/** 
+ *  @brief This function computes the AvgSNR .
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   AvgSNR
+ */
+static u8 wlan_getAvgSNR(wlan_private * priv)
+{
+	u8 i;
+	u16 temp = 0;
+	wlan_adapter *Adapter = priv->adapter;
+	if (Adapter->numSNRNF == 0)
+		return 0;
+	for (i = 0; i < Adapter->numSNRNF; i++)
+		temp += Adapter->rawSNR[i];
+	return (u8) (temp / Adapter->numSNRNF);
+
+}
+
+/** 
+ *  @brief This function computes the AvgNF
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   AvgNF
+ */
+static u8 wlan_getAvgNF(wlan_private * priv)
+{
+	u8 i;
+	u16 temp = 0;
+	wlan_adapter *Adapter = priv->adapter;
+	if (Adapter->numSNRNF == 0)
+		return 0;
+	for (i = 0; i < Adapter->numSNRNF; i++)
+		temp += Adapter->rawNF[i];
+	return (u8) (temp / Adapter->numSNRNF);
+
+}
+
+/** 
+ *  @brief This function save the raw SNR/NF to our internel buffer
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param pRxPD   A pointer to RxPD structure of received packet
+ *  @return 	   n/a
+ */
+static void wlan_save_rawSNRNF(wlan_private * priv, struct RxPD *pRxPD)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	if (Adapter->numSNRNF < Adapter->data_avg_factor)
+		Adapter->numSNRNF++;
+	Adapter->rawSNR[Adapter->nextSNRNF] = pRxPD->SNR;
+	Adapter->rawNF[Adapter->nextSNRNF] = pRxPD->NF;
+	Adapter->nextSNRNF++;
+	if (Adapter->nextSNRNF >= Adapter->data_avg_factor)
+		Adapter->nextSNRNF = 0;
+	return;
+}
+
+/** 
+ *  @brief This function computes the RSSI in received packet.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param pRxPD   A pointer to RxPD structure of received packet
+ *  @return 	   n/a
+ */
+static void wlan_compute_rssi(wlan_private * priv, struct RxPD *pRxPD)
+{
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	PRINTM(INFO, "RxPD: SNR = %d, NF = %d\n", pRxPD->SNR, pRxPD->NF);
+	PRINTM(INFO, "Before computing SNR: SNR- avg = %d, NF-avg = %d\n",
+	       Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+	       Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+
+	Adapter->SNR[TYPE_RXPD][TYPE_NOAVG] = pRxPD->SNR;
+	Adapter->NF[TYPE_RXPD][TYPE_NOAVG] = pRxPD->NF;
+	wlan_save_rawSNRNF(priv, pRxPD);
+
+	Adapter->RxPDSNRAge = jiffies;
+	Adapter->RxPDRate = pRxPD->RxRate;
+
+	Adapter->SNR[TYPE_RXPD][TYPE_AVG] = wlan_getAvgSNR(priv) * AVG_SCALE;
+	Adapter->NF[TYPE_RXPD][TYPE_AVG] = wlan_getAvgNF(priv) * AVG_SCALE;
+	PRINTM(INFO, "After computing SNR: SNR-avg = %d, NF-avg = %d\n",
+	       Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+	       Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+
+	Adapter->RSSI[TYPE_RXPD][TYPE_NOAVG] =
+	    CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_NOAVG],
+		     Adapter->NF[TYPE_RXPD][TYPE_NOAVG]);
+
+	Adapter->RSSI[TYPE_RXPD][TYPE_AVG] =
+	    CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE,
+		     Adapter->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE);
+
+	LEAVE();
+}
+
+/********************************************************
+		Global functions
+********************************************************/
+
+int libertas_upload_rx_packet(wlan_private * priv, struct sk_buff *skb)
+{
+	PRINTM(INFO, "skb->data=%p\n", skb->data);
+
+	skb->dev = priv->wlan_dev.netdev;
+	skb->protocol = eth_type_trans(skb, priv->wlan_dev.netdev);
+	skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+	netif_rx(skb);
+
+	return 0;
+}
+
+/**
+ *  @brief This function processes received packet and forwards it
+ *  to kernel/upper layer
+ *  
+ *  @param priv    A pointer to wlan_private
+ *  @param skb     A pointer to skb which includes the received packet
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_process_rxed_packet(wlan_private * priv, struct sk_buff *skb)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	struct RxPacketHdr *pRxPkt;
+	struct RxPD *pRxPD;
+
+	int hdrChop;
+	struct EthII_Hdr *pEthHdr;
+
+	const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+	ENTER();
+
+	if (priv->adapter->debugmode & MRVDRV_DEBUG_RX_PATH)
+		HEXDUMP("RX packet: ", skb->data,
+			 min_t(unsigned int, skb->len, 100));
+
+	if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
+		return ProcessRxed_802_11_Packet(priv, skb);
+
+	pRxPkt = (struct RxPacketHdr *) skb->data;
+	pRxPD = &pRxPkt->rx_pd;
+
+	HEXDUMP("RX Data: Before chop RxPD", skb->data,
+		 min_t(unsigned int, skb->len, 100));
+
+	if (skb->len < (ETH_HLEN + 8 + sizeof(struct RxPD))) {
+		PRINTM(INFO, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n");
+		priv->stats.rx_length_errors++;
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	/* 
+	 * Check RxPD status and update 802.3 stat,
+	 */
+	if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK)) {
+		PRINTM(INFO, "RX Error: frame received with bad status\n");
+		printk("<1> RxPD Not OK\n");
+		priv->stats.rx_errors++;
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	PRINTM(INFO, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
+	       skb->len, sizeof(struct RxPD), skb->len - sizeof(struct RxPD));
+
+	HEXDUMP("RX Data: Dest", pRxPkt->eth803_hdr.dest_addr,
+		sizeof(pRxPkt->eth803_hdr.dest_addr));
+	HEXDUMP("RX Data: Src", pRxPkt->eth803_hdr.src_addr,
+		sizeof(pRxPkt->eth803_hdr.src_addr));
+
+	if (memcmp(&pRxPkt->rfc1042_hdr,
+		   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
+		/* 
+		 *  Replace the 803 header and rfc1042 header (llc/snap) with an 
+		 *    EthernetII header, keep the src/dst and snap_type (ethertype)
+		 *
+		 *  The firmware only passes up SNAP frames converting
+		 *    all RX Data from 802.11 to 802.2/LLC/SNAP frames.
+		 *
+		 *  To create the Ethernet II, just move the src, dst address right
+		 *    before the snap_type.
+		 */
+		pEthHdr = (struct EthII_Hdr *)
+		    ((u8 *) & pRxPkt->eth803_hdr
+		     + sizeof(pRxPkt->eth803_hdr) + sizeof(pRxPkt->rfc1042_hdr)
+		     - sizeof(pRxPkt->eth803_hdr.dest_addr)
+		     - sizeof(pRxPkt->eth803_hdr.src_addr)
+		     - sizeof(pRxPkt->rfc1042_hdr.snap_type));
+
+		memcpy(pEthHdr->src_addr, pRxPkt->eth803_hdr.src_addr,
+		       sizeof(pEthHdr->src_addr));
+		memcpy(pEthHdr->dest_addr, pRxPkt->eth803_hdr.dest_addr,
+		       sizeof(pEthHdr->dest_addr));
+
+		/* Chop off the RxPD + the excess memory from the 802.2/llc/snap header
+		 *   that was removed 
+		 */
+		hdrChop = (u8 *) pEthHdr - (u8 *) pRxPkt;
+	} else {
+		HEXDUMP("RX Data: LLC/SNAP",
+			(u8 *) & pRxPkt->rfc1042_hdr,
+			sizeof(pRxPkt->rfc1042_hdr));
+
+		/* Chop off the RxPD */
+		hdrChop = (u8 *) & pRxPkt->eth803_hdr - (u8 *) pRxPkt;
+	}
+
+	/* Chop off the leading header bytes so the skb points to the start of 
+	 *   either the reconstructed EthII frame or the 802.2/llc/snap frame
+	 */
+	skb_pull(skb, hdrChop);
+
+	/* Take the data rate from the RxPD structure 
+	 * only if the rate is auto
+	 */
+	if (Adapter->Is_DataRate_Auto) {
+		Adapter->DataRate = libertas_index_to_data_rate(pRxPD->RxRate);
+	}
+
+	wlan_compute_rssi(priv, pRxPD);
+
+	PRINTM(INFO, "RX Data: Size of actual packet = %d\n", skb->len);
+	if (libertas_upload_rx_packet(priv, skb)) {
+		PRINTM(INFO, "RX Error: libertas_upload_rx_packet"
+		       " returns failure\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+	priv->stats.rx_bytes += skb->len;
+	priv->stats.rx_packets++;
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+
+	return (ret);
+}
+
+/**
+ *  @brief This function converts Tx/Rx rates from the Marvell WLAN format
+ *  (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s)
+ *  
+ *  @param rate    Input rate
+ *  @return 	   Output Rate (0 if invalid)
+ */
+static u8 convert_mv_rate_to_radiotap(u8 rate)
+{
+	switch (rate) {
+	case 0:		/*   1 Mbps */
+		return 2;
+	case 1:		/*   2 Mbps */
+		return 4;
+	case 2:		/* 5.5 Mbps */
+		return 11;
+	case 3:		/*  11 Mbps */
+		return 22;
+	case 4:		/*   6 Mbps */
+		return 12;
+	case 5:		/*   9 Mbps */
+		return 18;
+	case 6:		/*  12 Mbps */
+		return 24;
+	case 7:		/*  18 Mbps */
+		return 36;
+	case 8:		/*  24 Mbps */
+		return 48;
+	case 9:		/*  36 Mbps */
+		return 72;
+	case 10:		/*  48 Mbps */
+		return 96;
+	case 11:		/*  54 Mbps */
+		return 108;
+	}
+	PRINTM(MSG, "Invalid Marvell WLAN rate (%i)\n", rate);
+	return 0;
+}
+
+/**
+ *  @brief This function processes a received 802.11 packet and forwards it
+ *  to kernel/upper layer
+ *  
+ *  @param priv    A pointer to wlan_private
+ *  @param skb     A pointer to skb which includes the received packet
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int ProcessRxed_802_11_Packet(wlan_private * priv, struct sk_buff *skb)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	struct Rx80211PacketHdr *pRxPkt;
+	struct RxPD *pRxPD;
+	struct RxRadiotapHdr radiotap_hdr;
+	struct RxRadiotapHdr *pradiotap_hdr;
+
+	ENTER();
+
+	pRxPkt = (struct Rx80211PacketHdr *) skb->data;
+	pRxPD = &pRxPkt->rx_pd;
+
+	// HEXDUMP("RX Data: Before chop RxPD", skb->data, min(skb->len, 100));
+
+	if (skb->len < (ETH_HLEN + 8 + sizeof(struct RxPD))) {
+		PRINTM(INFO, "RX Error: FRAME RECEIVED WITH BAD LENGTH\n");
+		priv->stats.rx_length_errors++;
+		ret = WLAN_STATUS_SUCCESS;
+		goto done;
+	}
+
+	/* 
+	 * Check RxPD status and update 802.3 stat,
+	 */
+	if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK)) {
+		//PRINTM(INFO, "RX Error: frame received with bad status\n");
+		priv->stats.rx_errors++;
+	}
+
+	PRINTM(INFO, "RX Data: skb->len - sizeof(RxPd) = %d - %d = %d\n",
+	       skb->len, sizeof(struct RxPD), skb->len - sizeof(struct RxPD));
+
+	/* create the exported radio header */
+	switch (priv->adapter->radiomode) {
+	case WLAN_RADIOMODE_NONE:
+		/* no radio header */
+		/* chop the RxPD */
+		skb_pull(skb, sizeof(struct RxPD));
+		break;
+
+	case WLAN_RADIOMODE_RADIOTAP:
+		/* radiotap header */
+		radiotap_hdr.hdr.it_version = 0;
+		/* XXX must check this value for pad */
+		radiotap_hdr.hdr.it_pad = 0;
+		radiotap_hdr.hdr.it_len = sizeof(struct RxRadiotapHdr);
+		radiotap_hdr.hdr.it_present = RX_RADIOTAP_PRESENT;
+		/* unknown values */
+		radiotap_hdr.flags = 0;
+		radiotap_hdr.chan_freq = 0;
+		radiotap_hdr.chan_flags = 0;
+		radiotap_hdr.antenna = 0;
+		/* known values */
+		radiotap_hdr.rate = convert_mv_rate_to_radiotap(pRxPD->RxRate);
+		/* XXX must check no carryout */
+		radiotap_hdr.antsignal = pRxPD->SNR + pRxPD->NF;
+		radiotap_hdr.rx_flags = 0;
+		if (!(pRxPD->Status & MRVDRV_RXPD_STATUS_OK))
+			radiotap_hdr.rx_flags |= IEEE80211_RADIOTAP_F_RX_BADFCS;
+		//memset(radiotap_hdr.pad, 0x11, IEEE80211_RADIOTAP_HDRLEN - 18);
+
+		// HEXDUMP1("RX radiomode packet BEF: ", skb->data, min(skb->len, 100));
+
+		/* chop the RxPD */
+		skb_pull(skb, sizeof(struct RxPD));
+
+		/* add space for the new radio header */
+		if ((skb_headroom(skb) < sizeof(struct RxRadiotapHdr)) &&
+		    pskb_expand_head(skb, sizeof(struct RxRadiotapHdr), 0,
+				     GFP_ATOMIC)) {
+			PRINTM(MSG, "%s: couldn't pskb_expand_head\n",
+			       __func__);
+		}
+
+		pradiotap_hdr =
+		    (struct RxRadiotapHdr *)skb_push(skb,
+						     sizeof(struct
+							    RxRadiotapHdr));
+		memcpy(pradiotap_hdr, &radiotap_hdr,
+		       sizeof(struct RxRadiotapHdr));
+		//HEXDUMP1("RX radiomode packet AFT: ", skb->data, min(skb->len, 100));
+		break;
+
+	default:
+		/* unknown header */
+		PRINTM(MSG, "Unknown radiomode (%i)\n",
+		       priv->adapter->radiomode);
+		/* don't export any header */
+		/* chop the RxPD */
+		skb_pull(skb, sizeof(struct RxPD));
+		break;
+	}
+
+	/* Take the data rate from the RxPD structure 
+	 * only if the rate is auto
+	 */
+	if (Adapter->Is_DataRate_Auto) {
+		Adapter->DataRate = libertas_index_to_data_rate(pRxPD->RxRate);
+	}
+
+	wlan_compute_rssi(priv, pRxPD);
+
+	PRINTM(INFO, "RX Data: Size of actual packet = %d\n", skb->len);
+
+	if (libertas_upload_rx_packet(priv, skb)) {
+		PRINTM(INFO, "RX Error: libertas_upload_rx_packet "
+			"returns failure\n");
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	priv->stats.rx_bytes += skb->len;
+	priv->stats.rx_packets++;
+
+	ret = WLAN_STATUS_SUCCESS;
+      done:
+	LEAVE();
+
+	skb->protocol = __constant_htons(0x0019);	/* ETH_P_80211_RAW */
+
+	return (ret);
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_scan.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_scan.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_scan.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_scan.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,2337 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
+
+/** @file wlan_scan.c
+  *
+  * @brief Functions implementing wlan scan IOCTL and firmware command APIs
+  *
+  * IOCTL handlers as well as command preperation and response routines
+  *  for sending scan commands to the firmware.
+  *
+  * @sa wlan_scan.h
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change Log:
+    01/11/06: Initial revision. New scan code, relocate related functions
+    01/19/06: Update specific scan routines to discard old results for adhoc
+    01/31/06: Add support for selectively enabling the FW Scan channel filter
+
+************************************************************/
+
+#include <linux/ctype.h>
+#include <linux/if.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+
+#include <net/ieee80211.h>
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "wlan_decl.h"
+#include "wlan_dev.h"
+#include "wlan_scan.h"
+
+//! Approximate amount of data needed to pass a scan result back to iwlist
+#define MAX_SCAN_CELL_SIZE  (IW_EV_ADDR_LEN             \
+                             + MRVDRV_MAX_SSID_LENGTH   \
+                             + IW_EV_UINT_LEN           \
+                             + IW_EV_FREQ_LEN           \
+                             + IW_EV_QUAL_LEN           \
+                             + MRVDRV_MAX_SSID_LENGTH   \
+                             + IW_EV_PARAM_LEN          \
+                             + 40)	/* 40 for WPAIE */
+
+//! Memory needed to store a max sized Channel List TLV for a firmware scan
+#define CHAN_TLV_MAX_SIZE  (sizeof(struct MrvlIEtypesHeader)    \
+                            + (MRVDRV_MAX_CHANNELS_PER_SCAN     \
+                               * sizeof(struct ChanScanParamSet)))
+
+//! Memory needed to store a max number/size SSID TLV for a firmware scan
+#define SSID_TLV_MAX_SIZE  (1 * sizeof(struct MrvlIEtypes_SsIdParamSet))
+
+//! Maximum memory needed for a wlan_scan_cmd_config with all TLVs at max
+#define MAX_SCAN_CFG_ALLOC (sizeof(struct wlan_scan_cmd_config)  \
+                            + sizeof(struct MrvlIEtypes_NumProbes)   \
+                            + CHAN_TLV_MAX_SIZE                 \
+                            + SSID_TLV_MAX_SIZE)
+
+//! The maximum number of channels the firmware can scan per command
+#define MRVDRV_MAX_CHANNELS_PER_SCAN   14
+
+/**
+ * @brief Number of channels to scan per firmware scan command issuance.
+ *
+ *  Number restricted to prevent hitting the limit on the amount of scan data
+ *  returned in a single firmware scan command.
+ */
+#define MRVDRV_CHANNELS_PER_SCAN_CMD   4
+
+//! Scan time specified in the channel TLV for each channel for passive scans
+#define MRVDRV_PASSIVE_SCAN_CHAN_TIME  100
+
+//! Scan time specified in the channel TLV for each channel for active scans
+#define MRVDRV_ACTIVE_SCAN_CHAN_TIME   100
+
+//! Macro to enable/disable SSID checking before storing a scan table
+#ifdef DISCARD_BAD_SSID
+#define CHECK_SSID_IS_VALID(x) ssid_valid(&bssidEntry.Ssid)
+#else
+#define CHECK_SSID_IS_VALID(x) 1 
+#endif
+
+/**
+ * @brief Interally used to send a configured scan cmd between driver routines
+ */
+union wlan_scan_cmd_config_tlv {
+	struct wlan_scan_cmd_config config; //!< Scan configuration (variable length)
+	u8 configAllocBuf[MAX_SCAN_CFG_ALLOC]; //!< Max allocated block
+};
+
+/**
+ *  @brief Check if a scanned network compatible with the driver settings
+ *
+ *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
+ * enabled enabled  enabled   AES     mode   Privacy  WPA  WPA2  Compatible
+ *    0       0        0       0      NONE      0      0    0   yes No security
+ *    1       0        0       0      NONE      1      0    0   yes Static WEP
+ *    0       1        0       0       x        1x     1    x   yes WPA
+ *    0       0        1       0       x        1x     x    1   yes WPA2
+ *    0       0        0       1      NONE      1      0    0   yes Ad-hoc AES
+ *    0       0        0       0     !=NONE     1      0    0   yes Dynamic WEP
+ *
+ *
+ *  @param Adapter A pointer to wlan_adapter
+ *  @param index   Index in ScanTable to check against current driver settings
+ *  @param mode    Network mode: Infrastructure or IBSS
+ *
+ *  @return        Index in ScanTable, or error code if negative
+ */
+static int IsNetworkCompatible(wlan_adapter * Adapter, int index, int mode)
+{
+	ENTER();
+
+	if (Adapter->ScanTable[index].InfrastructureMode == mode) {
+		if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
+		    && !Adapter->SecInfo.WPAEnabled
+		    && !Adapter->SecInfo.WPA2Enabled
+		    && Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0] !=
+		    WPA_IE
+		    && Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0] !=
+		    WPA2_IE && Adapter->SecInfo.EncryptionMode == CIPHER_NONE
+		    && !Adapter->ScanTable[index].Privacy) {
+			/* no security */
+			LEAVE();
+			return index;
+		} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled
+			   && !Adapter->SecInfo.WPAEnabled
+			   && !Adapter->SecInfo.WPA2Enabled
+			   && Adapter->ScanTable[index].Privacy) {
+			/* static WEP enabled */
+			LEAVE();
+			return index;
+		} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
+			   && Adapter->SecInfo.WPAEnabled
+			   && !Adapter->SecInfo.WPA2Enabled
+			   && (Adapter->ScanTable[index].wpa_supplicant.
+			       Wpa_ie[0]
+			       == WPA_IE)
+			   /* Privacy bit may NOT be set in some APs like LinkSys WRT54G
+			      && Adapter->ScanTable[index].Privacy */
+		    ) {
+			/* WPA enabled */
+			PRINTM(INFO,
+			       "IsNetworkCompatible() WPA: index=%d wpa_ie=%#x "
+			       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+			       "privacy=%#x\n", index,
+			       Adapter->ScanTable[index].wpa_supplicant.
+			       Wpa_ie[0],
+			       Adapter->ScanTable[index].wpa2_supplicant.
+			       Wpa_ie[0],
+			       (Adapter->SecInfo.WEPStatus ==
+				Wlan802_11WEPEnabled) ? "e" : "d",
+			       (Adapter->SecInfo.WPAEnabled) ? "e" : "d",
+			       (Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
+			       Adapter->SecInfo.EncryptionMode,
+			       Adapter->ScanTable[index].Privacy);
+			LEAVE();
+			return index;
+		} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
+			   && !Adapter->SecInfo.WPAEnabled
+			   && Adapter->SecInfo.WPA2Enabled
+			   && (Adapter->ScanTable[index].wpa2_supplicant.
+			       Wpa_ie[0]
+			       == WPA2_IE)
+			   /* Privacy bit may NOT be set in some APs like LinkSys WRT54G
+			      && Adapter->ScanTable[index].Privacy */
+		    ) {
+			/* WPA2 enabled */
+			PRINTM(INFO,
+			       "IsNetworkCompatible() WPA2: index=%d wpa_ie=%#x "
+			       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
+			       "privacy=%#x\n", index,
+			       Adapter->ScanTable[index].wpa_supplicant.
+			       Wpa_ie[0],
+			       Adapter->ScanTable[index].wpa2_supplicant.
+			       Wpa_ie[0],
+			       (Adapter->SecInfo.WEPStatus ==
+				Wlan802_11WEPEnabled) ? "e" : "d",
+			       (Adapter->SecInfo.WPAEnabled) ? "e" : "d",
+			       (Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
+			       Adapter->SecInfo.EncryptionMode,
+			       Adapter->ScanTable[index].Privacy);
+			LEAVE();
+			return index;
+		} else if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPDisabled
+			   && !Adapter->SecInfo.WPAEnabled
+			   && !Adapter->SecInfo.WPA2Enabled
+			   && (Adapter->ScanTable[index].wpa_supplicant.
+			       Wpa_ie[0]
+			       != WPA_IE)
+			   && (Adapter->ScanTable[index].wpa2_supplicant.
+			       Wpa_ie[0]
+			       != WPA2_IE)
+			   && Adapter->SecInfo.EncryptionMode != CIPHER_NONE
+			   && Adapter->ScanTable[index].Privacy) {
+			/* dynamic WEP enabled */
+			PRINTM(INFO,
+			       "IsNetworkCompatible() dynamic WEP: index=%d "
+			       "wpa_ie=%#x wpa2_ie=%#x EncMode=%#x privacy=%#x\n",
+			       index,
+			       Adapter->ScanTable[index].wpa_supplicant.
+			       Wpa_ie[0],
+			       Adapter->ScanTable[index].wpa2_supplicant.
+			       Wpa_ie[0], Adapter->SecInfo.EncryptionMode,
+			       Adapter->ScanTable[index].Privacy);
+			LEAVE();
+			return index;
+		}
+
+		/* security doesn't match */
+		PRINTM(INFO,
+		       "IsNetworkCompatible() FAILED: index=%d wpa_ie=%#x "
+		       "wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
+		       index,
+		       Adapter->ScanTable[index].wpa_supplicant.Wpa_ie[0],
+		       Adapter->ScanTable[index].wpa2_supplicant.Wpa_ie[0],
+		       (Adapter->SecInfo.WEPStatus ==
+			Wlan802_11WEPEnabled) ? "e" : "d",
+		       (Adapter->SecInfo.WPAEnabled) ? "e" : "d",
+		       (Adapter->SecInfo.WPA2Enabled) ? "e" : "d",
+		       Adapter->SecInfo.EncryptionMode,
+		       Adapter->ScanTable[index].Privacy);
+		LEAVE();
+		return -ECONNREFUSED;
+	}
+
+	/* mode doesn't match */
+	LEAVE();
+	return -ENETUNREACH;
+}
+
+/**
+ *  @brief This function validates a SSID as being able to be printed
+ *
+ *  @param pSsid   SSID structure to validate
+ *
+ *  @return        TRUE or FALSE
+ */
+static u8 ssid_valid(struct WLAN_802_11_SSID *pSsid)
+{
+	int ssidIdx;
+
+	for (ssidIdx = 0; ssidIdx < pSsid->SsidLength; ssidIdx++) {
+		if (!isprint(pSsid->Ssid[ssidIdx])) {
+			return 0;
+		}
+	}
+
+	return 1;
+}
+
+/**
+ *  @brief Post process the scan table after a new scan command has completed
+ *
+ *  Inspect each entry of the scan table and try to find an entry that
+ *    matches our current associated/joined network from the scan.  If
+ *    one is found, update the stored copy of the BssDescriptor for our
+ *    current network.
+ *
+ *  Debug dump the current scan table contents if compiled accordingly.
+ *
+ *  @param priv   A pointer to wlan_private structure
+ *
+ *  @return       void
+ */
+static void wlan_scan_process_results(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int foundCurrent;
+	int i;
+
+	foundCurrent = 0;
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		/* try to find the current BSSID in the new scan list */
+		for (i = 0; i < Adapter->NumInScanTable; i++) {
+			if (!libertas_SSID_cmp(&Adapter->ScanTable[i].Ssid,
+				     &Adapter->CurBssParams.ssid) &&
+			    !memcmp(Adapter->CurBssParams.bssid,
+				    Adapter->ScanTable[i].MacAddress,
+				    ETH_ALEN)) {
+				foundCurrent = 1;
+			}
+		}
+
+		if (foundCurrent) {
+			/* Make a copy of current BSSID descriptor */
+			memcpy(&Adapter->CurBssParams.BSSDescriptor,
+			       &Adapter->ScanTable[i],
+			       sizeof(Adapter->CurBssParams.BSSDescriptor));
+		}
+	}
+
+	for (i = 0; i < Adapter->NumInScanTable; i++) {
+		PRINTM(INFO, "Scan:(%02d) %02x:%02x:%02x:%02x:%02x:%02x, "
+		       "RSSI[%03d], SSID[%s]\n",
+		       i,
+		       Adapter->ScanTable[i].MacAddress[0],
+		       Adapter->ScanTable[i].MacAddress[1],
+		       Adapter->ScanTable[i].MacAddress[2],
+		       Adapter->ScanTable[i].MacAddress[3],
+		       Adapter->ScanTable[i].MacAddress[4],
+		       Adapter->ScanTable[i].MacAddress[5],
+		       (s32) Adapter->ScanTable[i].Rssi,
+		       Adapter->ScanTable[i].Ssid.Ssid);
+	}
+}
+
+/**
+ *  @brief Create a channel list for the driver to scan based on region info
+ *
+ *  Use the driver region/band information to construct a comprehensive list
+ *    of channels to scan.  This routine is used for any scan that is not
+ *    provided a specific channel list to scan.
+ *
+ *  @param priv          A pointer to wlan_private structure
+ *  @param scanChanList  Output parameter: Resulting channel list to scan
+ *  @param filteredScan  Flag indicating whether or not a BSSID or SSID filter
+ *                       is being sent in the command to firmware.  Used to 
+ *                       increase the number of channels sent in a scan
+ *                       command and to disable the firmware channel scan
+ *                       filter.
+ *
+ *  @return              void
+ */
+static void wlan_scan_create_channel_list(wlan_private * priv,
+					  struct ChanScanParamSet * scanChanList,
+					  u8 filteredScan)
+{
+
+	wlan_adapter *Adapter = priv->adapter;
+	struct region_channel *scanRegion;
+	struct chan_freq_power *cfp;
+	int rgnIdx;
+	int chanIdx;
+	int nextChan;
+	u8 scanType;
+
+	chanIdx = 0;
+
+	/* Set the default scan type to the user specified type, will later
+	 *   be changed to passive on a per channel basis if restricted by
+	 *   regulatory requirements (11d or 11h)
+	 */
+	scanType = Adapter->ScanType;
+
+	for (rgnIdx = 0; rgnIdx < NELEMENTS(Adapter->region_channel); rgnIdx++) {
+		if (libertas_get_state_11d(priv) == ENABLE_11D &&
+		    Adapter->MediaConnectStatus != WlanMediaStateConnected) {
+			/* Scan all the supported chan for the first scan */
+			if (!Adapter->universal_channel[rgnIdx].Valid)
+				continue;
+			scanRegion = &Adapter->universal_channel[rgnIdx];
+
+			/* clear the parsed_region_chan for the first scan */
+			memset(&Adapter->parsed_region_chan, 0x00,
+			       sizeof(Adapter->parsed_region_chan));
+		} else {
+			if (!Adapter->region_channel[rgnIdx].Valid)
+				continue;
+			scanRegion = &Adapter->region_channel[rgnIdx];
+		}
+
+		for (nextChan = 0;
+		     nextChan < scanRegion->NrCFP; nextChan++, chanIdx++) {
+
+			cfp = scanRegion->CFP + nextChan;
+
+			if (libertas_get_state_11d(priv) == ENABLE_11D) {
+				scanType =
+				    libertas_get_scan_type_11d(cfp->Channel,
+							   &Adapter->
+							   parsed_region_chan);
+			}
+
+			switch (scanRegion->Band) {
+			case BAND_B:
+			case BAND_G:
+			default:
+				scanChanList[chanIdx].RadioType =
+				    HostCmd_SCAN_RADIO_TYPE_BG;
+				break;
+			}
+
+			if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
+				scanChanList[chanIdx].MaxScanTime =
+				    wlan_cpu_to_le16
+				    (MRVDRV_PASSIVE_SCAN_CHAN_TIME);
+				scanChanList[chanIdx].ChanScanMode.PassiveScan =
+				    1;
+			} else {
+				scanChanList[chanIdx].MaxScanTime =
+				    wlan_cpu_to_le16
+				    (MRVDRV_ACTIVE_SCAN_CHAN_TIME);
+				scanChanList[chanIdx].ChanScanMode.PassiveScan =
+				    0;
+			}
+
+			scanChanList[chanIdx].ChanNumber = cfp->Channel;
+
+			if (filteredScan) {
+				scanChanList[chanIdx].ChanScanMode.
+				    DisableChanFilt = 1;
+			}
+		}
+	}
+}
+
+/**
+ *  @brief Construct a wlan_scan_cmd_config structure to use in issue scan cmds
+ *
+ *  Application layer or other functions can invoke wlan_scan_networks
+ *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
+ *    This structure is used as the basis of one or many wlan_scan_cmd_config
+ *    commands that are sent to the command processing module and sent to
+ *    firmware.
+ *
+ *  Create a wlan_scan_cmd_config based on the following user supplied
+ *    parameters (if present):
+ *             - SSID filter
+ *             - BSSID filter
+ *             - Number of Probes to be sent
+ *             - Channel list
+ *
+ *  If the SSID or BSSID filter is not present, disable/clear the filter.
+ *  If the number of probes is not set, use the adapter default setting
+ *  Qualify the channel
+ *
+ *  @param priv             A pointer to wlan_private structure
+ *  @param pUserScanIn      NULL or pointer to scan configuration parameters
+ *  @param pScanCfgOut      Output parameter: Resulting scan configuration
+ *  @param ppChanTlvOut     Output parameter: Pointer to the start of the
+ *                          channel TLV portion of the output scan config
+ *  @param pScanChanList    Output parameter: Pointer to the resulting channel
+ *                          list to scan
+ *  @param pMaxChanPerScan  Output parameter: Number of channels to scan for
+ *                          each issuance of the firmware scan command
+ *  @param pFilteredScan    Output parameter: Flag indicating whether or not
+ *                          a BSSID or SSID filter is being sent in the
+ *                          command to firmware.  Used to increase the number
+ *                          of channels sent in a scan command and to 
+ *                          disable the firmware channel scan filter.
+ *  @param pScanCurrentOnly Output parameter: Flag indicating whether or not
+ *                          we are only scanning our current active channel
+ *
+ *  @return                 void
+ */
+static
+void wlan_scan_setup_scan_config(wlan_private * priv,
+				 const struct wlan_ioctl_user_scan_cfg * pUserScanIn,
+				 struct wlan_scan_cmd_config * pScanCfgOut,
+				 struct MrvlIEtypes_ChanListParamSet ** ppChanTlvOut,
+				 struct ChanScanParamSet * pScanChanList,
+				 int *pMaxChanPerScan,
+				 u8 * pFilteredScan, u8 * pScanCurrentOnly)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	const u8 zeroMac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
+	struct MrvlIEtypes_NumProbes *pNumProbesTlv;
+	struct MrvlIEtypes_SsIdParamSet *pSsidTlv;
+	u8 *pTlvPos;
+	u16 numProbes;
+	u16 ssidLen;
+	int chanIdx;
+	int scanType;
+	int scanDur;
+	int channel;
+	int radioType;
+
+	/* The tlvBufferLen is calculated for each scan command.  The TLVs added
+	 *   in this routine will be preserved since the routine that sends
+	 *   the command will append channelTLVs at *ppChanTlvOut.  The difference
+	 *   between the *ppChanTlvOut and the tlvBuffer start will be used
+	 *   to calculate the size of anything we add in this routine.
+	 */
+	pScanCfgOut->tlvBufferLen = 0;
+
+	/* Running tlv pointer.  Assigned to ppChanTlvOut at end of function
+	 *  so later routines know where channels can be added to the command buf
+	 */
+	pTlvPos = pScanCfgOut->tlvBuffer;
+
+	/*
+	 * Set the initial scan paramters for progressive scanning.  If a specific
+	 *   BSSID or SSID is used, the number of channels in the scan command
+	 *   will be increased to the absolute maximum
+	 */
+	*pMaxChanPerScan = MRVDRV_CHANNELS_PER_SCAN_CMD;
+
+	/* Initialize the scan as un-filtered by firmware, set to TRUE below if
+	 *   a SSID or BSSID filter is sent in the command
+	 */
+	*pFilteredScan = 0; 
+
+	/* Initialize the scan as not being only on the current channel.  If
+	 *   the channel list is customized, only contains one channel, and
+	 *   is the active channel, this is set true and data flow is not halted.
+	 */
+	*pScanCurrentOnly = 0;
+
+	if (pUserScanIn) {
+
+		/* Set the bss type scan filter, use Adapter setting if unset */
+		pScanCfgOut->bssType =
+		    (pUserScanIn->bssType ? pUserScanIn->bssType : Adapter->
+		     ScanMode);
+
+		/* Set the number of probes to send, use Adapter setting if unset */
+		numProbes = (pUserScanIn->numProbes ? pUserScanIn->numProbes :
+			     Adapter->ScanProbes);
+
+		/*
+		 * Set the BSSID filter to the incoming configuration,
+		 *   if non-zero.  If not set, it will remain disabled (all zeros).
+		 */
+		memcpy(pScanCfgOut->specificBSSID,
+		       pUserScanIn->specificBSSID,
+		       sizeof(pScanCfgOut->specificBSSID));
+
+		ssidLen = strlen(pUserScanIn->specificSSID);
+
+		if (ssidLen) {
+			pSsidTlv =
+			    (struct MrvlIEtypes_SsIdParamSet *) pScanCfgOut->
+			    tlvBuffer;
+			pSsidTlv->Header.Type = wlan_cpu_to_le16(TLV_TYPE_SSID);
+			pSsidTlv->Header.Len = wlan_cpu_to_le16(ssidLen);
+			memcpy(pSsidTlv->SsId, pUserScanIn->specificSSID,
+			       ssidLen);
+			pTlvPos += sizeof(pSsidTlv->Header) + ssidLen;
+		}
+
+		/*
+		 *  The default number of channels sent in the command is low to
+		 *    ensure the response buffer from the firmware does not truncate
+		 *    scan results.  That is not an issue with an SSID or BSSID
+		 *    filter applied to the scan results in the firmware.
+		 */
+		if (ssidLen || (memcmp(pScanCfgOut->specificBSSID,
+				       &zeroMac, sizeof(zeroMac)) != 0)) {
+			*pMaxChanPerScan = MRVDRV_MAX_CHANNELS_PER_SCAN;
+			*pFilteredScan = 1;
+		}
+	} else {
+		pScanCfgOut->bssType = Adapter->ScanMode;
+		numProbes = Adapter->ScanProbes;
+	}
+
+	/* If the input config or adapter has the number of Probes set, add tlv */
+	if (numProbes) {
+		pNumProbesTlv = (struct MrvlIEtypes_NumProbes *) pTlvPos;
+		pNumProbesTlv->Header.Type =
+		    wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
+		pNumProbesTlv->Header.Len = sizeof(pNumProbesTlv->NumProbes);
+		pNumProbesTlv->NumProbes = wlan_cpu_to_le16(numProbes);
+
+		pTlvPos +=
+		    sizeof(pNumProbesTlv->Header) + pNumProbesTlv->Header.Len;
+
+		pNumProbesTlv->Header.Len =
+		    wlan_cpu_to_le16(pNumProbesTlv->Header.Len);
+	}
+
+	/*
+	 * Set the output for the channel TLV to the address in the tlv buffer
+	 *   past any TLVs that were added in this fuction (SSID, numProbes).
+	 *   Channel TLVs will be added past this for each scan command, preserving
+	 *   the TLVs that were previously added.
+	 */
+	*ppChanTlvOut = (struct MrvlIEtypes_ChanListParamSet *) pTlvPos;
+
+	if (pUserScanIn && pUserScanIn->chanList[0].chanNumber) {
+
+		PRINTM(INFO, "Scan: Using supplied channel list\n");
+
+		for (chanIdx = 0;
+		     chanIdx < WLAN_IOCTL_USER_SCAN_CHAN_MAX
+		     && pUserScanIn->chanList[chanIdx].chanNumber; chanIdx++) {
+
+			channel = pUserScanIn->chanList[chanIdx].chanNumber;
+			(pScanChanList + chanIdx)->ChanNumber = channel;
+
+			radioType = pUserScanIn->chanList[chanIdx].radioType;
+			(pScanChanList + chanIdx)->RadioType = radioType;
+
+			scanType = pUserScanIn->chanList[chanIdx].scanType;
+
+			if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
+				(pScanChanList +
+				 chanIdx)->ChanScanMode.PassiveScan = 1;
+			} else {
+				(pScanChanList +
+				 chanIdx)->ChanScanMode.PassiveScan = 0;
+			}
+
+			if (pUserScanIn->chanList[chanIdx].scanTime) {
+				scanDur =
+				    pUserScanIn->chanList[chanIdx].scanTime;
+			} else {
+				if (scanType == HostCmd_SCAN_TYPE_PASSIVE) {
+					scanDur = MRVDRV_PASSIVE_SCAN_CHAN_TIME;
+				} else {
+					scanDur = MRVDRV_ACTIVE_SCAN_CHAN_TIME;
+				}
+			}
+
+			(pScanChanList + chanIdx)->MinScanTime =
+			    wlan_cpu_to_le16(scanDur);
+			(pScanChanList + chanIdx)->MaxScanTime =
+			    wlan_cpu_to_le16(scanDur);
+		}
+
+		/* Check if we are only scanning the current channel */
+		if ((chanIdx == 1) && (pUserScanIn->chanList[0].chanNumber
+				       ==
+				       priv->adapter->CurBssParams.channel)) {
+			*pScanCurrentOnly = 1;
+			PRINTM(INFO, "Scan: Scanning current channel only");
+		}
+
+	} else {
+		PRINTM(INFO, "Scan: Creating full region channel list\n");
+		wlan_scan_create_channel_list(priv, pScanChanList,
+					      *pFilteredScan);
+	}
+}
+
+/**
+ *  @brief Construct and send multiple scan config commands to the firmware
+ *
+ *  Previous routines have created a wlan_scan_cmd_config with any requested
+ *   TLVs.  This function splits the channel TLV into maxChanPerScan lists
+ *   and sends the portion of the channel TLV along with the other TLVs
+ *   to the wlan_cmd routines for execution in the firmware.
+ *
+ *  @param priv            A pointer to wlan_private structure
+ *  @param maxChanPerScan  Maximum number channels to be included in each
+ *                         scan command sent to firmware
+ *  @param filteredScan    Flag indicating whether or not a BSSID or SSID
+ *                         filter is being used for the firmware command
+ *                         scan command sent to firmware
+ *  @param pScanCfgOut     Scan configuration used for this scan.
+ *  @param pChanTlvOut     Pointer in the pScanCfgOut where the channel TLV
+ *                         should start.  This is past any other TLVs that
+ *                         must be sent down in each firmware command.
+ *  @param pScanChanList   List of channels to scan in maxChanPerScan segments
+ *
+ *  @return                WLAN_STATUS_SUCCESS or error return otherwise
+ */
+static int wlan_scan_channel_list(wlan_private * priv,
+				  int maxChanPerScan,
+				  u8 filteredScan,
+				  struct wlan_scan_cmd_config * pScanCfgOut,
+				  struct MrvlIEtypes_ChanListParamSet * pChanTlvOut,
+				  struct ChanScanParamSet * pScanChanList)
+{
+	struct ChanScanParamSet *pTmpChan;
+	struct ChanScanParamSet *pStartChan;
+	u8 scanBand;
+	int doneEarly;
+	int tlvIdx;
+	int ret;
+
+	ENTER();
+
+	if (pScanCfgOut == 0 || pChanTlvOut == 0 || pScanChanList == 0) {
+		PRINTM(INFO, "Scan: Null detect: %p, %p, %p\n",
+		       pScanCfgOut, pChanTlvOut, pScanChanList);
+		return WLAN_STATUS_FAILURE;
+	}
+
+	ret = WLAN_STATUS_SUCCESS;
+
+	pChanTlvOut->Header.Type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
+
+	/* Set the temp channel struct pointer to the start of the desired list */
+	pTmpChan = pScanChanList;
+
+	/* Loop through the desired channel list, sending a new firmware scan
+	 *   commands for each maxChanPerScan channels (or for 1,6,11 individually
+	 *   if configured accordingly)
+	 */
+	while (pTmpChan->ChanNumber) {
+
+		tlvIdx = 0;
+		pChanTlvOut->Header.Len = 0;
+		scanBand = pTmpChan->RadioType;
+		pStartChan = pTmpChan;
+		doneEarly = 0;
+
+		/* Construct the Channel TLV for the scan command.  Continue to
+		 *  insert channel TLVs until:
+		 *    - the tlvIdx hits the maximum configured per scan command
+		 *    - the next channel to insert is 0 (end of desired channel list)
+		 *    - doneEarly is set (controlling individual scanning of 1,6,11)
+		 */
+		while (tlvIdx < maxChanPerScan && pTmpChan->ChanNumber
+		       && !doneEarly) {
+
+			PRINTM(INFO,
+			       "Scan: Chan(%3d), Radio(%d), Mode(%d,%d), Dur(%d)\n",
+			       pTmpChan->ChanNumber, pTmpChan->RadioType,
+			       pTmpChan->ChanScanMode.PassiveScan,
+			       pTmpChan->ChanScanMode.DisableChanFilt,
+			       pTmpChan->MaxScanTime);
+
+			/* Copy the current channel TLV to the command being prepared */
+			memcpy(pChanTlvOut->ChanScanParam + tlvIdx,
+			       pTmpChan, sizeof(pChanTlvOut->ChanScanParam));
+
+			/* Increment the TLV header length by the size appended */
+			pChanTlvOut->Header.Len +=
+			    sizeof(pChanTlvOut->ChanScanParam);
+
+			/*
+			 *  The tlv buffer length is set to the number of bytes of the
+			 *    between the channel tlv pointer and the start of the
+			 *    tlv buffer.  This compensates for any TLVs that were appended
+			 *    before the channel list.
+			 */
+			pScanCfgOut->tlvBufferLen = ((u8 *) pChanTlvOut
+						     - pScanCfgOut->tlvBuffer);
+
+			/*  Add the size of the channel tlv header and the data length */
+			pScanCfgOut->tlvBufferLen +=
+			    (sizeof(pChanTlvOut->Header)
+			     + pChanTlvOut->Header.Len);
+
+			/* Increment the index to the channel tlv we are constructing */
+			tlvIdx++;
+
+			doneEarly = 0;
+
+			/* Stop the loop if the *current* channel is in the 1,6,11 set
+			 *   and we are not filtering on a BSSID or SSID.
+			 */
+			if (!filteredScan && (pTmpChan->ChanNumber == 1
+					      || pTmpChan->ChanNumber == 6
+					      || pTmpChan->ChanNumber == 11)) {
+				doneEarly = 1;
+			}
+
+			/* Increment the tmp pointer to the next channel to be scanned */
+			pTmpChan++;
+
+			/* Stop the loop if the *next* channel is in the 1,6,11 set.
+			 *  This will cause it to be the only channel scanned on the next
+			 *  interation
+			 */
+			if (!filteredScan && (pTmpChan->ChanNumber == 1
+					      || pTmpChan->ChanNumber == 6
+					      || pTmpChan->ChanNumber == 11)) {
+				doneEarly = 1;
+			}
+		}
+
+		/* Send the scan command to the firmware with the specified cfg */
+		ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SCAN, 0,
+					    HostCmd_OPTION_WAITFORRSP, 0,
+					    pScanCfgOut);
+	}
+
+	LEAVE();
+
+	if (ret) {
+		return WLAN_STATUS_FAILURE;
+	}
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Internal function used to start a scan based on an input config
+ *
+ *  Use the input user scan configuration information when provided in
+ *    order to send the appropriate scan commands to firmware to populate or
+ *    update the internal driver scan table
+ *
+ *  @param priv          A pointer to wlan_private structure
+ *  @param pUserScanIn   Pointer to the input configuration for the requested
+ *                       scan.
+ *
+ *  @return              WLAN_STATUS_SUCCESS or < 0 if error
+ */
+static int wlan_scan_networks(wlan_private * priv,
+			      const struct wlan_ioctl_user_scan_cfg * pUserScanIn)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct MrvlIEtypes_ChanListParamSet *pChanTlvOut;
+
+	struct ChanScanParamSet scanChanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+	union wlan_scan_cmd_config_tlv scanCfgOut;
+	u8 keepPreviousScan;
+	u8 filteredScan;
+	u8 scanCurrentChanOnly;
+	int maxChanPerScan;
+	int ret;
+
+	ENTER();
+
+	memset(scanChanList, 0x00, sizeof(scanChanList));
+	memset(&scanCfgOut, 0x00, sizeof(scanCfgOut));
+
+	keepPreviousScan = 0;
+
+	wlan_scan_setup_scan_config(priv,
+				    pUserScanIn,
+				    &scanCfgOut.config,
+				    &pChanTlvOut,
+				    scanChanList,
+				    &maxChanPerScan,
+				    &filteredScan, &scanCurrentChanOnly);
+
+	if (pUserScanIn) {
+		keepPreviousScan = pUserScanIn->keepPreviousScan;
+	}
+
+	if (!keepPreviousScan) {
+		memset(Adapter->ScanTable, 0x00,
+		       sizeof(struct bss_descriptor) * MRVDRV_MAX_BSSID_LIST);
+		Adapter->NumInScanTable = 0;
+	}
+
+	/* Keep the data path active if we are only scanning our current channel */
+	if (!scanCurrentChanOnly) {
+		netif_stop_queue(priv->wlan_dev.netdev);
+		netif_carrier_off(priv->wlan_dev.netdev);
+	}
+
+	ret = wlan_scan_channel_list(priv,
+				     maxChanPerScan,
+				     filteredScan,
+				     &scanCfgOut.config,
+				     pChanTlvOut, scanChanList);
+
+	/*  Process the resulting scan table:
+	 *    - Remove any bad ssids
+	 *    - Update our current BSS information from scan data
+	 */
+	wlan_scan_process_results(priv);
+
+	if (priv->adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		netif_carrier_on(priv->wlan_dev.netdev);
+		netif_wake_queue(priv->wlan_dev.netdev);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Create a brief scan resp to relay basic BSS info to the app layer
+ *
+ *  When the beacon/probe response has not been buffered, use the fixed field
+ *    information available to provide a minimum response for the application
+ *    ioctl retrieval routines.
+ *
+ *  @param ppBuffer  Output parameter: Buffer used to create basic scan rsp
+ *  @param pBssDesc  Pointer to a BSS entry in the scan table to create
+ *                   scan response from for delivery to the application layer
+ *
+ *  @return          void
+ */
+static void wlan_scan_create_brief_scan_table(u8 ** ppBuffer,
+					      struct bss_descriptor * pBssDesc)
+{
+	u8 *pTmpBuf = *ppBuffer;
+	u8 tmpSSIDHdr[2];
+
+	if (copy_to_user
+	    (pTmpBuf, pBssDesc->TimeStamp, sizeof(pBssDesc->TimeStamp))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return;
+	}
+	pTmpBuf += sizeof(pBssDesc->TimeStamp);
+
+	if (copy_to_user(pTmpBuf, &pBssDesc->BeaconPeriod,
+			 sizeof(pBssDesc->BeaconPeriod))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return;
+	}
+	pTmpBuf += sizeof(pBssDesc->BeaconPeriod);
+
+	if (copy_to_user(pTmpBuf, &pBssDesc->Cap, sizeof(pBssDesc->Cap))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return;
+	}
+	pTmpBuf += sizeof(pBssDesc->Cap);
+
+	tmpSSIDHdr[0] = 0;	/* Element ID for SSID is zero */
+	tmpSSIDHdr[1] = pBssDesc->Ssid.SsidLength;
+	if (copy_to_user(pTmpBuf, tmpSSIDHdr, sizeof(tmpSSIDHdr))) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return;
+	}
+	pTmpBuf += sizeof(tmpSSIDHdr);
+
+	if (copy_to_user(pTmpBuf, pBssDesc->Ssid.Ssid,
+			 pBssDesc->Ssid.SsidLength)) {
+		PRINTM(INFO, "Copy to user failed\n");
+		return;
+	}
+	pTmpBuf += pBssDesc->Ssid.SsidLength;
+
+	*ppBuffer = pTmpBuf;
+}
+
+/**
+ *  @brief Inspect the scan response buffer for pointers to expected TLVs
+ *
+ *  TLVs can be included at the end of the scan response BSS information.
+ *    Parse the data in the buffer for pointers to TLVs that can potentially
+ *    be passed back in the response
+ *
+ *  @param pTlv        Pointer to the start of the TLV buffer to parse
+ *  @param tlvBufSize  Size of the TLV buffer
+ *  @param pTsfTlv     Output parameter: Pointer to the TSF TLV if found
+ *
+ *  @return            void
+ */
+static
+void wlan_ret_802_11_scan_get_tlv_ptrs(struct MrvlIEtypes_Data * pTlv,
+				       int tlvBufSize,
+				       struct MrvlIEtypes_TsfTimestamp ** pTsfTlv)
+{
+	struct MrvlIEtypes_Data *pCurrentTlv;
+	int tlvBufLeft;
+	u16 tlvType;
+	u16 tlvLen;
+
+	pCurrentTlv = pTlv;
+	tlvBufLeft = tlvBufSize;
+	*pTsfTlv = NULL;
+
+	PRINTM(INFO, "SCAN_RESP: tlvBufSize = %d\n", tlvBufSize);
+	HEXDUMP("SCAN_RESP: TLV Buf", (u8 *) pTlv, tlvBufSize);
+
+	while (tlvBufLeft >= sizeof(struct MrvlIEtypesHeader)) {
+		tlvType = wlan_le16_to_cpu(pCurrentTlv->Header.Type);
+		tlvLen = wlan_le16_to_cpu(pCurrentTlv->Header.Len);
+
+		switch (tlvType) {
+		case TLV_TYPE_TSFTIMESTAMP:
+			*pTsfTlv = (struct MrvlIEtypes_TsfTimestamp *) pCurrentTlv;
+			break;
+
+		default:
+			PRINTM(INFO, "SCAN_RESP: Unhandled TLV = %d\n",
+			       tlvType);
+			/* Give up, this seems corrupted */
+			return;
+		}		/* switch */
+
+		tlvBufLeft -= (sizeof(pTlv->Header) + tlvLen);
+		pCurrentTlv =
+		    (struct MrvlIEtypes_Data *) (pCurrentTlv->Data + tlvLen);
+	}			/* while */
+}
+
+/**
+ *  @brief Interpret a BSS scan response returned from the firmware
+ *
+ *  Parse the various fixed fields and IEs passed back for a a BSS probe
+ *   response or beacon from the scan command.  Record information as needed
+ *   in the scan table struct bss_descriptor for that entry.
+ *
+ *  @param pBSSIDEntry  Output parameter: Pointer to the BSS Entry
+ *
+ *  @return             WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int InterpretBSSDescriptionWithIE(struct bss_descriptor * pBSSEntry,
+					 u8 ** pBeaconInfo, int *bytesLeft)
+{
+	enum IEEEtypes_ElementId elemID;
+	struct IEEEtypes_FhParamSet *pFH;
+	struct IEEEtypes_DsParamSet *pDS;
+	struct IEEEtypes_CfParamSet *pCF;
+	struct IEEEtypes_IbssParamSet *pIbss;
+	struct IEEEtypes_CapInfo *pCap;
+	struct WLAN_802_11_FIXED_IEs fixedIE;
+	u8 *pCurrentPtr;
+	u8 *pRate;
+	u8 elemLen;
+	u8 bytesToCopy;
+	u8 rateSize;
+	u16 beaconSize;
+	u8 foundDataRateIE;
+	int bytesLeftForCurrentBeacon;
+
+	struct WPA_SUPPLICANT *pwpa_supplicant;
+	struct WPA_SUPPLICANT *pwpa2_supplicant;
+	struct IE_WPA *pIe;
+	const u8 oui01[4] = { 0x00, 0x50, 0xf2, 0x01 };
+
+	struct IEEEtypes_CountryInfoSet *pcountryinfo;
+
+	ENTER();
+
+	foundDataRateIE = 0;
+	rateSize = 0;
+	beaconSize = 0;
+
+	if (*bytesLeft >= sizeof(beaconSize)) {
+		/* Extract & convert beacon size from the command buffer */
+		memcpy(&beaconSize, *pBeaconInfo, sizeof(beaconSize));
+		beaconSize = wlan_le16_to_cpu(beaconSize);
+		*bytesLeft -= sizeof(beaconSize);
+		*pBeaconInfo += sizeof(beaconSize);
+	}
+
+	if (beaconSize == 0 || beaconSize > *bytesLeft) {
+
+		*pBeaconInfo += *bytesLeft;
+		*bytesLeft = 0;
+
+		return WLAN_STATUS_FAILURE;
+	}
+
+	/* Initialize the current working beacon pointer for this BSS iteration */
+	pCurrentPtr = *pBeaconInfo;
+
+	/* Advance the return beacon pointer past the current beacon */
+	*pBeaconInfo += beaconSize;
+	*bytesLeft -= beaconSize;
+
+	bytesLeftForCurrentBeacon = beaconSize;
+
+	pwpa_supplicant = &pBSSEntry->wpa_supplicant;
+	pwpa2_supplicant = &pBSSEntry->wpa2_supplicant;
+
+	memcpy(pBSSEntry->MacAddress, pCurrentPtr, ETH_ALEN);
+	PRINTM(INFO, "InterpretIE: AP MAC Addr-%x:%x:%x:%x:%x:%x\n",
+	       pBSSEntry->MacAddress[0], pBSSEntry->MacAddress[1],
+	       pBSSEntry->MacAddress[2], pBSSEntry->MacAddress[3],
+	       pBSSEntry->MacAddress[4], pBSSEntry->MacAddress[5]);
+
+	pCurrentPtr += ETH_ALEN;
+	bytesLeftForCurrentBeacon -= ETH_ALEN;
+
+	if (bytesLeftForCurrentBeacon < 12) {
+		PRINTM(INFO, "InterpretIE: Not enough bytes left\n");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	/*
+	 * next 4 fields are RSSI, time stamp, beacon interval,
+	 *   and capability information
+	 */
+
+	/* RSSI is 1 byte long */
+	pBSSEntry->Rssi = wlan_le32_to_cpu((long)(*pCurrentPtr));
+	PRINTM(INFO, "InterpretIE: RSSI=%02X\n", *pCurrentPtr);
+	pCurrentPtr += 1;
+	bytesLeftForCurrentBeacon -= 1;
+
+	/* time stamp is 8 bytes long */
+	memcpy(fixedIE.Timestamp, pCurrentPtr, 8);
+	memcpy(pBSSEntry->TimeStamp, pCurrentPtr, 8);
+	pCurrentPtr += 8;
+	bytesLeftForCurrentBeacon -= 8;
+
+	/* beacon interval is 2 bytes long */
+	memcpy(&fixedIE.BeaconInterval, pCurrentPtr, 2);
+	pBSSEntry->BeaconPeriod = wlan_le16_to_cpu(fixedIE.BeaconInterval);
+	pCurrentPtr += 2;
+	bytesLeftForCurrentBeacon -= 2;
+
+	/* capability information is 2 bytes long */
+	memcpy(&fixedIE.Capabilities, pCurrentPtr, 2);
+	PRINTM(INFO, "InterpretIE: fixedIE.Capabilities=0x%X\n",
+	       fixedIE.Capabilities);
+	fixedIE.Capabilities = wlan_le16_to_cpu(fixedIE.Capabilities);
+	pCap = (struct IEEEtypes_CapInfo *) & fixedIE.Capabilities;
+	memcpy(&pBSSEntry->Cap, pCap, sizeof(struct IEEEtypes_CapInfo));
+	pCurrentPtr += 2;
+	bytesLeftForCurrentBeacon -= 2;
+
+	/* rest of the current buffer are IE's */
+	PRINTM(INFO, "InterpretIE: IELength for this AP = %d\n",
+	       bytesLeftForCurrentBeacon);
+
+	HEXDUMP("InterpretIE: IE info", (u8 *) pCurrentPtr,
+		bytesLeftForCurrentBeacon);
+
+	if (pCap->Privacy) {
+		PRINTM(INFO, "InterpretIE: AP WEP enabled\n");
+		pBSSEntry->Privacy = Wlan802_11PrivFilter8021xWEP;
+	} else {
+		pBSSEntry->Privacy = Wlan802_11PrivFilterAcceptAll;
+	}
+
+	if (pCap->Ibss == 1) {
+		pBSSEntry->InfrastructureMode = Wlan802_11IBSS;
+	} else {
+		pBSSEntry->InfrastructureMode = Wlan802_11Infrastructure;
+	}
+
+	/* process variable IE */
+	while (bytesLeftForCurrentBeacon >= 2) {
+		elemID = (enum IEEEtypes_ElementId) (*((u8 *) pCurrentPtr));
+		elemLen = *((u8 *) pCurrentPtr + 1);
+
+		if (bytesLeftForCurrentBeacon < elemLen) {
+			PRINTM(INFO, "InterpretIE: Error in processing IE, "
+			       "bytes left < IE length\n");
+			bytesLeftForCurrentBeacon = 0;
+			continue;
+		}
+
+		switch (elemID) {
+
+		case SSID:
+			pBSSEntry->Ssid.SsidLength = elemLen;
+			memcpy(pBSSEntry->Ssid.Ssid, (pCurrentPtr + 2),
+			       elemLen);
+			PRINTM(INFO, "Ssid: %32s", pBSSEntry->Ssid.Ssid);
+			break;
+
+		case SUPPORTED_RATES:
+			memcpy(pBSSEntry->DataRates, (pCurrentPtr + 2),
+			       elemLen);
+			memmove(pBSSEntry->libertas_supported_rates, (pCurrentPtr + 2),
+				elemLen);
+			rateSize = elemLen;
+			foundDataRateIE = 1;
+			break;
+
+		case EXTRA_IE:
+			PRINTM(INFO, "InterpretIE: EXTRA_IE Found!\n");
+			pBSSEntry->extra_ie = 1;
+			break;
+
+		case FH_PARAM_SET:
+			pFH = (struct IEEEtypes_FhParamSet *) pCurrentPtr;
+			pBSSEntry->NetworkTypeInUse = Wlan802_11FH;
+			memmove(&pBSSEntry->PhyParamSet.FhParamSet, pFH,
+				sizeof(struct IEEEtypes_FhParamSet));
+			pBSSEntry->PhyParamSet.FhParamSet.DwellTime
+			    =
+			    wlan_le16_to_cpu(pBSSEntry->PhyParamSet.FhParamSet.
+					     DwellTime);
+			break;
+
+		case DS_PARAM_SET:
+			pDS = (struct IEEEtypes_DsParamSet *) pCurrentPtr;
+
+			pBSSEntry->NetworkTypeInUse = Wlan802_11DS;
+			pBSSEntry->Channel = pDS->CurrentChan;
+
+			memcpy(&pBSSEntry->PhyParamSet.DsParamSet, pDS,
+			       sizeof(struct IEEEtypes_DsParamSet));
+			break;
+
+		case CF_PARAM_SET:
+			pCF = (struct IEEEtypes_CfParamSet *) pCurrentPtr;
+
+			memcpy(&pBSSEntry->SsParamSet.CfParamSet, pCF,
+			       sizeof(struct IEEEtypes_CfParamSet));
+			break;
+
+		case IBSS_PARAM_SET:
+			pIbss = (struct IEEEtypes_IbssParamSet *) pCurrentPtr;
+			pBSSEntry->ATIMWindow =
+			    wlan_le32_to_cpu(pIbss->AtimWindow);
+
+			memmove(&pBSSEntry->SsParamSet.IbssParamSet, pIbss,
+				sizeof(struct IEEEtypes_IbssParamSet));
+
+			pBSSEntry->SsParamSet.IbssParamSet.AtimWindow
+			    =
+			    wlan_le16_to_cpu(pBSSEntry->SsParamSet.IbssParamSet.
+					     AtimWindow);
+			break;
+
+			/* Handle Country Info IE */
+		case COUNTRY_INFO:
+			pcountryinfo =
+			    (struct IEEEtypes_CountryInfoSet *) pCurrentPtr;
+
+			if (pcountryinfo->Len <
+			    sizeof(pcountryinfo->CountryCode)
+			    || pcountryinfo->Len > 254) {
+				PRINTM(INFO, "InterpretIE: 11D- Err "
+				       "CountryInfo len =%d min=%d max=254\n",
+				       pcountryinfo->Len,
+				       sizeof(pcountryinfo->CountryCode));
+				LEAVE();
+				return WLAN_STATUS_FAILURE;
+			}
+
+			memcpy(&pBSSEntry->CountryInfo,
+			       pcountryinfo, pcountryinfo->Len + 2);
+			HEXDUMP("InterpretIE: 11D- CountryInfo:",
+				(u8 *) pcountryinfo,
+				(u32) (pcountryinfo->Len + 2));
+			break;
+
+		case EXTENDED_SUPPORTED_RATES:
+			/*
+			 * only process extended supported rate
+			 * if data rate is already found.
+			 * data rate IE should come before
+			 * extended supported rate IE
+			 */
+			if (foundDataRateIE) {
+				if ((elemLen + rateSize) > WLAN_SUPPORTED_RATES) {
+					bytesToCopy =
+					    (WLAN_SUPPORTED_RATES - rateSize);
+				} else {
+					bytesToCopy = elemLen;
+				}
+
+				pRate = (u8 *) pBSSEntry->DataRates;
+				pRate += rateSize;
+				memmove(pRate, (pCurrentPtr + 2), bytesToCopy);
+
+				pRate = (u8 *) pBSSEntry->libertas_supported_rates;
+
+				pRate += rateSize;
+				memmove(pRate, (pCurrentPtr + 2), bytesToCopy);
+			}
+			break;
+
+		case VENDOR_SPECIFIC_221:
+#define IE_ID_LEN_FIELDS_BYTES 2
+			pIe = (struct IE_WPA *)pCurrentPtr;
+
+			if (!memcmp(pIe->oui, oui01, sizeof(oui01))) {
+				pwpa_supplicant->Wpa_ie_len
+				    = min_t(size_t, elemLen + IE_ID_LEN_FIELDS_BYTES,
+					  sizeof(pwpa_supplicant->Wpa_ie));
+				memcpy(pwpa_supplicant->Wpa_ie,
+				       pCurrentPtr,
+				       pwpa_supplicant->Wpa_ie_len);
+				HEXDUMP("InterpretIE: Resp WPA_IE",
+					pwpa_supplicant->Wpa_ie, elemLen);
+			}
+			break;
+		case WPA2_IE:
+			pIe = (struct IE_WPA *)pCurrentPtr;
+			pwpa2_supplicant->Wpa_ie_len
+			    = min_t(size_t, elemLen + IE_ID_LEN_FIELDS_BYTES,
+				  sizeof(pwpa2_supplicant->Wpa_ie));
+			memcpy(pwpa2_supplicant->Wpa_ie,
+			       pCurrentPtr, pwpa2_supplicant->Wpa_ie_len);
+
+			HEXDUMP("InterpretIE: Resp WPA2_IE",
+				pwpa2_supplicant->Wpa_ie, elemLen);
+			break;
+		case TIM:
+			break;
+
+		case CHALLENGE_TEXT:
+			break;
+		}
+
+		pCurrentPtr += elemLen + 2;
+
+		/* need to account for IE ID and IE Len */
+		bytesLeftForCurrentBeacon -= (elemLen + 2);
+
+	}			/* while (bytesLeftForCurrentBeacon > 2) */
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Compare two SSIDs
+ *
+ *  @param ssid1    A pointer to ssid to compare
+ *  @param ssid2    A pointer to ssid to compare
+ *
+ *  @return         0--ssid is same, otherwise is different
+ */
+int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1, struct WLAN_802_11_SSID *ssid2)
+{
+	if (!ssid1 || !ssid2)
+		return -1;
+
+	if (ssid1->SsidLength != ssid2->SsidLength)
+		return -1;
+
+	return memcmp(ssid1->Ssid, ssid2->Ssid, ssid1->SsidLength);
+}
+
+/**
+ *  @brief This function finds a specific compatible BSSID in the scan list
+ *
+ *  @param Adapter  A pointer to wlan_adapter
+ *  @param bssid    BSSID to find in the scan list
+ *  @param mode     Network mode: Infrastructure or IBSS
+ *
+ *  @return         index in BSSID list, or error return code (< 0)
+ */
+int libertas_find_BSSID_in_list(wlan_adapter * Adapter, u8 * bssid, int mode)
+{
+	int ret = -ENETUNREACH;
+	int i;
+
+	if (!bssid)
+		return -EFAULT;
+
+	PRINTM(INFO, "FindBSSID: Num of BSSIDs = %d\n",
+	       Adapter->NumInScanTable);
+
+	/* Look through the scan table for a compatible match. The ret return
+	 *   variable will be equal to the index in the scan table (greater
+	 *   than zero) if the network is compatible.  The loop will continue
+	 *   past a matched bssid that is not compatible in case there is an
+	 *   AP with multiple SSIDs assigned to the same BSSID
+	 */
+	for (i = 0; ret < 0 && i < Adapter->NumInScanTable; i++) {
+		if (!memcmp(Adapter->ScanTable[i].MacAddress, bssid, ETH_ALEN)) {
+			switch (mode) {
+			case Wlan802_11Infrastructure:
+			case Wlan802_11IBSS:
+				ret = IsNetworkCompatible(Adapter, i, mode);
+				break;
+			default:
+				ret = i;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+/**
+ *  @brief This function finds ssid in ssid list.
+ *
+ *  @param Adapter  A pointer to wlan_adapter
+ *  @param ssid     SSID to find in the list
+ *  @param bssid    BSSID to qualify the SSID selection (if provided)
+ *  @param mode     Network mode: Infrastructure or IBSS
+ *
+ *  @return         index in BSSID list
+ */
+int libertas_find_SSID_in_list(wlan_adapter * Adapter,
+		   struct WLAN_802_11_SSID *ssid, u8 * bssid, int mode)
+{
+	int net = -ENETUNREACH;
+	u8 bestrssi = 0;
+	int i;
+	int j;
+
+	PRINTM(INFO, "Num of Entries in Table = %d\n", Adapter->NumInScanTable);
+
+	for (i = 0; i < Adapter->NumInScanTable; i++) {
+		if (!libertas_SSID_cmp(&Adapter->ScanTable[i].Ssid, ssid) &&
+		    (!bssid ||
+		     !memcmp(Adapter->ScanTable[i].
+			     MacAddress, bssid, ETH_ALEN))) {
+			switch (mode) {
+			case Wlan802_11Infrastructure:
+			case Wlan802_11IBSS:
+				j = IsNetworkCompatible(Adapter, i, mode);
+
+				if (j >= 0) {
+					if (bssid) {
+						return i;
+					}
+
+					if (SCAN_RSSI
+					    (Adapter->ScanTable[i].Rssi)
+					    > bestrssi) {
+						bestrssi =
+						    SCAN_RSSI(Adapter->
+							      ScanTable[i].
+							      Rssi);
+						net = i;
+					}
+				} else {
+					if (net == -ENETUNREACH) {
+						net = j;
+					}
+				}
+				break;
+			case Wlan802_11AutoUnknown:
+			default:
+				if (SCAN_RSSI(Adapter->ScanTable[i].Rssi)
+				    > bestrssi) {
+					bestrssi =
+					    SCAN_RSSI(Adapter->ScanTable[i].
+						      Rssi);
+					net = i;
+				}
+				break;
+			}
+		}
+	}
+
+	return net;
+}
+
+/**
+ *  @brief This function finds the best SSID in the Scan List
+ *
+ *  Search the scan table for the best SSID that also matches the current
+ *   adapter network preference (infrastructure or adhoc)
+ *
+ *  @param Adapter  A pointer to wlan_adapter
+ *
+ *  @return         index in BSSID list
+ */
+int libertas_find_best_SSID_in_list(wlan_adapter * Adapter)
+{
+	int mode = Adapter->InfrastructureMode;
+	int bestnet = -ENETUNREACH;
+	u8 bestrssi = 0;
+	int i;
+
+	ENTER();
+
+	PRINTM(INFO, "Num of BSSIDs = %d\n", Adapter->NumInScanTable);
+
+	for (i = 0; i < Adapter->NumInScanTable; i++) {
+		switch (mode) {
+		case Wlan802_11Infrastructure:
+		case Wlan802_11IBSS:
+			if (IsNetworkCompatible(Adapter, i, mode) >= 0) {
+				if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) >
+				    bestrssi) {
+					bestrssi =
+					    SCAN_RSSI(Adapter->ScanTable[i].
+						      Rssi);
+					bestnet = i;
+				}
+			}
+			break;
+		case Wlan802_11AutoUnknown:
+		default:
+			if (SCAN_RSSI(Adapter->ScanTable[i].Rssi) > bestrssi) {
+				bestrssi =
+				    SCAN_RSSI(Adapter->ScanTable[i].Rssi);
+				bestnet = i;
+			}
+			break;
+		}
+	}
+
+	LEAVE();
+	return bestnet;
+}
+
+/**
+ *  @brief Find the AP with specific ssid in the scan list
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param pSSID        A pointer to AP's ssid
+ *
+ *  @return             WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int libertas_find_best_network_SSID(wlan_private * priv, struct WLAN_802_11_SSID *pSSID)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	struct bss_descriptor *pReqBSSID;
+	int i;
+
+	ENTER();
+
+	memset(pSSID, 0, sizeof(struct WLAN_802_11_SSID));
+
+	wlan_scan_networks(priv, NULL);
+
+	i = libertas_find_best_SSID_in_list(Adapter);
+
+	if (i >= 0) {
+
+		pReqBSSID = &Adapter->ScanTable[i];
+		memcpy(pSSID, &pReqBSSID->Ssid,
+		       sizeof(struct WLAN_802_11_SSID));
+
+		/* Make sure we are in the right mode */
+		if (Adapter->InfrastructureMode == Wlan802_11AutoUnknown) {
+			Adapter->InfrastructureMode =
+			    pReqBSSID->InfrastructureMode;
+
+			ret = libertas_prepare_and_send_command(priv,
+						    HostCmd_CMD_802_11_SNMP_MIB,
+						    HostCmd_ACT_SET,
+						    HostCmd_OPTION_WAITFORRSP,
+						    OID_802_11_INFRASTRUCTURE_MODE,
+						    NULL);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+
+	if (!pSSID->SsidLength) {
+		ret = WLAN_STATUS_FAILURE;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/**
+ *  @brief Scan Network
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param vwrq         A pointer to iw_param structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
+		  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	union iwreq_data wrqu;
+
+	ENTER();
+
+#ifdef REASSOCIATION
+	if (down_interruptible(&Adapter->ReassocSem)) {
+		PRINTM(FATAL, "Acquire semaphore error, libertas_set_scan\n");
+		return -EBUSY;
+	}
+#endif
+
+	if (!wlan_scan_networks(priv, NULL)) {
+		memset(&wrqu, 0, sizeof(union iwreq_data));
+		wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu,
+				    NULL);
+	}
+#ifdef REASSOCIATION
+	up(&Adapter->ReassocSem);
+#endif
+
+	if (Adapter->SurpriseRemoved)
+		return WLAN_STATUS_FAILURE;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Send a scan command for all available channels filtered on a spec
+ *
+ *  @param priv             A pointer to wlan_private structure
+ *  @param pRequestedSSID   A pointer to AP's ssid
+ *  @param keepPreviousScan Flag used to save/clear scan table before scan
+ *
+ *  @return                WLAN_STATUS_SUCCESS-success, otherwise fail
+ */
+int libertas_send_specific_SSID_scan(wlan_private * priv,
+			 struct WLAN_802_11_SSID *pRequestedSSID,
+			 u8 keepPreviousScan)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct wlan_ioctl_user_scan_cfg scanCfg;
+
+	ENTER();
+
+	if (pRequestedSSID == NULL) {
+		return WLAN_STATUS_FAILURE;
+	}
+
+	memset(&scanCfg, 0x00, sizeof(scanCfg));
+
+	memcpy(scanCfg.specificSSID, pRequestedSSID->Ssid,
+	       pRequestedSSID->SsidLength);
+	scanCfg.keepPreviousScan = keepPreviousScan;
+
+	wlan_scan_networks(priv, &scanCfg);
+
+	if (Adapter->SurpriseRemoved)
+		return WLAN_STATUS_FAILURE;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief scan an AP with specific BSSID
+ *
+ *  @param priv             A pointer to wlan_private structure
+ *  @param bssid            A pointer to AP's bssid
+ *  @param keepPreviousScan Flag used to save/clear scan table before scan
+ *
+ *  @return          WLAN_STATUS_SUCCESS-success, otherwise fail
+ */
+int libertas_send_specific_BSSID_scan(wlan_private * priv, u8 * bssid, u8 keepPreviousScan)
+{
+	struct wlan_ioctl_user_scan_cfg scanCfg;
+
+	ENTER();
+
+	if (bssid == NULL) {
+		return WLAN_STATUS_FAILURE;
+	}
+
+	memset(&scanCfg, 0x00, sizeof(scanCfg));
+	memcpy(scanCfg.specificBSSID, bssid, sizeof(scanCfg.specificBSSID));
+	scanCfg.keepPreviousScan = keepPreviousScan;
+
+	wlan_scan_networks(priv, &scanCfg);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief  Retrieve the scan table entries via wireless tools IOCTL call
+ *
+ *  @param dev          A pointer to net_device structure
+ *  @param info         A pointer to iw_request_info structure
+ *  @param dwrq         A pointer to iw_point structure
+ *  @param extra        A pointer to extra data buf
+ *
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
+		  struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	char *current_ev = extra;
+	char *end_buf = extra + IW_SCAN_MAX_DATA;
+	struct chan_freq_power *cfp;
+	struct bss_descriptor *pScanTable;
+	char *current_val;	/* For rates */
+	struct iw_event iwe;	/* Temporary buffer */
+	int i;
+	int j;
+	int rate;
+#define PERFECT_RSSI ((u8)50)
+#define WORST_RSSI   ((u8)0)
+#define RSSI_DIFF    ((u8)(PERFECT_RSSI - WORST_RSSI))
+	u8 rssi;
+
+	u8 buf[16 + 256 * 2];
+	u8 *ptr;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected)
+		PRINTM(INFO, "Current Ssid: %32s\n",
+		       Adapter->CurBssParams.ssid.Ssid);
+
+	PRINTM(INFO, "Scan: Get: NumInScanTable = %d\n",
+	       Adapter->NumInScanTable);
+
+	/* The old API using SIOCGIWAPLIST had a hard limit of IW_MAX_AP.
+	 * The new API using SIOCGIWSCAN is only limited by buffer size
+	 * WE-14 -> WE-16 the buffer is limited to IW_SCAN_MAX_DATA bytes
+	 * which is 4096.
+	 */
+	for (i = 0; i < Adapter->NumInScanTable; i++) {
+		if ((current_ev + MAX_SCAN_CELL_SIZE) >= end_buf) {
+			PRINTM(INFO, "i=%d break out: current_ev=%p end_buf=%p "
+			       "MAX_SCAN_CELL_SIZE=%d\n",
+			       i, current_ev, end_buf, MAX_SCAN_CELL_SIZE);
+			break;
+		}
+
+		pScanTable = &Adapter->ScanTable[i];
+
+		PRINTM(INFO, "i=%d  Ssid: %32s\n", i, pScanTable->Ssid.Ssid);
+
+		cfp =
+		    libertas_find_cfp_by_band_and_channel(Adapter, 0,
+						 pScanTable->Channel);
+		if (!cfp) {
+			PRINTM(INFO, "Invalid channel number %d\n",
+			       pScanTable->Channel);
+			continue;
+		}
+
+		if (!ssid_valid(&Adapter->ScanTable[i].Ssid)) {
+			continue;
+		}
+
+		/* 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,
+		       &Adapter->ScanTable[i].MacAddress, ETH_ALEN);
+
+		iwe.len = IW_EV_ADDR_LEN;
+		current_ev =
+		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
+
+		//Add the ESSID
+		iwe.u.data.length = Adapter->ScanTable[i].Ssid.SsidLength;
+
+		if (iwe.u.data.length > 32) {
+			iwe.u.data.length = 32;
+		}
+
+		iwe.cmd = SIOCGIWESSID;
+		iwe.u.data.flags = 1;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  Adapter->ScanTable[i].Ssid.
+						  Ssid);
+
+		//Add mode
+		iwe.cmd = SIOCGIWMODE;
+		iwe.u.mode = Adapter->ScanTable[i].InfrastructureMode + 1;
+		iwe.len = IW_EV_UINT_LEN;
+		current_ev =
+		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
+
+		//frequency
+		iwe.cmd = SIOCGIWFREQ;
+		iwe.u.freq.m = (long)cfp->Freq * 100000;
+		iwe.u.freq.e = 1;
+		iwe.len = IW_EV_FREQ_LEN;
+		current_ev =
+		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
+
+		/* Add quality statistics */
+		iwe.cmd = IWEVQUAL;
+		iwe.u.qual.updated = IW_QUAL_ALL_UPDATED;
+		iwe.u.qual.level = SCAN_RSSI(Adapter->ScanTable[i].Rssi);
+
+		rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+		iwe.u.qual.qual =
+		    (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) *
+		     (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) /
+		    (RSSI_DIFF * RSSI_DIFF);
+		if (iwe.u.qual.qual > 100)
+			iwe.u.qual.qual = 100;
+		else if (iwe.u.qual.qual < 1)
+			iwe.u.qual.qual = 0;
+
+		if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+			iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+		} else {
+			iwe.u.qual.noise =
+			    CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+		}
+		if ((Adapter->InfrastructureMode == Wlan802_11IBSS) &&
+		    !libertas_SSID_cmp(&Adapter->CurBssParams.ssid,
+			     &Adapter->ScanTable[i].Ssid)
+		    && Adapter->AdhocCreate) {
+			ret = libertas_prepare_and_send_command(priv,
+						    HostCmd_CMD_802_11_RSSI,
+						    0,
+						    HostCmd_OPTION_WAITFORRSP,
+						    0, NULL);
+
+			if (!ret) {
+				iwe.u.qual.level =
+				    CAL_RSSI(Adapter->SNR[TYPE_RXPD][TYPE_AVG] /
+					     AVG_SCALE,
+					     Adapter->NF[TYPE_RXPD][TYPE_AVG] /
+					     AVG_SCALE);
+			}
+		}
+		iwe.len = IW_EV_QUAL_LEN;
+		current_ev =
+		    iwe_stream_add_event(current_ev, end_buf, &iwe, iwe.len);
+
+		/* Add encryption capability */
+		iwe.cmd = SIOCGIWENCODE;
+		if (Adapter->ScanTable[i].Privacy) {
+			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
+		} else {
+			iwe.u.data.flags = IW_ENCODE_DISABLED;
+		}
+		iwe.u.data.length = 0;
+		iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+		current_ev = iwe_stream_add_point(current_ev, end_buf, &iwe,
+						  Adapter->ScanTable->Ssid.
+						  Ssid);
+
+		current_val = current_ev + IW_EV_LCP_LEN;
+
+		iwe.cmd = SIOCGIWRATE;
+
+		iwe.u.bitrate.fixed = 0;
+		iwe.u.bitrate.disabled = 0;
+		iwe.u.bitrate.value = 0;
+
+		/* Bit rate given in 500 kb/s units (+ 0x80) */
+		for (j = 0; j < sizeof(Adapter->ScanTable[i].libertas_supported_rates);
+		     j++) {
+			if (Adapter->ScanTable[i].libertas_supported_rates[j] == 0) {
+				break;
+			}
+			rate =
+			    (Adapter->ScanTable[i].libertas_supported_rates[j] & 0x7F) *
+			    500000;
+			if (rate > iwe.u.bitrate.value) {
+				iwe.u.bitrate.value = rate;
+			}
+
+			iwe.u.bitrate.value =
+			    (Adapter->ScanTable[i].libertas_supported_rates[j]
+			     & 0x7f) * 500000;
+			iwe.len = IW_EV_PARAM_LEN;
+			current_ev =
+			    iwe_stream_add_value(current_ev, current_val,
+						 end_buf, &iwe, iwe.len);
+
+		}
+		if ((Adapter->ScanTable[i].InfrastructureMode == Wlan802_11IBSS)
+		    && !libertas_SSID_cmp(&Adapter->CurBssParams.ssid,
+				&Adapter->ScanTable[i].Ssid)
+		    && Adapter->AdhocCreate) {
+			iwe.u.bitrate.value = 22 * 500000;
+		}
+		iwe.len = IW_EV_PARAM_LEN;
+		current_ev =
+		    iwe_stream_add_value(current_ev, current_val, end_buf, &iwe,
+					 iwe.len);
+
+		/* Add new value to event */
+		current_val = current_ev + IW_EV_LCP_LEN;
+
+		if (Adapter->ScanTable[i].wpa2_supplicant.Wpa_ie[0] == WPA2_IE) {
+			memset(&iwe, 0, sizeof(iwe));
+			memset(buf, 0, sizeof(buf));
+			memcpy(buf, Adapter->ScanTable[i].
+						wpa2_supplicant.Wpa_ie,
+					Adapter->ScanTable[i].wpa2_supplicant.
+						Wpa_ie_len);
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = Adapter->ScanTable[i].
+					wpa2_supplicant.Wpa_ie_len;
+			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+			current_ev = iwe_stream_add_point(current_ev, end_buf,
+					&iwe, buf);
+		}
+		if (Adapter->ScanTable[i].wpa_supplicant.Wpa_ie[0] == WPA_IE) {
+			memset(&iwe, 0, sizeof(iwe));
+			memset(buf, 0, sizeof(buf));
+			memcpy(buf, Adapter->ScanTable[i].
+						wpa_supplicant.Wpa_ie,
+					Adapter->ScanTable[i].wpa_supplicant.
+						Wpa_ie_len);
+			iwe.cmd = IWEVGENIE;
+			iwe.u.data.length = Adapter->ScanTable[i].
+					wpa_supplicant.Wpa_ie_len;
+			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+			current_ev = iwe_stream_add_point(current_ev, end_buf,
+					&iwe, buf);
+		}
+
+
+		if (Adapter->ScanTable[i].extra_ie != 0) {
+			memset(&iwe, 0, sizeof(iwe));
+			memset(buf, 0, sizeof(buf));
+			ptr = buf;
+			ptr += sprintf(ptr, "extra_ie");
+			iwe.u.data.length = strlen(buf);
+
+			PRINTM(INFO, "iwe.u.data.length %d\n",
+			       iwe.u.data.length);
+			PRINTM(INFO, "BUF: %s \n", buf);
+
+			iwe.cmd = IWEVCUSTOM;
+			iwe.len = IW_EV_POINT_LEN + iwe.u.data.length;
+			current_ev =
+			    iwe_stream_add_point(current_ev, end_buf, &iwe,
+						 buf);
+		}
+
+		current_val = current_ev + IW_EV_LCP_LEN;
+
+		/*
+		 * Check if we added any event
+		 */
+		if ((current_val - current_ev) > IW_EV_LCP_LEN)
+			current_ev = current_val;
+	}
+
+	dwrq->length = (current_ev - extra);
+	dwrq->flags = 0;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief Retrieve the scan response/beacon table
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param wrq          A pointer to iwreq structure
+ *
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_get_scan_table_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	wlan_adapter *Adapter;
+	struct bss_descriptor *pBssInfo;
+	struct wlan_ioctl_get_scan_table_info *pRspInfo;
+	struct wlan_ioctl_get_scan_table_entry *pRspEntry;
+	struct wlan_ioctl_get_scan_table_entry tmpRspEntry;
+	int retcode;
+	int retlen;
+	int spaceNeeded;
+	int spaceLeft;
+	u8 *pCurrent;
+	u8 *pBufferEnd;
+	u32 scanStart;
+	u32 numScansDone;
+	int variableSize;
+
+	const int fixedSize = (sizeof(tmpRspEntry.fixedFieldLength)
+			       + sizeof(tmpRspEntry.fixedFields)
+			       + sizeof(tmpRspEntry.bssInfoLength));
+
+	retlen = 0;
+
+	if (copy_from_user(&scanStart,
+			   wrq->u.data.pointer, sizeof(scanStart)) != 0) {
+		/* copy_from_user failed  */
+		PRINTM(INFO, "GetScanTable: copy from user failed\n");
+		retcode = -EFAULT;
+
+	} else {
+
+		PRINTM(INFO, "GetScanTable: scanStart req = %d\n", scanStart);
+		PRINTM(INFO, "GetScanTable: length avail = %d\n",
+		       wrq->u.data.length);
+
+		Adapter = priv->adapter;
+
+		numScansDone = 0;
+
+		pRspInfo =
+		    (struct wlan_ioctl_get_scan_table_info *) wrq->u.data.pointer;
+		pCurrent = pRspInfo->scan_table_entry_buffer;
+		pBufferEnd = wrq->u.data.pointer + wrq->u.data.length - 1;
+		spaceLeft = pBufferEnd - pCurrent;
+
+		while (spaceLeft &&
+		       scanStart + numScansDone < Adapter->NumInScanTable) {
+
+			pBssInfo =
+			    &Adapter->ScanTable[scanStart + numScansDone];
+
+			/* No beacon stored, variable size set to 0 */
+			variableSize = 0;
+
+			/* If we stored a beacon and its size was zero, set the variable
+			 *  size return value to the size of the brief scan response 
+			 *  wlan_scan_create_brief_scan_table creates.  Also used if 
+			 *  we are not configured to store beacons in the first place
+			 */
+			if (variableSize == 0) {
+				variableSize = pBssInfo->Ssid.SsidLength + 2;
+				variableSize += (sizeof(pBssInfo->BeaconPeriod)
+						 + sizeof(pBssInfo->TimeStamp)
+						 + sizeof(pBssInfo->Cap));
+			}
+
+			spaceNeeded = fixedSize + variableSize;
+			spaceLeft = pBufferEnd - pCurrent;
+
+			PRINTM(INFO,
+			       "GetScanTable: bss[%d], need(%d), left(%d)\n",
+			       scanStart + numScansDone, spaceNeeded,
+			       spaceLeft);
+
+			if (spaceNeeded >= spaceLeft) {
+				spaceLeft = 0;
+			} else {
+
+				PRINTM(INFO, "GetScanTable: bss[%d] = "
+				       "%02x:%02x:%02x:%02x:%02x:%02x\n",
+				       scanStart + numScansDone,
+				       pBssInfo->MacAddress[0],
+				       pBssInfo->MacAddress[1],
+				       pBssInfo->MacAddress[2],
+				       pBssInfo->MacAddress[3],
+				       pBssInfo->MacAddress[4],
+				       pBssInfo->MacAddress[5]);
+
+				tmpRspEntry.fixedFieldLength
+				    = sizeof(pRspEntry->fixedFields);
+
+				memcpy(tmpRspEntry.fixedFields.bssid,
+				       pBssInfo->MacAddress,
+				       sizeof(pRspEntry->fixedFields.bssid));
+
+				tmpRspEntry.fixedFields.rssi = pBssInfo->Rssi;
+				tmpRspEntry.fixedFields.channel =
+				    pBssInfo->Channel;
+				tmpRspEntry.fixedFields.networkTSF =
+				    pBssInfo->networkTSF;
+				tmpRspEntry.bssInfoLength = variableSize;
+
+				/*
+				 *  Copy fixed fields to user space
+				 */
+				if (copy_to_user
+				    (pCurrent, &tmpRspEntry, fixedSize)) {
+					PRINTM(INFO, "Copy to user failed\n");
+					return -EFAULT;
+				}
+
+				pCurrent += fixedSize;
+
+				wlan_scan_create_brief_scan_table(&pCurrent,
+								  pBssInfo);
+
+				numScansDone++;
+
+			}	/* else */
+
+		}		/* while (spaceLeft && ... ) */
+
+		pRspInfo->scanNumber = numScansDone;
+		retlen = pCurrent - (u8 *) wrq->u.data.pointer;
+
+		retcode = WLAN_STATUS_SUCCESS;
+	}
+
+	wrq->u.data.length = retlen;
+
+	return retcode;
+}
+
+/**
+ *  @brief Private IOCTL entry to perform an app configured immediate scan
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param wrq          A pointer to iwreq structure containing the
+ *                      wlan_ioctl_user_scan_cfg requesting this scan
+ *
+ *  @return             0 if successful; IOCTL error code otherwise
+ */
+int libertas_set_user_scan_ioctl(wlan_private * priv, struct iwreq *wrq)
+{
+	struct wlan_ioctl_user_scan_cfg scanReq;
+	int retcode;
+	union iwreq_data wrqu;
+
+	if (copy_from_user(&scanReq,
+			   wrq->u.data.pointer,
+			   min_t(size_t, wrq->u.data.length, sizeof(scanReq))) != 0) {
+		/* copy_from_user failed  */
+		PRINTM(INFO, "SetUserScan: copy from user failed\n");
+		retcode = -EFAULT;
+
+	} else {
+		retcode = wlan_scan_networks(priv, &scanReq);
+
+		memset(&wrqu, 0x00, sizeof(union iwreq_data));
+		wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu,
+				    NULL);
+	}
+
+	return retcode;
+}
+
+/**
+ *  @brief Prepare a scan command to be sent to the firmware
+ *
+ *  Use the wlan_scan_cmd_config sent to the command processing module in
+ *   the libertas_prepare_and_send_command to configure a HostCmd_DS_802_11_SCAN command
+ *   struct to send to firmware.
+ *
+ *  The fixed fields specifying the BSS type and BSSID filters as well as a
+ *   variable number/length of TLVs are sent in the command to firmware.
+ *
+ *  @param priv       A pointer to wlan_private structure
+ *  @param cmd        A pointer to HostCmd_DS_COMMAND structure to be sent to
+ *                    firmware with the HostCmd_DS_801_11_SCAN structure
+ *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
+ *                    to set the fields/TLVs for the command sent to firmware
+ *
+ *  @return           WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ *
+ *  @sa wlan_scan_create_channel_list
+ */
+int libertas_cmd_80211_scan(wlan_private * priv,
+			 struct HostCmd_DS_COMMAND *cmd, void *pdata_buf)
+{
+	struct HostCmd_DS_802_11_SCAN *pScan = &cmd->params.scan;
+	struct wlan_scan_cmd_config *pScanCfg;
+
+	ENTER();
+
+	pScanCfg = (struct wlan_scan_cmd_config *) pdata_buf;
+
+	/* Set fixed field variables in scan command */
+	pScan->BSSType = pScanCfg->bssType;
+	memcpy(pScan->BSSID, pScanCfg->specificBSSID, sizeof(pScan->BSSID));
+	memcpy(pScan->TlvBuffer, pScanCfg->tlvBuffer, pScanCfg->tlvBufferLen);
+
+	cmd->Command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
+
+	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
+	cmd->Size = wlan_cpu_to_le16(sizeof(pScan->BSSType)
+				     + sizeof(pScan->BSSID)
+				     + pScanCfg->tlvBufferLen + S_DS_GEN);
+
+	PRINTM(INFO, "SCAN_CMD: Command=%x, Size=%x, SeqNum=%x\n",
+	       cmd->Command, cmd->Size, cmd->SeqNum);
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief This function handles the command response of scan
+ *
+ *   The response buffer for the scan command has the following
+ *      memory layout:
+ *
+ *     .-----------------------------------------------------------.
+ *     |  Header (4 * sizeof(u16)):  Standard command response hdr |
+ *     .-----------------------------------------------------------.
+ *     |  BufSize (u16) : sizeof the BSS Description data          |
+ *     .-----------------------------------------------------------.
+ *     |  NumOfSet (u8) : Number of BSS Descs returned             |
+ *     .-----------------------------------------------------------.
+ *     |  BSSDescription data (variable, size given in BufSize)    |
+ *     .-----------------------------------------------------------.
+ *     |  TLV data (variable, size calculated using Header->Size,  |
+ *     |            BufSize and sizeof the fixed fields above)     |
+ *     .-----------------------------------------------------------.
+ *
+ *  @param priv    A pointer to wlan_private structure
+ *  @param resp    A pointer to HostCmd_DS_COMMAND
+ *
+ *  @return        WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+int libertas_ret_80211_scan(wlan_private * priv, struct HostCmd_DS_COMMAND *resp)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct HostCmd_DS_802_11_SCAN_RSP *pScan;
+	struct bss_descriptor newBssEntry;
+	struct MrvlIEtypes_Data *pTlv;
+	struct MrvlIEtypes_TsfTimestamp *pTsfTlv;
+	u8 *pBssInfo;
+	u16 scanRespSize;
+	int bytesLeft;
+	int numInTable;
+	int bssIdx;
+	int idx;
+	int tlvBufSize;
+	u64 tsfVal;
+
+	ENTER();
+
+	pScan = &resp->params.scanresp;
+
+	if (pScan->NumberOfSets > MRVDRV_MAX_BSSID_LIST) {
+		PRINTM(INFO,
+		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
+		       pScan->NumberOfSets);
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	bytesLeft = wlan_le16_to_cpu(pScan->BSSDescriptSize);
+	PRINTM(INFO, "SCAN_RESP: BSSDescriptSize %d\n", bytesLeft);
+
+	scanRespSize = wlan_le16_to_cpu(resp->Size);
+	PRINTM(INFO, "SCAN_RESP: returned %d AP before parsing\n",
+	       pScan->NumberOfSets);
+
+	numInTable = Adapter->NumInScanTable;
+	pBssInfo = pScan->BssDescAndTlvBuffer;
+
+	/* The size of the TLV buffer is equal to the entire command response
+	 *   size (scanRespSize) minus the fixed fields (sizeof()'s), the
+	 *   BSS Descriptions (BSSDescriptSize as bytesLef) and the command
+	 *   response header (S_DS_GEN)
+	 */
+	tlvBufSize = scanRespSize - (bytesLeft + sizeof(pScan->BSSDescriptSize)
+				     + sizeof(pScan->NumberOfSets)
+				     + S_DS_GEN);
+
+	pTlv = (struct MrvlIEtypes_Data *) (pScan->BssDescAndTlvBuffer + bytesLeft);
+
+	/* Search the TLV buffer space in the scan response for any valid TLVs */
+	wlan_ret_802_11_scan_get_tlv_ptrs(pTlv, tlvBufSize, &pTsfTlv);
+
+	/*
+	 *  Process each scan response returned (pScan->NumberOfSets).  Save
+	 *    the information in the newBssEntry and then insert into the
+	 *    driver scan table either as an update to an existing entry
+	 *    or as an addition at the end of the table
+	 */
+	for (idx = 0; idx < pScan->NumberOfSets && bytesLeft; idx++) {
+		/* Zero out the newBssEntry we are about to store info in */
+		memset(&newBssEntry, 0x00, sizeof(newBssEntry));
+
+		/* Process the data fields and IEs returned for this BSS */
+		if ((InterpretBSSDescriptionWithIE(&newBssEntry,
+						   &pBssInfo,
+						   &bytesLeft) ==
+		     WLAN_STATUS_SUCCESS)
+		    && CHECK_SSID_IS_VALID(&newBssEntry.Ssid)) {
+
+			PRINTM(INFO,
+			       "SCAN_RESP: BSSID = %02x:%02x:%02x:%02x:%02x:%02x\n",
+			       newBssEntry.MacAddress[0],
+			       newBssEntry.MacAddress[1],
+			       newBssEntry.MacAddress[2],
+			       newBssEntry.MacAddress[3],
+			       newBssEntry.MacAddress[4],
+			       newBssEntry.MacAddress[5]);
+
+			/*
+			 * Search the scan table for the same bssid
+			 */
+			for (bssIdx = 0; bssIdx < numInTable; bssIdx++) {
+				if (memcmp(newBssEntry.MacAddress,
+					   Adapter->ScanTable[bssIdx].
+					   MacAddress,
+					   sizeof(newBssEntry.MacAddress)) ==
+				    0) {
+					/*
+					 * If the SSID matches as well, it is a duplicate of
+					 *   this entry.  Keep the bssIdx set to this
+					 *   entry so we replace the old contents in the table
+					 */
+					if ((newBssEntry.Ssid.SsidLength ==
+					     Adapter->ScanTable[bssIdx].Ssid.
+					     SsidLength)
+					    &&
+					    (memcmp
+					     (newBssEntry.Ssid.Ssid,
+					      Adapter->ScanTable[bssIdx].Ssid.
+					      Ssid,
+					      newBssEntry.Ssid.SsidLength) ==
+					     0)) {
+						PRINTM(INFO,
+						       "SCAN_RESP: Duplicate of index: %d\n",
+						       bssIdx);
+						break;
+					}
+				}
+			}
+			/*
+			 * If the bssIdx is equal to the number of entries in the table,
+			 *   the new entry was not a duplicate; append it to the scan
+			 *   table
+			 */
+			if (bssIdx == numInTable) {
+				/* Range check the bssIdx, keep it limited to the last entry */
+				if (bssIdx == MRVDRV_MAX_BSSID_LIST) {
+					bssIdx--;
+				} else {
+					numInTable++;
+				}
+			}
+
+			/*
+			 * If the TSF TLV was appended to the scan results, save the
+			 *   this entries TSF value in the networkTSF field.  The
+			 *   networkTSF is the firmware's TSF value at the time the
+			 *   beacon or probe response was received.
+			 */
+			if (pTsfTlv) {
+				memcpy(&tsfVal, &pTsfTlv->tsfTable[idx],
+				       sizeof(tsfVal));
+				tsfVal = wlan_le64_to_cpu(tsfVal);
+
+				memcpy(&newBssEntry.networkTSF,
+				       &tsfVal, sizeof(newBssEntry.networkTSF));
+			}
+
+			/* Copy the locally created newBssEntry to the scan table */
+			memcpy(&Adapter->ScanTable[bssIdx],
+			       &newBssEntry,
+			       sizeof(Adapter->ScanTable[bssIdx]));
+
+		} else {
+
+			/* Error parsing/interpreting the scan response, skipped */
+			PRINTM(INFO, "SCAN_RESP: "
+			       "InterpretBSSDescriptionWithIE returned ERROR\n");
+		}
+	}
+
+	PRINTM(INFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
+	       pScan->NumberOfSets, numInTable - Adapter->NumInScanTable,
+	       numInTable);
+
+	/* Update the total number of BSSIDs in the scan table */
+	Adapter->NumInScanTable = numInTable;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/**
+ *  @brief scan network with specific ssid
+ *
+ *  @param priv         A pointer to wlan_private structure
+ *  @param req          A pointer to ifreq structure
+ *
+ *  @return             WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int libertas_extscan_ioctl(wlan_private * priv, struct ifreq *req)
+{
+	struct WLAN_802_11_SSID Ext_Scan_SSID;
+	union iwreq_data wrqu;
+
+	ENTER();
+
+	if (copy_from_user(&Ext_Scan_SSID, req->ifr_data,
+			   sizeof(Ext_Scan_SSID))) {
+		PRINTM(INFO, "copy of SSID for ext scan from user failed \n");
+		LEAVE();
+		return -EFAULT;
+	}
+	libertas_send_specific_SSID_scan(priv, &Ext_Scan_SSID, 1);
+
+	memset(&wrqu, 0, sizeof(union iwreq_data));
+	wireless_send_event(priv->wlan_dev.netdev, SIOCGIWSCAN, &wrqu, NULL);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_scan.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_scan.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_scan.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_scan.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,319 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil -*- */
+/* vi: set expandtab shiftwidth=4 tabstop=4 textwidth=78: */
+
+/** @file wlan_scan.h
+  *
+  * @brief Interface for the wlan network scan routines
+  *
+  * Driver interface functions and type declarations for the scan module
+  *   implemented in wlan_scan.c.
+  *
+  * @sa wlan_scan.c
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change Log:
+    01/11/06: Initial revision. New scan code, relocate related functions
+
+************************************************************/
+
+#ifndef _WLAN_SCAN_H
+#define _WLAN_SCAN_H
+
+#include "hostcmd.h"
+
+/**
+ *  @brief Maximum number of channels that can be sent in a setuserscan ioctl
+ *
+ *  @sa wlan_ioctl_user_scan_cfg
+ */
+#define WLAN_IOCTL_USER_SCAN_CHAN_MAX  50
+
+//! Infrastructure BSS scan type in wlan_scan_cmd_config
+#define WLAN_SCAN_BSS_TYPE_BSS         1
+
+//! Adhoc BSS scan type in wlan_scan_cmd_config
+#define WLAN_SCAN_BSS_TYPE_IBSS        2
+
+//! Adhoc or Infrastructure BSS scan type in wlan_scan_cmd_config, no filter
+#define WLAN_SCAN_BSS_TYPE_ANY         3
+
+/**
+ * @brief Structure used internally in the wlan driver to configure a scan.
+ *
+ * Sent to the command processing module to configure the firmware
+ *   scan command prepared by libertas_cmd_80211_scan.
+ *
+ * @sa wlan_scan_networks
+ *
+ */
+struct wlan_scan_cmd_config {
+    /**
+     *  @brief BSS Type to be sent in the firmware command
+     *
+     *  Field can be used to restrict the types of networks returned in the
+     *    scan.  Valid settings are:
+     *
+     *   - WLAN_SCAN_BSS_TYPE_BSS  (infrastructure)
+     *   - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
+     *   - WLAN_SCAN_BSS_TYPE_ANY  (unrestricted, adhoc and infrastructure)
+     */
+	u8 bssType;
+
+    /**
+     *  @brief Specific BSSID used to filter scan results in the firmware
+     */
+	u8 specificBSSID[ETH_ALEN];
+
+    /**
+     *  @brief Length of TLVs sent in command starting at tlvBuffer
+     */
+	int tlvBufferLen;
+
+    /**
+     *  @brief SSID TLV(s) and ChanList TLVs to be sent in the firmware command
+     *
+     *  @sa TLV_TYPE_CHANLIST, MrvlIEtypes_ChanListParamSet_t
+     *  @sa TLV_TYPE_SSID, MrvlIEtypes_SsIdParamSet_t
+     */
+	u8 tlvBuffer[1];	//!< SSID TLV(s) and ChanList TLVs are stored here
+};
+
+/**
+ *  @brief IOCTL channel sub-structure sent in wlan_ioctl_user_scan_cfg
+ *
+ *  Multiple instances of this structure are included in the IOCTL command
+ *   to configure a instance of a scan on the specific channel.
+ */
+struct wlan_ioctl_user_scan_chan {
+	u8 chanNumber;		//!< Channel Number to scan
+	u8 radioType;		//!< Radio type: 'B/G' Band = 0, 'A' Band = 1
+	u8 scanType;		//!< Scan type: Active = 0, Passive = 1
+	u16 scanTime;		//!< Scan duration in milliseconds; if 0 default used
+};
+
+/**
+ *  @brief IOCTL input structure to configure an immediate scan cmd to firmware
+ *
+ *  Used in the setuserscan (WLAN_SET_USER_SCAN) private ioctl.  Specifies
+ *   a number of parameters to be used in general for the scan as well
+ *   as a channel list (wlan_ioctl_user_scan_chan) for each scan period
+ *   desired.
+ *
+ *  @sa libertas_set_user_scan_ioctl
+ */
+struct wlan_ioctl_user_scan_cfg {
+
+    /**
+     *  @brief Flag set to keep the previous scan table intact
+     *
+     *  If set, the scan results will accumulate, replacing any previous
+     *   matched entries for a BSS with the new scan data
+     */
+	u8 keepPreviousScan;	//!< Do not erase the existing scan results
+
+    /**
+     *  @brief BSS Type to be sent in the firmware command
+     *
+     *  Field can be used to restrict the types of networks returned in the
+     *    scan.  Valid settings are:
+     *
+     *   - WLAN_SCAN_BSS_TYPE_BSS  (infrastructure)
+     *   - WLAN_SCAN_BSS_TYPE_IBSS (adhoc)
+     *   - WLAN_SCAN_BSS_TYPE_ANY  (unrestricted, adhoc and infrastructure)
+     */
+	u8 bssType;
+
+    /**
+     *  @brief Configure the number of probe requests for active chan scans
+     */
+	u8 numProbes;
+
+    /**
+     *  @brief BSSID filter sent in the firmware command to limit the results
+     */
+	u8 specificBSSID[ETH_ALEN];
+
+    /**
+     *  @brief SSID filter sent in the firmware command to limit the results
+     */
+	char specificSSID[MRVDRV_MAX_SSID_LENGTH + 1];
+
+    /**
+     *  @brief Variable number (fixed maximum) of channels to scan up
+     */
+	struct wlan_ioctl_user_scan_chan chanList[WLAN_IOCTL_USER_SCAN_CHAN_MAX];
+} __attribute__ ((packed));
+
+/**
+ *  @brief Sub-structure passed in wlan_ioctl_get_scan_table_entry for each BSS
+ *
+ *  Fixed field information returned for the scan response in the IOCTL
+ *    response.
+ */
+struct wlan_ioctl_get_scan_table_fixed {
+	u8 bssid[6];		//!< BSSID of this network
+	u8 channel;		//!< Channel this beacon/probe response was detected
+	u8 rssi;		//!< RSSI for the received packet
+	u64 networkTSF;		//!< TSF value from the firmware at packet reception
+} __attribute__ ((packed));
+
+/**
+ *  @brief Structure passed in the wlan_ioctl_get_scan_table_info for each
+ *         BSS returned in the WLAN_GET_SCAN_RESP IOCTL
+ *
+ *  @sa libertas_get_scan_table_ioctl
+ */
+struct wlan_ioctl_get_scan_table_entry {
+
+    /**
+     *  @brief Fixed field length included in the response.
+     *
+     *  Length value is included so future fixed fields can be added to the
+     *   response without breaking backwards compatibility.  Use the length
+     *   to find the offset for the bssInfoLength field, not a sizeof() calc.
+     */
+	u32 fixedFieldLength;
+
+    /**
+     *  @brief Always present, fixed length data fields for the BSS
+     */
+	struct wlan_ioctl_get_scan_table_fixed fixedFields;
+
+    /**
+     *  @brief Length of the BSS Information (probe resp or beacon) that
+     *         follows starting at bssInfoBuffer
+     */
+	u32 bssInfoLength;
+
+    /**
+     *  @brief Probe response or beacon scanned for the BSS.
+     *
+     *  Field layout:
+     *   - TSF              8 octets
+     *   - Beacon Interval  2 octets
+     *   - Capability Info  2 octets
+     *
+     *   - IEEE Infomation Elements; variable number & length per 802.11 spec
+     */
+	u8 bssInfoBuffer[1];
+} __attribute__ ((packed));
+
+/**
+ *  @brief WLAN_GET_SCAN_RESP private IOCTL struct to retrieve the scan table
+ *
+ *  @sa libertas_get_scan_table_ioctl
+ */
+struct wlan_ioctl_get_scan_table_info {
+
+    /**
+     *  - Zero based scan entry to start retrieval in command request
+     *  - Number of scans entires returned in command response
+     */
+	u32 scanNumber;
+
+     /**
+      * Buffer marker for multiple wlan_ioctl_get_scan_table_entry structures.
+      *   Each struct is padded to the nearest 32 bit boundary.
+      */
+	u8 scan_table_entry_buffer[1];
+
+} __attribute__ ((packed));
+
+/**
+ *  @brief Structure used to store information for each beacon/probe response
+ */
+struct bss_descriptor {
+	u8 MacAddress[ETH_ALEN];
+
+	struct WLAN_802_11_SSID Ssid;
+
+	/* WEP encryption requirement */
+	u32 Privacy;
+
+	/* receive signal strength in dBm */
+	long Rssi;
+
+	u32 Channel;
+
+	u16 BeaconPeriod;
+
+	u32 ATIMWindow;
+
+	enum WLAN_802_11_NETWORK_TYPE NetworkTypeInUse;
+	enum WLAN_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
+	u8 libertas_supported_rates[WLAN_SUPPORTED_RATES];
+
+	int extra_ie;
+
+	u8 TimeStamp[8];	//!< TSF value included in the beacon/probe response
+	union IEEEtypes_PhyParamSet PhyParamSet;
+	union IEEEtypes_SsParamSet SsParamSet;
+	struct IEEEtypes_CapInfo Cap;
+	u8 DataRates[WLAN_SUPPORTED_RATES];
+
+	u64 networkTSF;		//!< TSF timestamp from the current firmware TSF
+
+	struct IEEEtypes_CountryInfoFullSet CountryInfo;
+
+	struct WPA_SUPPLICANT wpa_supplicant;
+	struct WPA_SUPPLICANT wpa2_supplicant;
+
+};
+
+extern int libertas_SSID_cmp(struct WLAN_802_11_SSID *ssid1,
+		   struct WLAN_802_11_SSID *ssid2);
+extern int libertas_find_SSID_in_list(wlan_adapter * Adapter, struct WLAN_802_11_SSID *ssid,
+			  u8 * bssid, int mode);
+extern int libertas_find_best_SSID_in_list(wlan_adapter * Adapter);
+extern int libertas_find_BSSID_in_list(wlan_adapter * Adapter, u8 * bssid, int mode);
+
+extern int libertas_find_best_network_SSID(wlan_private * priv,
+			       struct WLAN_802_11_SSID *pSSID);
+
+extern int libertas_send_specific_SSID_scan(wlan_private * priv,
+				struct WLAN_802_11_SSID *pRequestedSSID,
+				u8 keepPreviousScan);
+extern int libertas_send_specific_BSSID_scan(wlan_private * priv,
+				 u8 * bssid, u8 keepPreviousScan);
+
+extern int libertas_get_scan_table_ioctl(wlan_private * priv, struct iwreq *wrq);
+extern int libertas_set_user_scan_ioctl(wlan_private * priv, struct iwreq *wrq);
+
+extern int libertas_cmd_80211_scan(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *cmd,
+				void *pdata_buf);
+
+extern int libertas_ret_80211_scan(wlan_private * priv,
+				struct HostCmd_DS_COMMAND *resp);
+
+struct ifreq;
+extern int libertas_extscan_ioctl(wlan_private * priv, struct ifreq *req);
+
+#ifdef __KERNEL__
+struct iw_point;
+struct iw_param;
+struct iw_request_info;
+extern int libertas_get_scan(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_point *dwrq, char *extra);
+extern int libertas_set_scan(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_param *vwrq, char *extra);
+#endif
+
+#endif				/* _WLAN_SCAN_H */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_thread.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_thread.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_thread.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_thread.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,69 @@
+/**
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+
+#ifndef	__WLAN_THREAD_H_
+#define	__WLAN_THREAD_H_
+
+#include	<linux/kthread.h>
+
+struct wlan_thread {
+	struct task_struct *task;
+	wait_queue_head_t waitQ;
+	pid_t pid;
+	void *priv;
+};
+
+static inline void wlan_activate_thread(struct wlan_thread * thr)
+{
+	/** Record the thread pid */
+	thr->pid = current->pid;
+
+	/** Initialize the wait queue */
+	init_waitqueue_head(&thr->waitQ);
+}
+
+static inline void wlan_deactivate_thread(struct wlan_thread * thr)
+{
+	ENTER();
+
+	LEAVE();
+}
+
+static inline void wlan_create_thread(int (*wlanfunc) (void *),
+				      struct wlan_thread * thr, char *name)
+{
+	thr->task = kthread_run(wlanfunc, thr, "%s", name);
+}
+
+static inline int wlan_terminate_thread(struct wlan_thread * thr)
+{
+	ENTER();
+
+	/* Check if the thread is active or not */
+	if (!thr->pid) {
+		PRINTM(INFO, "Thread does not exist\n");
+		return -1;
+	}
+	kthread_stop(thr->task);
+
+	LEAVE();
+	return 0;
+}
+
+#endif
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_tx.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_tx.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_tx.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_tx.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,374 @@
+/** @file wlan_tx.c
+  * @brief This file contains the handling of TX in wlan driver.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	09/28/05: Add Doxygen format comments
+	12/13/05: Add Proprietary periodic sleep support
+	01/05/06: Add kernel 2.6.x support	
+	04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+********************************************************/
+
+#include <linux/netdevice.h>
+
+#include "hostcmd.h"
+#include "radiotap.h"
+#include "sbi.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+#include "wlan_wext.h"
+
+/**
+ *  @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 
+ *  units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1)
+ *
+ *  @param rate    Input rate
+ *  @return      Output Rate (0 if invalid)
+ */
+static u32 convert_radiotap_rate_to_mv(u8 rate)
+{
+	switch (rate) {
+	case 2:		/*   1 Mbps */
+		return 0 | (1 << 4);
+	case 4:		/*   2 Mbps */
+		return 1 | (1 << 4);
+	case 11:		/* 5.5 Mbps */
+		return 2 | (1 << 4);
+	case 22:		/*  11 Mbps */
+		return 3 | (1 << 4);
+	case 12:		/*   6 Mbps */
+		return 4 | (1 << 4);
+	case 18:		/*   9 Mbps */
+		return 5 | (1 << 4);
+	case 24:		/*  12 Mbps */
+		return 6 | (1 << 4);
+	case 36:		/*  18 Mbps */
+		return 7 | (1 << 4);
+	case 48:		/*  24 Mbps */
+		return 8 | (1 << 4);
+	case 72:		/*  36 Mbps */
+		return 9 | (1 << 4);
+	case 96:		/*  48 Mbps */
+		return 10 | (1 << 4);
+	case 108:		/*  54 Mbps */
+		return 11 | (1 << 4);
+	}
+	return 0;
+}
+
+/** 
+ *  @brief This function processes a single packet and sends
+ *  to IF layer
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @param skb     A pointer to skb which includes TX packet
+ *  @return 	   WLAN_STATUS_SUCCESS or WLAN_STATUS_FAILURE
+ */
+static int SendSinglePacket(wlan_private * priv, struct sk_buff *skb)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	struct TxPD LocalTxPD;
+	struct TxPD *pLocalTxPD = &LocalTxPD;
+	u8 *p802x_hdr;
+	struct TxRadiotapHdr *pradiotap_hdr;
+	u32 new_rate;
+	u8 *ptr = priv->adapter->TmpTxBuf;
+
+	ENTER();
+
+	if ((priv->adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
+		HEXDUMP("TX packet: ", skb->data,
+			 min_t(unsigned int, skb->len, 100));
+
+	if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) {
+		PRINTM(INFO, "Tx Error: Bad skb length %d : %d\n",
+		       skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE);
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(pLocalTxPD, 0, sizeof(struct TxPD));
+
+	pLocalTxPD->TxPacketLength = skb->len;
+
+	if (Adapter->PSState != PS_STATE_FULL_POWER) {
+		if (libertas_check_last_packet_indication(priv)) {
+			Adapter->TxLockFlag = 1;
+			pLocalTxPD->PowerMgmt =
+			    MRVDRV_TxPD_POWER_MGMT_LAST_PACKET;
+		}
+	}
+	/* offset of actual data */
+	pLocalTxPD->TxPacketLocation = sizeof(struct TxPD);
+
+	/* TxCtrl set by user or default */
+	pLocalTxPD->TxControl = Adapter->PktTxCtrl;
+
+	p802x_hdr = skb->data;
+	if (priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
+
+		/* locate radiotap header */
+		pradiotap_hdr = (struct TxRadiotapHdr *)skb->data;
+
+		/* set TxPD fields from the radiotap header */
+		new_rate = convert_radiotap_rate_to_mv(pradiotap_hdr->rate);
+		if (new_rate != 0) {
+			/* erase TxControl[4:0] */
+			pLocalTxPD->TxControl &= ~0x1f;
+			/* write new TxControl[4:0] */
+			pLocalTxPD->TxControl |= new_rate;
+		}
+
+		/* skip the radiotap header */
+		p802x_hdr += sizeof(struct TxRadiotapHdr);
+		pLocalTxPD->TxPacketLength -= sizeof(struct TxRadiotapHdr);
+
+	}
+	/* copy destination address from 802.3 or 802.11 header */
+	if (priv->adapter->linkmode == WLAN_LINKMODE_802_11)
+		memcpy(pLocalTxPD->TxDestAddrHigh, p802x_hdr + 4, ETH_ALEN);
+	else
+		memcpy(pLocalTxPD->TxDestAddrHigh, p802x_hdr, ETH_ALEN);
+
+	HEXDUMP("TxPD", (u8 *) pLocalTxPD, sizeof(struct TxPD));
+
+	memcpy(ptr, pLocalTxPD, sizeof(struct TxPD));
+
+	ptr += sizeof(struct TxPD);
+
+	HEXDUMP("Tx Data", (u8 *) p802x_hdr, pLocalTxPD->TxPacketLength);
+	memcpy(ptr, p802x_hdr, pLocalTxPD->TxPacketLength);
+	ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
+			       priv->adapter->TmpTxBuf,
+			       pLocalTxPD->TxPacketLength +
+			       sizeof(struct TxPD));
+
+	if (ret) {
+		PRINTM(INFO, "Tx Error: libertas_sbi_host_to_card failed: 0x%X\n", ret);
+		goto done;
+	}
+
+	PRINTM(INFO, "SendSinglePacket succeeds\n");
+
+      done:
+	if (!ret) {
+		priv->stats.tx_packets++;
+		priv->stats.tx_bytes += skb->len;
+	} else {
+		priv->stats.tx_dropped++;
+		priv->stats.tx_errors++;
+	}
+
+	if (!ret && priv->adapter->radiomode == WLAN_RADIOMODE_RADIOTAP) {
+		/* Keep the skb to echo it back once Tx feedback is 
+		   received from FW */
+		skb_orphan(skb);
+		/* stop processing outgoing pkts */
+		netif_stop_queue(priv->wlan_dev.netdev);
+		/* freeze any packets already in our queues */
+		priv->adapter->TxLockFlag = 1;
+	} else {
+		dev_kfree_skb_any(skb);
+		priv->adapter->CurrentTxSkb = NULL;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+
+void libertas_tx_runqueue(wlan_private *priv)
+{
+	wlan_adapter *adapter = priv->adapter;
+	int i;
+
+	spin_lock(&adapter->txqueue_lock);
+	for (i = 0; i < adapter->tx_queue_idx; i++) {
+	 	struct sk_buff *skb = adapter->tx_queue_ps[i];
+		spin_unlock(&adapter->txqueue_lock);
+		SendSinglePacket(priv, skb);
+		spin_lock(&adapter->txqueue_lock);
+	}
+	adapter->tx_queue_idx = 0;
+	spin_unlock(&adapter->txqueue_lock);
+}
+
+static void wlan_tx_queue(wlan_private *priv, struct sk_buff *skb)
+{
+	wlan_adapter *adapter = priv->adapter;
+
+	spin_lock(&adapter->txqueue_lock);
+
+	WARN_ON(priv->adapter->tx_queue_idx >= NR_TX_QUEUE);
+	adapter->tx_queue_ps[adapter->tx_queue_idx++] = skb;
+	if (adapter->tx_queue_idx == NR_TX_QUEUE)
+		netif_stop_queue(priv->wlan_dev.netdev);
+	else
+		netif_start_queue(priv->wlan_dev.netdev);
+
+	spin_unlock(&adapter->txqueue_lock);
+}
+
+/** 
+ *  @brief This function checks the conditions and sends packet to IF
+ *  layer if everything is ok.
+ *  
+ *  @param priv    A pointer to wlan_private structure
+ *  @return 	   n/a
+ */
+int libertas_process_tx(wlan_private * priv, struct sk_buff *skb)
+{
+	int ret = WLAN_STATUS_FAILURE;
+
+	ENTER();
+
+	HEXDUMP("TX Data", skb->data, min_t(unsigned int, skb->len, 100));
+
+	if (priv->wlan_dev.dnld_sent) {
+		PRINTM(MSG, "TX Error: dnld_sent = %d, not sending\n",
+		       priv->wlan_dev.dnld_sent);
+		goto done;
+	}
+
+	if ((priv->adapter->PSState == PS_STATE_SLEEP) ||
+	    (priv->adapter->PSState == PS_STATE_PRE_SLEEP)) {
+		wlan_tx_queue(priv, skb);
+		return ret;
+	}
+
+	priv->adapter->CurrentTxSkb = skb;
+
+	ret = SendSinglePacket(priv, skb);
+done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function tells firmware to send a NULL data packet.
+ *  
+ *  @param priv     A pointer to wlan_private structure
+ *  @param pwr_mgmt indicate if power management bit should be 0 or 1
+ *  @return 	    n/a
+ */
+int libertas_send_null_packet(wlan_private * priv, u8 pwr_mgmt)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct TxPD txpd;
+	int ret = WLAN_STATUS_SUCCESS;
+	u8 *ptr = priv->adapter->TmpTxBuf;
+
+	ENTER();
+
+	if (priv->adapter->SurpriseRemoved) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	if (priv->adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
+		ret = WLAN_STATUS_FAILURE;
+		goto done;
+	}
+
+	memset(&txpd, 0, sizeof(struct TxPD));
+
+	txpd.TxControl = Adapter->PktTxCtrl;
+	txpd.PowerMgmt = pwr_mgmt;
+	txpd.TxPacketLocation = sizeof(struct TxPD);
+
+	memcpy(ptr, &txpd, sizeof(struct TxPD));
+
+	ret = libertas_sbi_host_to_card(priv, MVMS_DAT,
+			       priv->adapter->TmpTxBuf, sizeof(struct TxPD));
+
+	if (ret != 0) {
+		PRINTM(INFO, "TX Error: libertas_send_null_packet failed!\n");
+		goto done;
+	}
+
+      done:
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief This function check if we need send last packet indication.
+ *  
+ *  @param priv     A pointer to wlan_private structure
+ *
+ *  @return 	   TRUE or FALSE
+ */
+u8 libertas_check_last_packet_indication(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	u8 ret = 0;
+	if (Adapter->sleep_period.period == 0)
+		goto done;
+      done:
+	return ret;
+}
+
+/** 
+ *  @brief This function sends to the host the last transmitted packet,
+ *  filling the radiotap headers with transmission information.
+ *  
+ *  @param priv     A pointer to wlan_private structure
+ *  @param status   A 32 bit value containing transmission status.
+ *
+ *  @returns void
+ */
+void libertas_send_tx_feedback(wlan_private * priv)
+{
+	wlan_adapter *Adapter = priv->adapter;
+	struct TxRadiotapHdr *radiotap_hdr;
+	u32 status = Adapter->EventCause;
+	int txfail;
+	int try_count;
+
+	if (Adapter->radiomode != WLAN_RADIOMODE_RADIOTAP ||
+	    Adapter->CurrentTxSkb == NULL)
+		return;
+
+	radiotap_hdr = (struct TxRadiotapHdr *)Adapter->CurrentTxSkb->data;
+
+	if ((Adapter->debugmode & MRVDRV_DEBUG_TX_PATH) != 0)
+		HEXDUMP("TX feedback: ", (u8 *) radiotap_hdr,
+			min_t(unsigned int, Adapter->CurrentTxSkb->len, 100));
+
+	txfail = (status >> 24);
+
+#if 0
+	/* The version of roofnet that we've tested does not use this yet 
+	 * But it may be used in the future.
+	 */
+	if (txfail)
+		radiotap_hdr->flags &= IEEE80211_RADIOTAP_F_TX_FAIL;
+#endif
+	try_count = (status >> 16) & 0xff;
+	radiotap_hdr->data_retries = (try_count) ?
+	    (1 + Adapter->TxRetryCount - try_count) : 0;
+	libertas_upload_rx_packet(priv, Adapter->CurrentTxSkb);
+	Adapter->CurrentTxSkb = NULL;
+	priv->adapter->TxLockFlag = 0;
+	if (priv->adapter->MediaConnectStatus == WlanMediaStateConnected)
+		netif_wake_queue(priv->wlan_dev.netdev);
+}
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_types.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_types.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_types.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_types.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,349 @@
+/** @file wlan_types.h
+  * @brief This header file contains definition for global types
+  *
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/*************************************************************
+Change log:
+	10/11/05: add Doxygen format comments 
+	01/11/06: Add IEEE Association response type.  Add TSF TLV information.
+	01/31/06: Add support to selectively enabe the FW Scan channel filter
+	04/10/06: Add power_adapt_cfg_ext command
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+************************************************************/
+
+#ifndef _WLAN_TYPES_
+#define _WLAN_TYPES_
+
+#include <linux/if_ether.h>
+
+/** IEEE Type definitions  */
+enum IEEEtypes_ElementId {
+	SSID = 0,
+	SUPPORTED_RATES,
+	FH_PARAM_SET,
+	DS_PARAM_SET,
+	CF_PARAM_SET,
+	TIM,
+	IBSS_PARAM_SET,
+	COUNTRY_INFO = 7,
+
+	CHALLENGE_TEXT = 16,
+
+	EXTENDED_SUPPORTED_RATES = 50,
+
+	VENDOR_SPECIFIC_221 = 221,
+
+	WPA_IE = 221,
+	WPA2_IE = 48,
+
+	EXTRA_IE = 133,
+} __attribute__ ((packed));
+
+#define CAPINFO_MASK    (~( W_BIT_15 | W_BIT_14 |               \
+                            W_BIT_12 | W_BIT_11 | W_BIT_9) )
+
+struct IEEEtypes_CapInfo {
+	u8 Ess:1;
+	u8 Ibss:1;
+	u8 CfPollable:1;
+	u8 CfPollRqst:1;
+	u8 Privacy:1;
+	u8 ShortPreamble:1;
+	u8 Pbcc:1;
+	u8 ChanAgility:1;
+	u8 SpectrumMgmt:1;
+	u8 Rsrvd3:1;
+	u8 ShortSlotTime:1;
+	u8 Apsd:1;
+	u8 Rsvrd2:1;
+	u8 DSSSOFDM:1;
+	u8 Rsrvd1:2;
+} __attribute__ ((packed));
+
+/** IEEEtypes_CfParamSet */
+struct IEEEtypes_CfParamSet {
+	u8 ElementId;
+	u8 Len;
+	u8 CfpCnt;
+	u8 CfpPeriod;
+	u16 CfpMaxDuration;
+	u16 CfpDurationRemaining;
+} __attribute__ ((packed));
+
+struct IEEEtypes_IbssParamSet {
+	u8 ElementId;
+	u8 Len;
+	u16 AtimWindow;
+} __attribute__ ((packed));
+
+/** IEEEtypes_SsParamSet */
+union IEEEtypes_SsParamSet {
+	struct IEEEtypes_CfParamSet CfParamSet;
+	struct IEEEtypes_IbssParamSet IbssParamSet;
+} __attribute__ ((packed));
+
+/** IEEEtypes_FhParamSet */
+struct IEEEtypes_FhParamSet {
+	u8 ElementId;
+	u8 Len;
+	u16 DwellTime;
+	u8 HopSet;
+	u8 HopPattern;
+	u8 HopIndex;
+} __attribute__ ((packed));
+
+struct IEEEtypes_DsParamSet {
+	u8 ElementId;
+	u8 Len;
+	u8 CurrentChan;
+} __attribute__ ((packed));
+
+/** IEEEtypes_DsParamSet */
+union IEEEtypes_PhyParamSet {
+	struct IEEEtypes_FhParamSet FhParamSet;
+	struct IEEEtypes_DsParamSet DsParamSet;
+} __attribute__ ((packed));
+
+struct IEEEtypes_AssocRsp {
+	struct IEEEtypes_CapInfo Capability;
+	u16 StatusCode;
+	u16 AId;
+	u8 IEBuffer[1];
+} __attribute__ ((packed));
+
+/** TLV  type ID definition */
+#define PROPRIETARY_TLV_BASE_ID		0x0100
+
+/* Terminating TLV Type */
+#define MRVL_TERMINATE_TLV_ID		0xffff
+
+#define TLV_TYPE_SSID				0x0000
+#define TLV_TYPE_RATES				0x0001
+#define TLV_TYPE_PHY_FH				0x0002
+#define TLV_TYPE_PHY_DS				0x0003
+#define TLV_TYPE_CF				    0x0004
+#define TLV_TYPE_IBSS				0x0006
+
+#define TLV_TYPE_DOMAIN				0x0007
+
+#define TLV_TYPE_POWER_CAPABILITY	0x0021
+
+#define TLV_TYPE_KEY_MATERIAL       (PROPRIETARY_TLV_BASE_ID + 0)
+#define TLV_TYPE_CHANLIST           (PROPRIETARY_TLV_BASE_ID + 1)
+#define TLV_TYPE_NUMPROBES          (PROPRIETARY_TLV_BASE_ID + 2)
+#define TLV_TYPE_RSSI_LOW           (PROPRIETARY_TLV_BASE_ID + 4)
+#define TLV_TYPE_SNR_LOW            (PROPRIETARY_TLV_BASE_ID + 5)
+#define TLV_TYPE_FAILCOUNT          (PROPRIETARY_TLV_BASE_ID + 6)
+#define TLV_TYPE_BCNMISS            (PROPRIETARY_TLV_BASE_ID + 7)
+#define TLV_TYPE_LED_GPIO           (PROPRIETARY_TLV_BASE_ID + 8)
+#define TLV_TYPE_LEDBEHAVIOR        (PROPRIETARY_TLV_BASE_ID + 9)
+#define TLV_TYPE_PASSTHROUGH        (PROPRIETARY_TLV_BASE_ID + 10)
+#define TLV_TYPE_REASSOCAP          (PROPRIETARY_TLV_BASE_ID + 11)
+#define TLV_TYPE_POWER_TBL_2_4GHZ   (PROPRIETARY_TLV_BASE_ID + 12)
+#define TLV_TYPE_POWER_TBL_5GHZ     (PROPRIETARY_TLV_BASE_ID + 13)
+#define TLV_TYPE_BCASTPROBE	    (PROPRIETARY_TLV_BASE_ID + 14)
+#define TLV_TYPE_NUMSSID_PROBE	    (PROPRIETARY_TLV_BASE_ID + 15)
+#define TLV_TYPE_WMMQSTATUS   	    (PROPRIETARY_TLV_BASE_ID + 16)
+#define TLV_TYPE_CRYPTO_DATA	    (PROPRIETARY_TLV_BASE_ID + 17)
+#define TLV_TYPE_WILDCARDSSID	    (PROPRIETARY_TLV_BASE_ID + 18)
+#define TLV_TYPE_TSFTIMESTAMP	    (PROPRIETARY_TLV_BASE_ID + 19)
+#define TLV_TYPE_RSSI_HIGH          (PROPRIETARY_TLV_BASE_ID + 22)
+#define TLV_TYPE_SNR_HIGH           (PROPRIETARY_TLV_BASE_ID + 23)
+
+/** TLV related data structures*/
+/** MrvlIEtypesHeader */
+struct MrvlIEtypesHeader {
+	u16 Type;
+	u16 Len;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_Data */
+struct MrvlIEtypes_Data {
+	struct MrvlIEtypesHeader Header;
+	u8 Data[1];
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_RatesParamSet */
+struct MrvlIEtypes_RatesParamSet {
+	struct MrvlIEtypesHeader Header;
+	u8 Rates[1];
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_SsIdParamSet */
+struct MrvlIEtypes_SsIdParamSet {
+	struct MrvlIEtypesHeader Header;
+	u8 SsId[1];
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_WildCardSsIdParamSet */
+struct MrvlIEtypes_WildCardSsIdParamSet {
+	struct MrvlIEtypesHeader Header;
+	u8 MaxSsidLength;
+	u8 SsId[1];
+} __attribute__ ((packed));
+
+/** ChanScanMode */
+struct ChanScanMode {
+	u8 PassiveScan:1;
+	u8 DisableChanFilt:1;
+	u8 Reserved_2_7:6;
+} __attribute__ ((packed));
+
+/** ChanScanParamSet */
+struct ChanScanParamSet {
+	u8 RadioType;
+	u8 ChanNumber;
+	struct ChanScanMode ChanScanMode;
+	u16 MinScanTime;
+	u16 MaxScanTime;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_ChanListParamSet */
+struct MrvlIEtypes_ChanListParamSet {
+	struct MrvlIEtypesHeader Header;
+	struct ChanScanParamSet ChanScanParam[1];
+} __attribute__ ((packed));
+
+/** CfParamSet */
+struct CfParamSet {
+	u8 CfpCnt;
+	u8 CfpPeriod;
+	u16 CfpMaxDuration;
+	u16 CfpDurationRemaining;
+} __attribute__ ((packed));
+
+/** IbssParamSet */
+struct IbssParamSet {
+	u16 AtimWindow;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_SsParamSet */
+struct MrvlIEtypes_SsParamSet {
+	struct MrvlIEtypesHeader Header;
+	union {
+		struct CfParamSet CfParamSet[1];
+		struct IbssParamSet IbssParamSet[1];
+	} cf_ibss;
+} __attribute__ ((packed));
+
+/** FhParamSet */
+struct FhParamSet {
+	u16 DwellTime;
+	u8 HopSet;
+	u8 HopPattern;
+	u8 HopIndex;
+} __attribute__ ((packed));
+
+/** DsParamSet */
+struct DsParamSet {
+	u8 CurrentChan;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_PhyParamSet */
+struct MrvlIEtypes_PhyParamSet {
+	struct MrvlIEtypesHeader Header;
+	union {
+		struct FhParamSet FhParamSet[1];
+		struct DsParamSet DsParamSet[1];
+	} fh_ds;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_RsnParamSet */
+struct MrvlIEtypes_RsnParamSet {
+	struct MrvlIEtypesHeader Header;
+	u8 RsnIE[1];
+} __attribute__ ((packed));
+
+struct MrvlIEtypes_TsfTimestamp {
+	struct MrvlIEtypesHeader Header;
+	u64 tsfTable[1];
+} __attribute__ ((packed));
+
+/**  Local Power Capability */
+struct MrvlIEtypes_PowerCapability {
+	struct MrvlIEtypesHeader Header;
+	s8 MinPower;
+	s8 MaxPower;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_RssiParamSet */
+struct MrvlIEtypes_RssiThreshold {
+	struct MrvlIEtypesHeader Header;
+	u8 RSSIValue;
+	u8 RSSIFreq;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_SnrThreshold */
+struct MrvlIEtypes_SnrThreshold {
+	struct MrvlIEtypesHeader Header;
+	u8 SNRValue;
+	u8 SNRFreq;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_FailureCountt */
+struct MrvlIEtypes_FailureCount {
+	struct MrvlIEtypesHeader Header;
+	u8 FailValue;
+	u8 FailFreq;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_BeaconsMissed */
+struct _rvlIEtypes_BeaconsMissed {
+	struct MrvlIEtypesHeader Header;
+	u8 BeaconMissed;
+	u8 Reserved;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_NumProbes */
+struct MrvlIEtypes_NumProbes {
+	struct MrvlIEtypesHeader Header;
+	u16 NumProbes;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_BcastProbe */
+struct MrvlIEtypes_BcastProbe {
+	struct MrvlIEtypesHeader Header;
+	u16 BcastProbe;
+} __attribute__ ((packed));
+
+/** MrvlIEtypes_NumSSIDProbe */
+struct MrvlIEtypes_NumSSIDProbe {
+	struct MrvlIEtypesHeader Header;
+	u16 NumSSIDProbe;
+} __attribute__ ((packed));
+
+struct Led_Pin {
+	u8 Led;
+	u8 Pin;
+} __attribute__ ((packed));
+
+/* MrvlIEtypes_LedGpio */
+struct MrvlIEtypes_LedGpio {
+	struct MrvlIEtypesHeader Header;
+	struct Led_Pin LedPin[1];
+} __attribute__ ((packed));
+
+struct EthII_Hdr {
+	u8 dest_addr[ETH_ALEN];
+	u8 src_addr[ETH_ALEN];
+	u16 ethertype;
+} __attribute__ ((packed));
+
+#endif				/* _WLAN_TYPES_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_version.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_version.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_version.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_version.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,36 @@
+/** @file wlan_version.h
+  * @brief This file contains wlan driver version number.
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/04/05: Add Doxygen format comments
+	
+********************************************************/
+
+#define KERVER	"26"
+#define DRIVER_RELEASE_VERSION		KERVER"318.p4"
+
+#define FPNUM "14"
+
+const char libertas_driver_version[] = "COMM-USB8388-%s-" DRIVER_RELEASE_VERSION
+#ifdef	DEBUG_LEVEL2
+    "-dbg"
+#endif
+    " ";
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_wext.c linux-2.6-libertas/drivers/net/wireless/libertas/wlan_wext.c
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_wext.c	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_wext.c	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,2745 @@
+/** @file  wlan_wext.c 
+  * @brief This file contains ioctl functions
+  * 
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/10/05: Add Doxygen format comments
+	12/23/05: Modify libertas_find_BSSID_in_list to search entire table for
+	          duplicate BSSIDs when earlier matches are not compatible
+	12/26/05: Remove errant memcpy in libertas_idle_off; overwriting stack space
+	01/05/06: Add kernel 2.6.x support	
+	01/11/06: Change compile flag BULVERDE_SDIO to SD to support Monahans/Zylonite
+	01/11/06: Conditionalize new scan/join functions.
+	          Update statics/externs.  Move forward decl. from wlan_decl.h
+	04/06/06: Add TSPEC, queue metrics, and MSDU expiry support
+	04/10/06: Add hostcmd generic API
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+********************************************************/
+
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/if.h>
+#include <linux/if_arp.h>
+#include <linux/wireless.h>
+
+#include <net/iw_handler.h>
+
+#include "host.h"
+#include "radiotap.h"
+#include "wlan_decl.h"
+#include "wlan_defs.h"
+#include "wlan_dev.h"
+#include "wlan_join.h"
+#include "wlan_version.h"
+#include "wlan_wext.h"
+
+
+/** 
+ *  @brief Convert mw value to dbm value
+ *   
+ *  @param mw	   the value of mw
+ *  @return 	   the value of dbm
+ */
+static int mw_to_dbm(int mw)
+{
+	if (mw < 2)
+		return 0;
+	else if (mw < 3)
+		return 3;
+	else if (mw < 4)
+		return 5;
+	else if (mw < 6)
+		return 7;
+	else if (mw < 7)
+		return 8;
+	else if (mw < 8)
+		return 9;
+	else if (mw < 10)
+		return 10;
+	else if (mw < 13)
+		return 11;
+	else if (mw < 16)
+		return 12;
+	else if (mw < 20)
+		return 13;
+	else if (mw < 25)
+		return 14;
+	else if (mw < 32)
+		return 15;
+	else if (mw < 40)
+		return 16;
+	else if (mw < 50)
+		return 17;
+	else if (mw < 63)
+		return 18;
+	else if (mw < 79)
+		return 19;
+	else if (mw < 100)
+		return 20;
+	else
+		return 21;
+}
+
+/** 
+ *  @brief Find the channel frequency power info with specific channel
+ *   
+ *  @param adapter 	A pointer to wlan_adapter structure
+ *  @param band		it can be BAND_A, BAND_G or BAND_B
+ *  @param channel      the channel for looking	
+ *  @return 	   	A pointer to struct chan_freq_power structure or NULL if not find.
+ */
+struct chan_freq_power *libertas_find_cfp_by_band_and_channel(wlan_adapter * adapter,
+						 u8 band, u16 channel)
+{
+	struct chan_freq_power *cfp = NULL;
+	struct region_channel *rc;
+	int count = sizeof(adapter->region_channel) /
+	    sizeof(adapter->region_channel[0]);
+	int i, j;
+
+	for (j = 0; !cfp && (j < count); j++) {
+		rc = &adapter->region_channel[j];
+
+		if (adapter->State11D.Enable11D == ENABLE_11D) {
+			rc = &adapter->universal_channel[j];
+		}
+		if (!rc->Valid || !rc->CFP)
+			continue;
+		if (rc->Band != band)
+			continue;
+		for (i = 0; i < rc->NrCFP; i++) {
+			if (rc->CFP[i].Channel == channel) {
+				cfp = &rc->CFP[i];
+				break;
+			}
+		}
+	}
+
+	if (!cfp && channel)
+		PRINTM(INFO, "libertas_find_cfp_by_band_and_channel(): cannot find "
+		       "cfp by band %d & channel %d\n", band, channel);
+
+	return cfp;
+}
+
+/** 
+ *  @brief Find the channel frequency power info with specific frequency
+ *   
+ *  @param adapter 	A pointer to wlan_adapter structure
+ *  @param band		it can be BAND_A, BAND_G or BAND_B
+ *  @param freq	        the frequency for looking	
+ *  @return 	   	A pointer to struct chan_freq_power structure or NULL if not find.
+ */
+static struct chan_freq_power *find_cfp_by_band_and_freq(wlan_adapter * adapter,
+						     u8 band, u32 freq)
+{
+	struct chan_freq_power *cfp = NULL;
+	struct region_channel *rc;
+	int count = sizeof(adapter->region_channel) /
+	    sizeof(adapter->region_channel[0]);
+	int i, j;
+
+	for (j = 0; !cfp && (j < count); j++) {
+		rc = &adapter->region_channel[j];
+
+		if (adapter->State11D.Enable11D == ENABLE_11D) {
+			rc = &adapter->universal_channel[j];
+		}
+
+		if (!rc->Valid || !rc->CFP)
+			continue;
+		if (rc->Band != band)
+			continue;
+		for (i = 0; i < rc->NrCFP; i++) {
+			if (rc->CFP[i].Freq == freq) {
+				cfp = &rc->CFP[i];
+				break;
+			}
+		}
+	}
+
+	if (!cfp && freq)
+		PRINTM(INFO, "find_cfp_by_band_and_freql(): cannot find cfp by "
+		       "band %d & freq %d\n", band, freq);
+
+	return cfp;
+}
+
+/** 
+ *  @brief Update Current Channel 
+ *   
+ *  @param priv 		A pointer to wlan_private structure
+ *  @return 	   		WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+static int UpdateCurrentChannel(wlan_private * priv)
+{
+	int ret;
+
+	/*
+	 ** the channel in f/w could be out of sync, get the current channel
+	 */
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_CHANNEL,
+				    HostCmd_OPT_802_11_RF_CHANNEL_GET,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	PRINTM(INFO, "Current Channel = %d\n",
+	       priv->adapter->CurBssParams.channel);
+
+	return ret;
+}
+
+/** 
+ *  @brief Set Current Channel 
+ *   
+ *  @param priv 		A pointer to wlan_private structure
+ *  @param channel		The channel to be set. 
+ *  @return 	   		WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+static int SetCurrentChannel(wlan_private * priv, int channel)
+{
+	PRINTM(INFO, "Set Channel = %d\n", channel);
+
+	/* 
+	 **  Current channel is not set to AdhocChannel requested, set channel
+	 */
+	return (libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_RF_CHANNEL,
+				      HostCmd_OPT_802_11_RF_CHANNEL_SET,
+				      HostCmd_OPTION_WAITFORRSP, 0, &channel));
+}
+
+/** 
+ *  @brief Change Adhoc Channel
+ *   
+ *  @param priv 		A pointer to wlan_private structure
+ *  @param channel		The channel to be set. 
+ *  @return 	   		WLAN_STATUS_SUCCESS--success, WLAN_STATUS_FAILURE--fail
+ */
+static int ChangeAdhocChannel(wlan_private * priv, int channel)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_adapter *Adapter = priv->adapter;
+
+	Adapter->AdhocChannel = channel;
+
+	UpdateCurrentChannel(priv);
+
+	if (Adapter->CurBssParams.channel == Adapter->AdhocChannel) {
+		/* AdhocChannel is set to the current Channel already */
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	PRINTM(INFO, "Updating Channel from %d to %d\n",
+	       Adapter->CurBssParams.channel, Adapter->AdhocChannel);
+
+	SetCurrentChannel(priv, Adapter->AdhocChannel);
+
+	UpdateCurrentChannel(priv);
+
+	if (Adapter->CurBssParams.channel != Adapter->AdhocChannel) {
+		PRINTM(INFO, "Failed to updated Channel to %d, channel = %d\n",
+		       Adapter->AdhocChannel, Adapter->CurBssParams.channel);
+		LEAVE();
+		return WLAN_STATUS_FAILURE;
+	}
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		int i;
+		struct WLAN_802_11_SSID curAdhocSsid;
+
+		PRINTM(INFO, "Channel Changed while in an IBSS\n");
+
+		/* Copy the current ssid */
+		memcpy(&curAdhocSsid, &Adapter->CurBssParams.ssid,
+		       sizeof(struct WLAN_802_11_SSID));
+
+		/* Exit Adhoc mode */
+		PRINTM(INFO, "In ChangeAdhocChannel(): Sending Adhoc Stop\n");
+		ret = libertas_stop_adhoc_network(priv);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+		/* Scan for the network, do not save previous results.  Stale
+		 *   scan data will cause us to join a non-existant adhoc network
+		 */
+		libertas_send_specific_SSID_scan(priv, &curAdhocSsid, 0);
+
+		// find out the BSSID that matches the current SSID 
+		i = libertas_find_SSID_in_list(Adapter, &curAdhocSsid, NULL,
+				   Wlan802_11IBSS);
+
+		if (i >= 0) {
+			PRINTM(INFO, "SSID found at %d in List,"
+			       "so join\n", i);
+			libertas_join_adhoc_network(priv, &Adapter->ScanTable[i]);
+		} else {
+			// else send START command
+			PRINTM(INFO, "SSID not found in list, "
+			       "so creating adhoc with ssid = %s\n",
+			       curAdhocSsid.Ssid);
+			libertas_start_adhoc_network(priv, &curAdhocSsid);
+		}		// end of else (START command)
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set WPA key
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_encode_wpa(struct net_device *dev,
+			       struct iw_request_info *info,
+			       struct iw_point *dwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	struct WLAN_802_11_KEY *pKey;
+
+	ENTER();
+
+	pKey = (struct WLAN_802_11_KEY *)extra;
+
+	HEXDUMP("Key buffer: ", extra, dwrq->length);
+
+	HEXDUMP("KeyMaterial: ", (u8 *) pKey->KeyMaterial, pKey->KeyLength);
+
+	// current driver only supports key length of up to 32 bytes
+	if (pKey->KeyLength > MRVL_MAX_WPA_KEY_LENGTH) {
+		PRINTM(INFO, " Error in key length \n");
+		return WLAN_STATUS_FAILURE;
+	}
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_KEY_MATERIAL,
+				    HostCmd_ACT_SET,
+				    HostCmd_OPTION_WAITFORRSP,
+				    KEY_INFO_ENABLED, pKey);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/*
+ *  iwconfig ethX key on:	WEPEnabled;
+ *  iwconfig ethX key off:	WEPDisabled;
+ *  iwconfig ethX key [x]:	CurrentWepKeyIndex = x; WEPEnabled;
+ *  iwconfig ethX key [x] kstr:	WepKey[x] = kstr;
+ *  iwconfig ethX key kstr:	WepKey[CurrentWepKeyIndex] = kstr;
+ *
+ *  all:			Send command SET_WEP;
+ 				libertas_set_mac_packet_filter;
+ */
+
+/** 
+ *  @brief Set WEP key
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_encode_nonwpa(struct net_device *dev,
+				  struct iw_request_info *info,
+				  struct iw_point *dwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct MRVL_WEP_KEY *pWep;
+	struct WLAN_802_11_SSID ssid;
+	int index, PrevAuthMode;
+
+	ENTER();
+
+	pWep = &Adapter->WepKey[Adapter->CurrentWepKeyIndex];
+	PrevAuthMode = Adapter->SecInfo.AuthenticationMode;
+
+	index = (dwrq->flags & IW_ENCODE_INDEX) - 1;
+
+	if (index >= 4) {
+		PRINTM(INFO, "Key index #%d out of range.\n", index + 1);
+		return -EINVAL;
+	}
+
+	PRINTM(INFO, "Flags=0x%x, Length=%d Index=%d CurrentWepKeyIndex=%d\n",
+	       dwrq->flags, dwrq->length, index, Adapter->CurrentWepKeyIndex);
+
+	if (dwrq->length > 0) {
+		/* iwconfig ethX key [n] xxxxxxxxxxx 
+		 * Key has been provided by the user 
+		 */
+
+		/*
+		 * Check the size of the key 
+		 */
+
+		if (dwrq->length > MAX_WEP_KEY_SIZE) {
+			return -EINVAL;
+		}
+
+		/*
+		 * Check the index (none -> use current) 
+		 */
+
+		if (index < 0 || index > 3)	//invalid index or no index
+			index = Adapter->CurrentWepKeyIndex;
+		else		//index is given & valid
+			pWep = &Adapter->WepKey[index];
+
+		/*
+		 * Check if the key is not marked as invalid 
+		 */
+		if (!(dwrq->flags & IW_ENCODE_NOKEY)) {
+			/* Cleanup */
+			memset(pWep, 0, sizeof(struct MRVL_WEP_KEY));
+
+			/* Copy the key in the driver */
+			memcpy(pWep->KeyMaterial, extra, dwrq->length);
+
+			/* Set the length */
+			if (dwrq->length > MIN_WEP_KEY_SIZE) {
+				pWep->KeyLength = MAX_WEP_KEY_SIZE;
+			} else {
+				if (dwrq->length > 0) {
+					pWep->KeyLength = MIN_WEP_KEY_SIZE;
+				} else {
+					/* Disable the key */
+					pWep->KeyLength = 0;
+				}
+			}
+			pWep->KeyIndex = index;
+
+			if (Adapter->SecInfo.WEPStatus != Wlan802_11WEPEnabled) {
+				/*
+				 * The status is set as Key Absent 
+				 * so as to make sure we display the 
+				 * keys when iwlist ethX key is 
+				 * used - MPS 
+				 */
+
+				Adapter->SecInfo.WEPStatus =
+				    Wlan802_11WEPKeyAbsent;
+			}
+
+			PRINTM(INFO, "KeyIndex=%u KeyLength=%u\n",
+			       pWep->KeyIndex, pWep->KeyLength);
+			HEXDUMP("WepKey", (u8 *) pWep->KeyMaterial,
+				pWep->KeyLength);
+		}
+	} else {
+		/*
+		 * No key provided so it is either enable key, 
+		 * on or off */
+		if (dwrq->flags & IW_ENCODE_DISABLED) {
+			PRINTM(INFO,
+			       "******** iwconfig ethX key off **********\n");
+
+			Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled;
+			if (Adapter->SecInfo.AuthenticationMode ==
+			    Wlan802_11AuthModeShared)
+				Adapter->SecInfo.AuthenticationMode =
+				    Wlan802_11AuthModeOpen;
+		} else {
+			/* iwconfig ethX key [n]
+			 * iwconfig ethX key on 
+			 * Do we want to just set the transmit key index ? 
+			 */
+
+			if (index < 0 || index > 3) {
+				PRINTM(INFO,
+				       "******** iwconfig ethX key on **********\n");
+				index = Adapter->CurrentWepKeyIndex;
+			} else {
+				PRINTM(INFO,
+				       "******** iwconfig ethX key [x=%d] **********\n",
+				       index);
+				Adapter->CurrentWepKeyIndex = index;
+			}
+
+			/* Copy the required key as the current key */
+			pWep = &Adapter->WepKey[index];
+
+			if (!pWep->KeyLength) {
+				PRINTM(INFO,
+				       "Key not set,so cannot enable it\n");
+				return -EPERM;
+			}
+
+			Adapter->SecInfo.WEPStatus = Wlan802_11WEPEnabled;
+
+			HEXDUMP("KeyMaterial", (u8 *) pWep->KeyMaterial,
+				pWep->KeyLength);
+		}
+	}
+
+	if (pWep->KeyLength) {
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_SET_WEP,
+					    0, HostCmd_OPTION_WAITFORRSP,
+					    OID_802_11_ADD_WEP, NULL);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	}
+
+	if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) {
+		Adapter->CurrentPacketFilter |= HostCmd_ACT_MAC_WEP_ENABLE;
+	} else {
+		Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+	}
+
+	libertas_set_mac_packet_filter(priv);
+
+	if (dwrq->flags & IW_ENCODE_RESTRICTED) {
+		/* iwconfig ethX restricted key [1] */
+		Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeShared;
+		PRINTM(INFO, "Authentication mode restricted!\n");
+	} else if (dwrq->flags & IW_ENCODE_OPEN) {
+		/* iwconfig ethX key [2] open */
+		Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen;
+		PRINTM(INFO, "Authentication mode open!\n");
+	}
+
+	/*
+	 * If authentication mode changed - de-authenticate, set authentication
+	 * method and re-associate if we were previously associated.
+	 */
+	if (Adapter->SecInfo.AuthenticationMode != PrevAuthMode) {
+		if (Adapter->MediaConnectStatus == WlanMediaStateConnected &&
+		    Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+
+			/* keep a copy of the ssid associated with */
+			memcpy(&ssid, &Adapter->CurBssParams.ssid,
+			       sizeof(ssid));
+
+			/*
+			 * De-authenticate from AP 
+			 */
+
+			ret = libertas_send_deauthentication(priv);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+
+		} else {
+			/* reset ssid */
+			memset(&ssid, 0, sizeof(ssid));
+		}
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set Radio On/OFF
+ *   
+ *  @param priv                 A pointer to wlan_private structure
+ *  @option 			Radio Option
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail 
+ */
+int wlan_radio_ioctl(wlan_private * priv, u8 option)
+{
+	int ret = 0;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (Adapter->RadioOn != option) {
+		PRINTM(INFO, "Switching %s the Radio\n", option ? "On" : "Off");
+		Adapter->RadioOn = option;
+
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_RADIO_CONTROL,
+					    HostCmd_ACT_GEN_SET,
+					    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	}
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief Copy Rates
+ *   
+ *  @param dest                 A pointer to Dest Buf
+ *  @param src		        A pointer to Src Buf
+ *  @param len                  The len of Src Buf
+ *  @return 	   	        Number of Rates copyed 
+ */
+static inline int CopyRates(u8 * dest, int pos, u8 * src, int len)
+{
+	int i;
+
+	for (i = 0; i < len && src[i]; i++, pos++) {
+		if (pos >= sizeof(u8) * WLAN_SUPPORTED_RATES)
+			break;
+		dest[pos] = src[i];
+	}
+
+	return pos;
+}
+
+/** 
+ *  @brief Get active data rates
+ *   
+ *  @param Adapter              A pointer to wlan_adapter structure
+ *  @param rate		        The buf to return the active rates
+ *  @return 	   	        The number of Rates
+ */
+static int get_active_data_rates(wlan_adapter * Adapter,
+				 u8* rates)
+{
+	int k = 0;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus != WlanMediaStateConnected) {
+		if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+			//Infra. mode
+			PRINTM(INFO, "Infra\n");
+			k = CopyRates(rates, k, libertas_supported_rates,
+				      sizeof(libertas_supported_rates));
+		} else {
+			//ad-hoc mode
+			PRINTM(INFO, "Adhoc G\n");
+			k = CopyRates(rates, k, libertas_adhoc_rates_g,
+				      sizeof(libertas_adhoc_rates_g));
+		}
+	} else {
+		k = CopyRates(rates, 0, Adapter->CurBssParams.DataRates,
+			      Adapter->CurBssParams.NumOfRates);
+	}
+
+	LEAVE();
+
+	return k;
+}
+
+/** 
+ *  @brief Commit handler: called after a bunch of SET operations
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_config_commit(struct net_device *dev,
+			      struct iw_request_info *info,
+			      char *cwrq, char *extra)
+{
+	ENTER();
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get protocol name 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_name(struct net_device *dev, struct iw_request_info *info,
+			 char *cwrq, char *extra)
+{
+	const char *cp;
+	char comm[6] = { "COMM-" };
+	char mrvl[6] = { "MRVL-" };
+	int cnt;
+
+	ENTER();
+
+	strcpy(cwrq, mrvl);
+
+	cp = strstr(libertas_driver_version, comm);
+	if (cp == libertas_driver_version)	//skip leading "COMM-"
+		cp = libertas_driver_version + strlen(comm);
+	else
+		cp = libertas_driver_version;
+
+	cnt = strlen(mrvl);
+	cwrq += cnt;
+	while (cnt < 16 && (*cp != '-')) {
+		*cwrq++ = toupper(*cp++);
+		cnt++;
+	}
+	*cwrq = '\0';
+
+	LEAVE();
+
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get frequency
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param fwrq 		A pointer to iw_freq structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_freq(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_freq *fwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct chan_freq_power *cfp;
+
+	ENTER();
+
+	cfp = libertas_find_cfp_by_band_and_channel(Adapter, 0,
+					   Adapter->CurBssParams.channel);
+
+	if (!cfp) {
+		if (Adapter->CurBssParams.channel)
+			PRINTM(INFO, "Invalid channel=%d\n",
+			       Adapter->CurBssParams.channel);
+		return -EINVAL;
+	}
+
+	fwrq->m = (long)cfp->Freq * 100000;
+	fwrq->e = 1;
+
+	PRINTM(INFO, "freq=%u\n", fwrq->m);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get current BSSID
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param awrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_wap(struct net_device *dev, struct iw_request_info *info,
+			struct sockaddr *awrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		memcpy(awrq->sa_data, Adapter->CurBssParams.bssid, ETH_ALEN);
+	} else {
+		memset(awrq->sa_data, 0, ETH_ALEN);
+	}
+	awrq->sa_family = ARPHRD_ETHER;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set Adapter Node Name
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_nick(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/*
+	 * Check the size of the string 
+	 */
+
+	if (dwrq->length > 16) {
+		return -E2BIG;
+	}
+
+	memset(Adapter->nodeName, 0, sizeof(Adapter->nodeName));
+	memcpy(Adapter->nodeName, extra, dwrq->length);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get Adapter Node Name
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_nick(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/*
+	 * Get the Nick Name saved 
+	 */
+
+	strncpy(extra, Adapter->nodeName, 16);
+
+	extra[16] = '\0';
+
+	/*
+	 * If none, we may want to get the one that was set 
+	 */
+
+	/*
+	 * Push it out ! 
+	 */
+	dwrq->length = strlen(extra) + 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set RTS threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_rts(struct net_device *dev, struct iw_request_info *info,
+			struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int rthr = vwrq->value;
+
+	ENTER();
+
+	if (vwrq->disabled) {
+		Adapter->RTSThsd = rthr = MRVDRV_RTS_MAX_VALUE;
+	} else {
+		if (rthr < MRVDRV_RTS_MIN_VALUE || rthr > MRVDRV_RTS_MAX_VALUE)
+			return -EINVAL;
+		Adapter->RTSThsd = rthr;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_RTS_THRESHOLD, &rthr);
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief Get RTS threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_rts(struct net_device *dev, struct iw_request_info *info,
+			struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	Adapter->RTSThsd = 0;
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_RTS_THRESHOLD, NULL);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	vwrq->value = Adapter->RTSThsd;
+	vwrq->disabled = ((vwrq->value < MRVDRV_RTS_MIN_VALUE)
+			  || (vwrq->value > MRVDRV_RTS_MAX_VALUE));
+	vwrq->fixed = 1;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set Fragment threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_frag(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	int fthr = vwrq->value;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (vwrq->disabled) {
+		Adapter->FragThsd = fthr = MRVDRV_FRAG_MAX_VALUE;
+	} else {
+		if (fthr < MRVDRV_FRAG_MIN_VALUE
+		    || fthr > MRVDRV_FRAG_MAX_VALUE)
+			return -EINVAL;
+		Adapter->FragThsd = fthr;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_SET, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_FRAGMENTATION_THRESHOLD, &fthr);
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief Get Fragment threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_frag(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	Adapter->FragThsd = 0;
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_FRAGMENTATION_THRESHOLD, NULL);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	vwrq->value = Adapter->FragThsd;
+	vwrq->disabled = ((vwrq->value < MRVDRV_FRAG_MIN_VALUE)
+			  || (vwrq->value > MRVDRV_FRAG_MAX_VALUE));
+	vwrq->fixed = 1;
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief Get Wlan Mode
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_mode(struct net_device *dev,
+			 struct iw_request_info *info, u32 * uwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *adapter = priv->adapter;
+
+	ENTER();
+
+	switch (adapter->InfrastructureMode) {
+	case Wlan802_11IBSS:
+		*uwrq = IW_MODE_ADHOC;
+		break;
+
+	case Wlan802_11Infrastructure:
+		*uwrq = IW_MODE_INFRA;
+		break;
+
+	default:
+	case Wlan802_11AutoUnknown:
+		*uwrq = IW_MODE_AUTO;
+		break;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get Encryption key
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_encode(struct net_device *dev,
+			   struct iw_request_info *info,
+			   struct iw_point *dwrq, u8 * extra)
+{
+
+	wlan_private *priv = dev->priv;
+	wlan_adapter *adapter = priv->adapter;
+	int index = (dwrq->flags & IW_ENCODE_INDEX);
+
+	ENTER();
+
+	PRINTM(INFO, "flags=0x%x index=%d length=%d CurrentWepKeyIndex=%d\n",
+	       dwrq->flags, index, dwrq->length, adapter->CurrentWepKeyIndex);
+
+	dwrq->flags = 0;
+
+	/*
+	 * Check encryption mode 
+	 */
+
+	switch (adapter->SecInfo.AuthenticationMode) {
+	case Wlan802_11AuthModeOpen:
+		dwrq->flags = IW_ENCODE_OPEN;
+		break;
+
+	case Wlan802_11AuthModeShared:
+	case Wlan802_11AuthModeNetworkEAP:
+		dwrq->flags = IW_ENCODE_RESTRICTED;
+		break;
+	default:
+		dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN;
+		break;
+	}
+
+	if ((adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled)
+	    || (adapter->SecInfo.WEPStatus == Wlan802_11WEPKeyAbsent)
+	    || adapter->SecInfo.WPAEnabled || adapter->SecInfo.WPA2Enabled) {
+		dwrq->flags &= ~IW_ENCODE_DISABLED;
+	} else {
+		dwrq->flags |= IW_ENCODE_DISABLED;
+	}
+
+	memset(extra, 0, 16);
+
+	if (!index) {
+		/* Handle current key request   */
+		if ((adapter->WepKey[adapter->CurrentWepKeyIndex].KeyLength) &&
+		    (adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled)) {
+			index =
+			    adapter->WepKey[adapter->CurrentWepKeyIndex].
+			    KeyIndex;
+			memcpy(extra, adapter->WepKey[index].KeyMaterial,
+			       adapter->WepKey[index].KeyLength);
+			dwrq->length = adapter->WepKey[index].KeyLength;
+			/* return current key */
+			dwrq->flags |= (index + 1);
+			/* return WEP enabled */
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else if ((adapter->SecInfo.WPAEnabled)
+			   || (adapter->SecInfo.WPA2Enabled)
+		    ) {
+			/* return WPA enabled */
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			dwrq->flags |= IW_ENCODE_DISABLED;
+		}
+	} else {
+		/* Handle specific key requests */
+		index--;
+		if (adapter->WepKey[index].KeyLength) {
+			memcpy(extra, adapter->WepKey[index].KeyMaterial,
+			       adapter->WepKey[index].KeyLength);
+			dwrq->length = adapter->WepKey[index].KeyLength;
+			/* return current key */
+			dwrq->flags |= (index + 1);
+			/* return WEP enabled */
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else if ((adapter->SecInfo.WPAEnabled)
+			   || (adapter->SecInfo.WPA2Enabled)
+		    ) {
+			/* return WPA enabled */
+			dwrq->flags &= ~IW_ENCODE_DISABLED;
+		} else {
+			dwrq->flags |= IW_ENCODE_DISABLED;
+		}
+	}
+
+	dwrq->flags |= IW_ENCODE_NOKEY;
+
+	PRINTM(INFO, "Key:%02x:%02x:%02x:%02x:%02x:%02x KeyLen=%d\n",
+	       extra[0], extra[1], extra[2],
+	       extra[3], extra[4], extra[5], dwrq->length);
+
+	if (adapter->EncryptionStatus == Wlan802_11Encryption2Enabled
+	    && !dwrq->length) {
+		dwrq->length = MAX_WEP_KEY_SIZE;
+	}
+
+	PRINTM(INFO, "Return flags=0x%x\n", dwrq->flags);
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get TX Power
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_txpow(struct net_device *dev,
+			  struct iw_request_info *info,
+			  struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_RF_TX_POWER,
+				    HostCmd_ACT_TX_POWER_OPT_GET,
+				    HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	PRINTM(INFO, "TXPOWER GET %d dbm.\n", Adapter->TxPowerLevel);
+	vwrq->value = Adapter->TxPowerLevel;
+	vwrq->fixed = 1;
+	if (Adapter->RadioOn) {
+		vwrq->disabled = 0;
+		vwrq->flags = IW_TXPOW_DBM;
+	} else {
+		vwrq->disabled = 1;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set TX Retry Count
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_retry(struct net_device *dev, struct iw_request_info *info,
+			  struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *adapter = priv->adapter;
+
+	ENTER();
+
+	if (vwrq->flags == IW_RETRY_LIMIT) {
+		/* The MAC has a 4-bit Total_Tx_Count register
+		   Total_Tx_Count = 1 + Tx_Retry_Count */
+#define TX_RETRY_MIN 0
+#define TX_RETRY_MAX 14
+		if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX)
+			return -EINVAL;
+
+		/* Adding 1 to convert retry count to try count */
+		adapter->TxRetryCount = vwrq->value + 1;
+
+		ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_SNMP_MIB,
+					    HostCmd_ACT_SET,
+					    HostCmd_OPTION_WAITFORRSP,
+					    OID_802_11_TX_RETRYCOUNT, NULL);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+	} else {
+		return -EOPNOTSUPP;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get TX Retry Count
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_retry(struct net_device *dev, struct iw_request_info *info,
+			  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+
+	ENTER();
+	Adapter->TxRetryCount = 0;
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_SNMP_MIB,
+				    HostCmd_ACT_GET, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_TX_RETRYCOUNT, NULL);
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+	vwrq->disabled = 0;
+	if (!vwrq->flags) {
+		vwrq->flags = IW_RETRY_LIMIT;
+		/* Subtract 1 to convert try count to retry count */
+		vwrq->value = Adapter->TxRetryCount - 1;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Sort Channels
+ *   
+ *  @param freq 		A pointer to iw_freq structure
+ *  @param num		        number of Channels
+ *  @return 	   		NA
+ */
+static inline void sort_channels(struct iw_freq *freq, int num)
+{
+	int i, j;
+	struct iw_freq temp;
+
+	for (i = 0; i < num; i++)
+		for (j = i + 1; j < num; j++)
+			if (freq[i].i > freq[j].i) {
+				temp.i = freq[i].i;
+				temp.m = freq[i].m;
+
+				freq[i].i = freq[j].i;
+				freq[i].m = freq[j].m;
+
+				freq[j].i = temp.i;
+				freq[j].m = temp.m;
+			}
+}
+
+/* data rate listing
+	MULTI_BANDS:
+		abg		a	b	b/g
+   Infra 	G(12)		A(8)	B(4)	G(12)
+   Adhoc 	A+B(12)		A(8)	B(4)	B(4)
+
+	non-MULTI_BANDS:
+		   		 	b	b/g
+   Infra 	     		    	B(4)	G(12)
+   Adhoc 	      		    	B(4)	B(4)
+ */
+/** 
+ *  @brief Get Range Info
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_range(struct net_device *dev, struct iw_request_info *info,
+			  struct iw_point *dwrq, char *extra)
+{
+	int i, j;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	struct iw_range *range = (struct iw_range *)extra;
+	struct chan_freq_power *cfp;
+	u8 rates[WLAN_SUPPORTED_RATES];
+
+	u8 flag = 0;
+
+	ENTER();
+
+	dwrq->length = sizeof(struct iw_range);
+	memset(range, 0, sizeof(struct iw_range));
+
+	range->min_nwid = 0;
+	range->max_nwid = 0;
+
+	memset(rates, 0, sizeof(rates));
+	range->num_bitrates = get_active_data_rates(Adapter, rates);
+
+	for (i = 0; i < min_t(__u8, range->num_bitrates, IW_MAX_BITRATES) && rates[i];
+	     i++) {
+		range->bitrate[i] = (rates[i] & 0x7f) * 500000;
+	}
+	range->num_bitrates = i;
+	PRINTM(INFO, "IW_MAX_BITRATES=%d num_bitrates=%d\n", IW_MAX_BITRATES,
+	       range->num_bitrates);
+
+	range->num_frequency = 0;
+	if (libertas_get_state_11d(priv) == ENABLE_11D &&
+	    Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		u8 chan_no;
+		u8 band;
+
+		struct parsed_region_chan_11d *parsed_region_chan =
+		    &Adapter->parsed_region_chan;
+
+		if (parsed_region_chan == NULL) {
+			PRINTM(INFO, "11D:parsed_region_chan is NULL\n");
+			LEAVE();
+			return 0;
+		}
+		band = parsed_region_chan->band;
+		PRINTM(INFO, "band=%d NoOfChan=%d\n", band,
+		       parsed_region_chan->NoOfChan);
+
+		for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+		     && (i < parsed_region_chan->NoOfChan); i++) {
+			chan_no = parsed_region_chan->chanPwr[i].chan;
+			PRINTM(INFO, "chan_no=%d\n", chan_no);
+			range->freq[range->num_frequency].i = (long)chan_no;
+			range->freq[range->num_frequency].m =
+			    (long)libertas_chan_2_freq(chan_no, band) * 100000;
+			range->freq[range->num_frequency].e = 1;
+			range->num_frequency++;
+		}
+		flag = 1;
+	}
+	if (!flag) {
+		for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+		     && (j < sizeof(Adapter->region_channel)
+			 / sizeof(Adapter->region_channel[0])); j++) {
+			cfp = Adapter->region_channel[j].CFP;
+			for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES)
+			     && Adapter->region_channel[j].Valid
+			     && cfp
+			     && (i < Adapter->region_channel[j].NrCFP); i++) {
+				range->freq[range->num_frequency].i =
+				    (long)cfp->Channel;
+				range->freq[range->num_frequency].m =
+				    (long)cfp->Freq * 100000;
+				range->freq[range->num_frequency].e = 1;
+				cfp++;
+				range->num_frequency++;
+			}
+		}
+	}
+
+	PRINTM(INFO, "IW_MAX_FREQUENCIES=%d num_frequency=%d\n",
+	       IW_MAX_FREQUENCIES, range->num_frequency);
+
+	range->num_channels = range->num_frequency;
+
+	sort_channels(&range->freq[0], range->num_frequency);
+
+	/*
+	 * Set an indication of the max TCP throughput in bit/s that we can
+	 * expect using this interface 
+	 */
+	if (i > 2)
+		range->throughput = 5000 * 1000;
+	else
+		range->throughput = 1500 * 1000;
+
+	range->min_rts = MRVDRV_RTS_MIN_VALUE;
+	range->max_rts = MRVDRV_RTS_MAX_VALUE;
+	range->min_frag = MRVDRV_FRAG_MIN_VALUE;
+	range->max_frag = MRVDRV_FRAG_MAX_VALUE;
+
+	range->encoding_size[0] = 5;
+	range->encoding_size[1] = 13;
+	range->num_encoding_sizes = 2;
+	range->max_encoding_tokens = 4;
+
+	range->min_pmp = 1000000;
+	range->max_pmp = 120000000;
+	range->min_pmt = 1000;
+	range->max_pmt = 1000000;
+	range->pmp_flags = IW_POWER_PERIOD;
+	range->pmt_flags = IW_POWER_TIMEOUT;
+	range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R;
+
+	/*
+	 * Minimum version we recommend 
+	 */
+	range->we_version_source = 15;
+
+	/*
+	 * Version we are compiled with 
+	 */
+	range->we_version_compiled = WIRELESS_EXT;
+
+	range->retry_capa = IW_RETRY_LIMIT;
+	range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
+
+	range->min_retry = TX_RETRY_MIN;
+	range->max_retry = TX_RETRY_MAX;
+
+	/*
+	 * Set the qual, level and noise range values 
+	 */
+	range->max_qual.qual = 100;
+	range->max_qual.level = 0;
+	range->max_qual.noise = 0;
+	range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+	range->avg_qual.qual = 70;
+	/* TODO: Find real 'good' to 'bad' threshold value for RSSI */
+	range->avg_qual.level = 0;
+	range->avg_qual.noise = 0;
+	range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM;
+
+	range->sensitivity = 0;
+
+	/*
+	 * Setup the supported power level ranges 
+	 */
+	memset(range->txpower, 0, sizeof(range->txpower));
+	range->txpower[0] = 5;
+	range->txpower[1] = 7;
+	range->txpower[2] = 9;
+	range->txpower[3] = 11;
+	range->txpower[4] = 13;
+	range->txpower[5] = 15;
+	range->txpower[6] = 17;
+	range->txpower[7] = 19;
+
+	range->num_txpower = 8;
+	range->txpower_capa = IW_TXPOW_DBM;
+	range->txpower_capa |= IW_TXPOW_RANGE;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  Set power management 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_power(struct net_device *dev, struct iw_request_info *info,
+			  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	/* PS is currently supported only in Infrastructure Mode 
+	 * Remove this check if it is to be supported in IBSS mode also 
+	 */
+
+	if (vwrq->disabled) {
+		Adapter->PSMode = Wlan802_11PowerModeCAM;
+		if (Adapter->PSState != PS_STATE_FULL_POWER) {
+			libertas_ps_wakeup(priv, HostCmd_OPTION_WAITFORRSP);
+		}
+
+		return 0;
+	}
+
+	if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) {
+		PRINTM(INFO,
+		       "Setting power timeout command is not supported\n");
+		return -EINVAL;
+	} else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) {
+		PRINTM(INFO, "Setting power period command is not supported\n");
+		return -EINVAL;
+	}
+
+	if (Adapter->PSMode != Wlan802_11PowerModeCAM) {
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	Adapter->PSMode = Wlan802_11PowerModeMAX_PSP;
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		libertas_ps_sleep(priv, HostCmd_OPTION_WAITFORRSP);
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  Get power management 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_get_power(struct net_device *dev, struct iw_request_info *info,
+			  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int mode;
+
+	ENTER();
+
+	mode = Adapter->PSMode;
+
+	if ((vwrq->disabled = (mode == Wlan802_11PowerModeCAM))
+	    || Adapter->MediaConnectStatus == WlanMediaStateDisconnected) {
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	vwrq->value = 0;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  Set sensitivity threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+static int wlan_set_sens(struct net_device *dev, struct iw_request_info *info,
+			 struct iw_param *vwrq, char *extra)
+{
+	ENTER();
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief  Get sensitivity threshold
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_FAILURE
+ */
+static int wlan_get_sens(struct net_device *dev,
+			 struct iw_request_info *info, struct iw_param *vwrq,
+			 char *extra)
+{
+	ENTER();
+	LEAVE();
+	return WLAN_STATUS_FAILURE;
+}
+
+/*
+ * iwpriv settable callbacks 
+ */
+
+static const iw_handler wlan_private_handler[] = {
+	NULL,			/* SIOCIWFIRSTPRIV */
+};
+
+static const struct iw_priv_args wlan_private_args[] = {
+	/*
+	 * { cmd, set_args, get_args, name } 
+	 */
+	{
+	 WLANEXTSCAN,
+	 IW_PRIV_TYPE_INT,
+	 IW_PRIV_TYPE_CHAR | 2,
+	 "extscan"},
+
+	{
+	 WLANCISDUMP,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_BYTE | 512,
+	 "getcis"},
+
+	{
+	 WLANSCAN_TYPE,
+	 IW_PRIV_TYPE_CHAR | 8,
+	 IW_PRIV_TYPE_CHAR | 8,
+	 "scantype"},
+
+	{
+	 WLAN_SETINT_GETINT,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 ""},
+	{
+	 WLANNF,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getNF"},
+	{
+	 WLANRSSI,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getRSSI"},
+	{
+	 WLANENABLE11D,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "enable11d"},
+	{
+	 WLANADHOCGRATE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "adhocgrate"},
+
+	{
+	 WLAN_SUBCMD_SET_PRESCAN,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "prescan"},
+	{
+	 WLAN_SETONEINT_GETONEINT,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 ""},
+	{
+	 WLAN_BEACON_INTERVAL,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "bcninterval"},
+	{
+	 WLAN_LISTENINTRVL,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "lolisteninter"},
+	{
+	 WLAN_TXCONTROL,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "txcontrol"},
+	{
+	 WLAN_NULLPKTINTERVAL,
+	 IW_PRIV_TYPE_INT | 1,
+	 IW_PRIV_TYPE_INT | 1,
+	 "psnullinterval"},
+	/* Using iwpriv sub-command feature */
+	{
+	 WLAN_SETONEINT_GETNONE,	/* IOCTL: 24 */
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 ""},
+
+	{
+	 WLAN_SUBCMD_SETRXANTENNA,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setrxant"},
+	{
+	 WLAN_SUBCMD_SETTXANTENNA,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "settxant"},
+	{
+	 WLANSETAUTHALG,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "authalgs",
+	 },
+	{
+	 WLANSET8021XAUTHALG,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "8021xauthalgs",
+	 },
+	{
+	 WLANSETENCRYPTIONMODE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "encryptionmode",
+	 },
+	{
+	 WLANSETREGION,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setregioncode"},
+	{
+	 WLAN_SET_LISTEN_INTERVAL,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setlisteninter"},
+	{
+	 WLAN_SET_MULTIPLE_DTIM,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setmultipledtim"},
+	{
+	 WLAN_SET_ATIM_WINDOW,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "atimwindow"},
+	{
+	 WLANSETBCNAVG,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setbcnavg"},
+	{
+	 WLANSETDATAAVG,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "setdataavg"},
+	{
+	 WLAN_SET_LINKMODE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "linkmode"},
+	{
+	 WLAN_SET_RADIOMODE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "radiomode"},
+	{
+	 WLAN_SET_DEBUGMODE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 IW_PRIV_TYPE_NONE,
+	 "debugmode"},
+	{
+	 WLAN_SETNONE_GETONEINT,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 ""},
+	{
+	 WLANGETREGION,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getregioncode"},
+	{
+	 WLAN_GET_LISTEN_INTERVAL,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getlisteninter"},
+	{
+	 WLAN_GET_MULTIPLE_DTIM,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getmultipledtim"},
+	{
+	 WLAN_GET_TX_RATE,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "gettxrate"},
+	{
+	 WLANGETBCNAVG,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "getbcnavg"},
+	{
+	 WLAN_GET_LINKMODE,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "get_linkmode"},
+	{
+	 WLAN_GET_RADIOMODE,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "get_radiomode"},
+	{
+	 WLAN_GET_DEBUGMODE,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
+	 "get_debugmode"},
+	{
+	 WLAN_SETNONE_GETTWELVE_CHAR,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 12,
+	 ""},
+	{
+	 WLAN_SUBCMD_GETRXANTENNA,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 12,
+	 "getrxant"},
+	{
+	 WLAN_SUBCMD_GETTXANTENNA,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 12,
+	 "gettxant"},
+	{
+	 WLAN_GET_TSF,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 12,
+	 "gettsf"},
+	{
+	 WLAN_SETNONE_GETNONE,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 ""},
+	{
+	 WLANDEAUTH,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "deauth"},
+	{
+	 WLANADHOCSTOP,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "adhocstop"},
+	{
+	 WLANRADIOON,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "radioon"},
+	{
+	 WLANRADIOOFF,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "radiooff"},
+#ifdef REASSOCIATION
+	{
+	 WLANREASSOCIATIONAUTO,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "reasso-on"},
+	{
+	 WLANREASSOCIATIONUSER,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "reasso-off"},
+#endif				/* REASSOCIATION */
+	{
+	 WLANWLANIDLEON,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "wlanidle-on"},
+	{
+	 WLANWLANIDLEOFF,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "wlanidle-off"},
+	{
+	 WLAN_SUBCMD_DFT_RESET,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "dft_reset"},
+	{
+	 WLAN_SUBCMD_BT_RESET,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_NONE,
+	 "bt_reset"},
+	{
+	 WLAN_SET64CHAR_GET64CHAR,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 ""},
+	{
+	 WLANSLEEPPARAMS,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "sleepparams"},
+	/* DFT Management */
+	{
+	 WLAN_SUBCMD_DFT_ADD,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "dft_add"},
+	{
+	 WLAN_SUBCMD_DFT_DEL,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "dft_del"},
+	{
+	 WLAN_SUBCMD_DFT_LIST,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "dft_list"},
+	/* BT Management */
+	{
+	 WLAN_SUBCMD_BT_ADD,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "bt_add"},
+	{
+	 WLAN_SUBCMD_BT_DEL,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "bt_del"},
+	{
+	 WLAN_SUBCMD_BT_LIST,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "bt_list"},
+	{
+	 WLANSCAN_MODE,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "scanmode"},
+	{
+	 WLAN_GET_ADHOC_STATUS,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 IW_PRIV_TYPE_CHAR | 64,
+	 "getadhocstatus"},
+	{
+	 WLAN_SETWORDCHAR_GETNONE,
+	 IW_PRIV_TYPE_CHAR | 32,
+	 IW_PRIV_TYPE_NONE,
+	 ""},
+	{
+	 WLAN_SETNONE_GETWORDCHAR,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 128,
+	 ""},
+	{
+	 WLANVERSION,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 128,
+	 "version"},
+	{
+	 WLANSETWPAIE,
+	 IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 24,
+	 IW_PRIV_TYPE_NONE,
+	 "setwpaie"},
+	{
+	 WLAN_SETTENCHAR_GETNONE,
+	 IW_PRIV_TYPE_CHAR | 10,
+	 IW_PRIV_TYPE_NONE,
+	 ""},
+	{
+	 WLAN_SETNONE_GETTENCHAR,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | 10,
+	 ""},
+	{
+	 WLANGETLOG,
+	 IW_PRIV_TYPE_NONE,
+	 IW_PRIV_TYPE_CHAR | GETLOG_BUFSIZE,
+	 "getlog"},
+	{
+	 WLAN_SET_GET_SIXTEEN_INT,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 ""},
+	{
+	 WLAN_TPCCFG,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "tpccfg"},
+	{
+	 WLAN_POWERCFG,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "powercfg"},
+	{
+	 WLAN_AUTO_FREQ_SET,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "setafc"},
+	{
+	 WLAN_AUTO_FREQ_GET,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "getafc"},
+	{
+	 WLAN_SCANPROBES,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "scanprobes"},
+	{
+	 WLAN_LED_GPIO_CTRL,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "ledgpio"},
+	{
+	 WLAN_SLEEP_PERIOD,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "sleeppd"},
+	{
+	 WLAN_ADAPT_RATESET,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "rateadapt"},
+
+	{
+	 WLAN_INACTIVITY_TIMEOUT,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "inactivityto"},
+	{
+	 WLANSNR,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "getSNR"},
+	{
+	 WLAN_GET_RATE,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "getrate"},
+	{
+	 WLAN_GET_RXINFO,
+	 IW_PRIV_TYPE_INT | 16,
+	 IW_PRIV_TYPE_INT | 16,
+	 "getrxinfo"},
+
+	{
+	 WLAN_SET_GET_2K,	/* IOCTL : 14 */
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 ""},
+
+	{
+	 WLAN_SET_USER_SCAN,
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 "setuserscan"},
+	{
+	 WLAN_GET_SCAN_TABLE,
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 IW_PRIV_TYPE_BYTE | 2000,
+	 "getscantable"},
+};
+
+/** 
+ *  @brief Get wireless statistics
+ *
+ *  @param dev		A pointer to net_device structure
+ *  @return 	   	A pointer to iw_statistics buf
+ */
+static struct iw_statistics *wlan_get_wireless_stats(struct net_device *dev)
+{
+	enum {
+		POOR = 30,
+		FAIR = 60,
+		GOOD = 80,
+		VERY_GOOD = 90,
+		EXCELLENT = 95,
+		PERFECT = 100
+	};
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int ret = WLAN_STATUS_SUCCESS;
+	u32 rssi_qual;
+	u32 tx_qual;
+	u32 quality = 0;
+	int stats_valid = 0;
+	u8 rssi;
+
+	ENTER();
+
+	priv->wstats.status = Adapter->InfrastructureMode;
+
+	/* If we're not associated, all quality values are meaningless */
+	if (Adapter->MediaConnectStatus != WlanMediaStateConnected)
+		goto out;
+
+	/* send RSSI command to get beacon RSSI/NF, valid only if associated */
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_RSSI,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	if (ret)
+		goto out;
+
+	/* Quality by RSSI */
+	priv->wstats.qual.level =
+	    CAL_RSSI(Adapter->SNR[TYPE_BEACON][TYPE_NOAVG],
+	     Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+
+	if (Adapter->NF[TYPE_BEACON][TYPE_NOAVG] == 0) {
+		priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE;
+	} else {
+		priv->wstats.qual.noise =
+		    CAL_NF(Adapter->NF[TYPE_BEACON][TYPE_NOAVG]);
+	}
+
+	PRINTM(INFO, "Signal Level = %#x\n", priv->wstats.qual.level);
+	PRINTM(INFO, "Noise = %#x\n", priv->wstats.qual.noise);
+
+	rssi = priv->wstats.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE;
+	if (rssi < 15)
+		rssi_qual = rssi * POOR / 10;
+	else if (rssi < 20)
+		rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR;
+	else if (rssi < 30)
+		rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR;
+	else if (rssi < 40)
+		rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) /
+		    10 + GOOD;
+	else
+		rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) /
+		    10 + VERY_GOOD;
+	quality = rssi_qual;
+
+	/* Quality by TX errors */
+	priv->wstats.discard.retries = priv->stats.tx_errors;
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_GET_LOG,
+				    0, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+	if (!ret) {
+		u32 tx_retries = Adapter->LogMsg.retry;
+
+		if (tx_retries > 75)
+			tx_qual = (90 - tx_retries) * POOR / 15;
+		else if (tx_retries > 70)
+			tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR;
+		else if (tx_retries > 65)
+			tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR;
+		else if (tx_retries > 50)
+			tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) /
+			    15 + GOOD;
+		else
+			tx_qual = (50 - tx_retries) *
+			    (PERFECT - VERY_GOOD) / 50 + VERY_GOOD;
+		quality = min(quality, tx_qual);
+
+		priv->wstats.discard.code = Adapter->LogMsg.wepundecryptable;
+		priv->wstats.discard.fragment = Adapter->LogMsg.fcserror;
+		priv->wstats.discard.retries = tx_retries;
+		priv->wstats.discard.misc = Adapter->LogMsg.ackfailure;
+	}
+
+	/* Calculate quality */
+	priv->wstats.qual.qual = max(quality, (u32)100);
+	priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+	stats_valid = 1;
+
+out:
+	if (!stats_valid) {
+		priv->wstats.miss.beacon = 0;
+		priv->wstats.discard.retries = 0;
+		priv->wstats.qual.qual = 0;
+		priv->wstats.qual.level = 0;
+		priv->wstats.qual.noise = 0;
+		priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED;
+		priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID |
+		    IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID;
+	}
+
+	LEAVE ();
+	return &priv->wstats;
+
+
+}
+
+/** 
+ *  @brief Set frequency
+ *   
+ *  @param priv 		A pointer to wlan_private structure
+ *  @param info			A pointer to iw_request_info structure 
+ *  @param fwrq			A pointer to iw_freq structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS--success, otherwise--fail
+ */
+int wlan_set_freq(struct net_device *dev, struct iw_request_info *info,
+		  struct iw_freq *fwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	int rc = -EINPROGRESS;	/* Call commit handler */
+	struct chan_freq_power *cfp;
+
+	ENTER();
+
+	/*
+	 * If setting by frequency, convert to a channel 
+	 */
+	if (fwrq->e == 1) {
+
+		long f = fwrq->m / 100000;
+		int c = 0;
+
+		cfp = find_cfp_by_band_and_freq(Adapter, 0, f);
+		if (!cfp) {
+			PRINTM(INFO, "Invalid freq=%ld\n", f);
+			return -EINVAL;
+		}
+
+		c = (int)cfp->Channel;
+
+		if (c < 0)
+			return -EINVAL;
+
+		fwrq->e = 0;
+		fwrq->m = c;
+	}
+
+	/*
+	 * Setting by channel number 
+	 */
+	if (fwrq->m > 1000 || fwrq->e > 0) {
+		rc = -EOPNOTSUPP;
+	} else {
+		int channel = fwrq->m;
+
+		cfp = libertas_find_cfp_by_band_and_channel(Adapter, 0, channel);
+		if (!cfp) {
+			rc = -EINVAL;
+		} else {
+			if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
+				rc = ChangeAdhocChannel(priv, channel);
+				/*  If station is WEP enabled, send the 
+				 *  command to set WEP in firmware
+				 */
+				if (Adapter->SecInfo.WEPStatus ==
+				    Wlan802_11WEPEnabled) {
+					PRINTM(INFO, "set_freq: WEP Enabled\n");
+					ret = libertas_prepare_and_send_command(priv,
+								    HostCmd_CMD_802_11_SET_WEP,
+								    0,
+								    HostCmd_OPTION_WAITFORRSP,
+								    OID_802_11_ADD_WEP,
+								    NULL);
+
+					if (ret) {
+						LEAVE();
+						return ret;
+					}
+
+					Adapter->CurrentPacketFilter |=
+					    HostCmd_ACT_MAC_WEP_ENABLE;
+
+					libertas_set_mac_packet_filter(priv);
+				}
+			} else {
+				rc = -EOPNOTSUPP;
+			}
+		}
+	}
+
+	LEAVE();
+	return rc;
+}
+
+/** 
+ *  @brief use index to get the data rate
+ *   
+ *  @param index                The index of data rate
+ *  @return 	   		data rate or 0 
+ */
+u32 libertas_index_to_data_rate(u8 index)
+{
+	if (index >= sizeof(libertas_wlan_data_rates))
+		index = 0;
+
+	return libertas_wlan_data_rates[index];
+}
+
+/** 
+ *  @brief use rate to get the index
+ *   
+ *  @param rate                 data rate
+ *  @return 	   		index or 0 
+ */
+u8 libertas_data_rate_to_index(u32 rate)
+{
+	u8 *ptr;
+
+	if (rate)
+		if ((ptr = memchr(libertas_wlan_data_rates, (u8) rate,
+				  sizeof(libertas_wlan_data_rates))))
+			return (ptr - libertas_wlan_data_rates);
+
+	return 0;
+}
+
+/** 
+ *  @brief set data rate
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_set_rate(struct net_device *dev, struct iw_request_info *info,
+		  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+	u32 data_rate;
+	u16 action;
+	int ret = WLAN_STATUS_SUCCESS;
+	u8 rates[WLAN_SUPPORTED_RATES];
+	u8 *rate;
+
+	ENTER();
+
+	PRINTM(INFO, "Vwrq->value = %d\n", vwrq->value);
+
+	if (vwrq->value == -1) {
+		action = HostCmd_ACT_SET_TX_AUTO;	// Auto
+		Adapter->Is_DataRate_Auto = 1;
+		Adapter->DataRate = 0;
+	} else {
+		if (vwrq->value % 100000) {
+			return -EINVAL;
+		}
+
+		data_rate = vwrq->value / 500000;
+
+		memset(rates, 0, sizeof(rates));
+		get_active_data_rates(Adapter, rates);
+		rate = rates;
+		while (*rate) {
+			PRINTM(INFO, "Rate=0x%X  Wanted=0x%X\n", *rate,
+			       data_rate);
+			if ((*rate & 0x7f) == (data_rate & 0x7f))
+				break;
+			rate++;
+		}
+		if (!*rate) {
+			PRINTM(MSG, "The fixed data rate 0x%X is out "
+			       "of range.\n", data_rate);
+			return -EINVAL;
+		}
+
+		Adapter->DataRate = data_rate;
+		action = HostCmd_ACT_SET_TX_FIX_RATE;
+		Adapter->Is_DataRate_Auto = 0;
+	}
+
+	ret = libertas_prepare_and_send_command(priv, HostCmd_CMD_802_11_DATA_RATE,
+				    action, HostCmd_OPTION_WAITFORRSP, 0, NULL);
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief get data rate
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_get_rate(struct net_device *dev, struct iw_request_info *info,
+		  struct iw_param *vwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+
+	if (Adapter->Is_DataRate_Auto) {
+		vwrq->fixed = 0;
+	} else {
+		vwrq->fixed = 1;
+	}
+
+	vwrq->value = Adapter->DataRate * 500000;
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief set wireless mode 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_set_mode(struct net_device *dev,
+		  struct iw_request_info *info, u32 * uwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	enum WLAN_802_11_NETWORK_INFRASTRUCTURE WantedMode;
+
+	ENTER();
+
+	switch (*uwrq) {
+	case IW_MODE_ADHOC:
+		PRINTM(INFO, "Wanted Mode is ad-hoc: current DataRate=%#x\n",
+		       Adapter->DataRate);
+		WantedMode = Wlan802_11IBSS;
+		Adapter->AdhocChannel = DEFAULT_AD_HOC_CHANNEL;
+		break;
+
+	case IW_MODE_INFRA:
+		PRINTM(INFO, "Wanted Mode is Infrastructure\n");
+		WantedMode = Wlan802_11Infrastructure;
+		break;
+
+	case IW_MODE_AUTO:
+		PRINTM(INFO, "Wanted Mode is Auto\n");
+		WantedMode = Wlan802_11AutoUnknown;
+		break;
+
+	default:
+		PRINTM(INFO, "Wanted Mode is Unknown: 0x%x\n", *uwrq);
+		return -EINVAL;
+	}
+
+	if (Adapter->InfrastructureMode == WantedMode ||
+	    WantedMode == Wlan802_11AutoUnknown) {
+		PRINTM(INFO, "Already set to required mode! No change!\n");
+
+		Adapter->InfrastructureMode = WantedMode;
+
+		LEAVE();
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+		if (Adapter->PSState != PS_STATE_FULL_POWER) {
+			libertas_ps_wakeup(priv, HostCmd_OPTION_WAITFORRSP);
+		}
+		Adapter->PSMode = Wlan802_11PowerModeCAM;
+	}
+
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		if (Adapter->InfrastructureMode == Wlan802_11Infrastructure) {
+			ret = libertas_send_deauthentication(priv);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		} else if (Adapter->InfrastructureMode == Wlan802_11IBSS) {
+			/* If current mode is Adhoc, clean stale information */
+			ret = libertas_stop_adhoc_network(priv);
+
+			if (ret) {
+				LEAVE();
+				return ret;
+			}
+		}
+	}
+
+	if (Adapter->SecInfo.WEPStatus == Wlan802_11WEPEnabled) {
+		/* If there is a key with the specified SSID, 
+		 * send REMOVE WEP command, to make sure we clean up
+		 * the WEP keys in firmware
+		 */
+		ret = libertas_prepare_and_send_command(priv,
+					    HostCmd_CMD_802_11_SET_WEP,
+					    0, HostCmd_OPTION_WAITFORRSP,
+					    OID_802_11_REMOVE_WEP, NULL);
+
+		if (ret) {
+			LEAVE();
+			return ret;
+		}
+
+		Adapter->CurrentPacketFilter &= ~HostCmd_ACT_MAC_WEP_ENABLE;
+
+		libertas_set_mac_packet_filter(priv);
+	}
+
+	Adapter->SecInfo.WEPStatus = Wlan802_11WEPDisabled;
+	Adapter->SecInfo.AuthenticationMode = Wlan802_11AuthModeOpen;
+
+	Adapter->InfrastructureMode = WantedMode;
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_SNMP_MIB,
+				    0, HostCmd_OPTION_WAITFORRSP,
+				    OID_802_11_INFRASTRUCTURE_MODE, NULL);
+
+	if (ret) {
+		LEAVE();
+		return ret;
+	}
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Set Encryption key
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_set_encode(struct net_device *dev,
+		    struct iw_request_info *info,
+		    struct iw_point *dwrq, char *extra)
+{
+
+	struct WLAN_802_11_KEY *pKey = NULL;
+
+	ENTER();
+
+	if (dwrq->length > MAX_WEP_KEY_SIZE) {
+		pKey = (struct WLAN_802_11_KEY *)extra;
+
+		if (pKey->KeyLength <= MAX_WEP_KEY_SIZE) {
+			//dynamic WEP
+			dwrq->length = pKey->KeyLength;
+			dwrq->flags = pKey->KeyIndex + 1;
+			return wlan_set_encode_nonwpa(dev, info, dwrq,
+						      pKey->KeyMaterial);
+		} else {
+			//WPA
+			return wlan_set_encode_wpa(dev, info, dwrq, extra);
+		}
+	} else {
+		//static WEP
+		PRINTM(INFO, "Setting WEP\n");
+		return wlan_set_encode_nonwpa(dev, info, dwrq, extra);
+	}
+
+	return -EINVAL;
+}
+
+/** 
+ *  @brief set tx power 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_set_txpow(struct net_device *dev, struct iw_request_info *info,
+		   struct iw_param *vwrq, char *extra)
+{
+	int ret = WLAN_STATUS_SUCCESS;
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	u16 dbm;
+
+	ENTER();
+
+	if (vwrq->disabled) {
+		wlan_radio_ioctl(priv, RADIO_OFF);
+		return WLAN_STATUS_SUCCESS;
+	}
+
+	Adapter->Preamble = HostCmd_TYPE_AUTO_PREAMBLE;
+
+	wlan_radio_ioctl(priv, RADIO_ON);
+
+	if ((vwrq->flags & IW_TXPOW_TYPE) == IW_TXPOW_MWATT) {
+		dbm = (u16) mw_to_dbm(vwrq->value);
+	} else
+		dbm = (u16) vwrq->value;
+
+	/* auto tx power control */
+
+	if (vwrq->fixed == 0)
+		dbm = 0xffff;
+
+	PRINTM(INFO, "<1>TXPOWER SET %d dbm.\n", dbm);
+
+	ret = libertas_prepare_and_send_command(priv,
+				    HostCmd_CMD_802_11_RF_TX_POWER,
+				    HostCmd_ACT_TX_POWER_OPT_SET_LOW,
+				    HostCmd_OPTION_WAITFORRSP, 0, (void *)&dbm);
+
+	LEAVE();
+	return ret;
+}
+
+/** 
+ *  @brief Get current essid 
+ *   
+ *  @param dev                  A pointer to net_device structure
+ *  @param info			A pointer to iw_request_info structure
+ *  @param vwrq 		A pointer to iw_param structure
+ *  @param extra		A pointer to extra data buf
+ *  @return 	   		WLAN_STATUS_SUCCESS --success, otherwise fail
+ */
+int wlan_get_essid(struct net_device *dev, struct iw_request_info *info,
+		   struct iw_point *dwrq, char *extra)
+{
+	wlan_private *priv = dev->priv;
+	wlan_adapter *Adapter = priv->adapter;
+
+	ENTER();
+	/*
+	 * Note : if dwrq->flags != 0, we should get the relevant SSID from
+	 * the SSID list... 
+	 */
+
+	/*
+	 * Get the current SSID 
+	 */
+	if (Adapter->MediaConnectStatus == WlanMediaStateConnected) {
+		memcpy(extra, Adapter->CurBssParams.ssid.Ssid,
+		       Adapter->CurBssParams.ssid.SsidLength);
+		extra[Adapter->CurBssParams.ssid.SsidLength] = '\0';
+	} else {
+		memset(extra, 0, 32);
+		extra[Adapter->CurBssParams.ssid.SsidLength] = '\0';
+	}
+	/*
+	 * If none, we may want to get the one that was set 
+	 */
+
+	/* To make the driver backward compatible with WPA supplicant v0.2.4 */
+	if (dwrq->length == 32)	/* check with WPA supplicant buffer size */
+		dwrq->length = min_t(size_t, Adapter->CurBssParams.ssid.SsidLength,
+				   IW_ESSID_MAX_SIZE);
+	else
+		dwrq->length = Adapter->CurBssParams.ssid.SsidLength + 1;
+
+	dwrq->flags = 1;	/* active */
+
+	LEAVE();
+	return WLAN_STATUS_SUCCESS;
+}
+
+/** 
+ *  @brief Get version 
+ *   
+ *  @param adapter              A pointer to wlan_adapter structure
+ *  @param version		A pointer to version buffer
+ *  @param maxlen		max length of version buffer
+ *  @return 	   		NA
+ */
+void libertas_get_version(wlan_adapter * adapter, char *version, int maxlen)
+{
+	union {
+		u32 l;
+		u8 c[4];
+	} ver;
+	char fwver[32];
+
+	ver.l = adapter->FWReleaseNumber;
+	if (ver.c[3] == 0)
+		sprintf(fwver, "%u.%u.%u", ver.c[2], ver.c[1], ver.c[0]);
+	else
+		sprintf(fwver, "%u.%u.%u.p%u",
+			ver.c[2], ver.c[1], ver.c[0], ver.c[3]);
+
+	snprintf(version, maxlen, libertas_driver_version, fwver);
+}
+
+
+/*
+ * iwconfig settable callbacks 
+ */
+static const iw_handler wlan_handler[] = {
+	(iw_handler) wlan_config_commit,	/* SIOCSIWCOMMIT */
+	(iw_handler) wlan_get_name,	/* SIOCGIWNAME */
+	(iw_handler) NULL,	/* SIOCSIWNWID */
+	(iw_handler) NULL,	/* SIOCGIWNWID */
+	(iw_handler) wlan_set_freq,	/* SIOCSIWFREQ */
+	(iw_handler) wlan_get_freq,	/* SIOCGIWFREQ */
+	(iw_handler) wlan_set_mode,	/* SIOCSIWMODE */
+	(iw_handler) wlan_get_mode,	/* SIOCGIWMODE */
+	(iw_handler) wlan_set_sens,	/* SIOCSIWSENS */
+	(iw_handler) wlan_get_sens,	/* SIOCGIWSENS */
+	(iw_handler) NULL,	/* SIOCSIWRANGE */
+	(iw_handler) wlan_get_range,	/* SIOCGIWRANGE */
+	(iw_handler) NULL,	/* SIOCSIWPRIV */
+	(iw_handler) NULL,	/* SIOCGIWPRIV */
+	(iw_handler) NULL,	/* SIOCSIWSTATS */
+	(iw_handler) NULL,	/* SIOCGIWSTATS */
+	iw_handler_set_spy,	/* SIOCSIWSPY */
+	iw_handler_get_spy,	/* SIOCGIWSPY */
+	iw_handler_set_thrspy,	/* SIOCSIWTHRSPY */
+	iw_handler_get_thrspy,	/* SIOCGIWTHRSPY */
+	(iw_handler) libertas_set_wap,	/* SIOCSIWAP */
+	(iw_handler) wlan_get_wap,	/* SIOCGIWAP */
+	(iw_handler) NULL,	/* -- hole -- */
+	//(iw_handler) wlan_get_aplist,         /* SIOCGIWAPLIST */
+	NULL,			/* SIOCGIWAPLIST */
+	(iw_handler) libertas_set_scan,	/* SIOCSIWSCAN */
+	(iw_handler) libertas_get_scan,	/* SIOCGIWSCAN */
+	(iw_handler) libertas_set_essid,	/* SIOCSIWESSID */
+	(iw_handler) wlan_get_essid,	/* SIOCGIWESSID */
+	(iw_handler) wlan_set_nick,	/* SIOCSIWNICKN */
+	(iw_handler) wlan_get_nick,	/* SIOCGIWNICKN */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) wlan_set_rate,	/* SIOCSIWRATE */
+	(iw_handler) wlan_get_rate,	/* SIOCGIWRATE */
+	(iw_handler) wlan_set_rts,	/* SIOCSIWRTS */
+	(iw_handler) wlan_get_rts,	/* SIOCGIWRTS */
+	(iw_handler) wlan_set_frag,	/* SIOCSIWFRAG */
+	(iw_handler) wlan_get_frag,	/* SIOCGIWFRAG */
+	(iw_handler) wlan_set_txpow,	/* SIOCSIWTXPOW */
+	(iw_handler) wlan_get_txpow,	/* SIOCGIWTXPOW */
+	(iw_handler) wlan_set_retry,	/* SIOCSIWRETRY */
+	(iw_handler) wlan_get_retry,	/* SIOCGIWRETRY */
+	(iw_handler) wlan_set_encode,	/* SIOCSIWENCODE */
+	(iw_handler) wlan_get_encode,	/* SIOCGIWENCODE */
+	(iw_handler) wlan_set_power,	/* SIOCSIWPOWER */
+	(iw_handler) wlan_get_power,	/* SIOCGIWPOWER */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+	(iw_handler) NULL,	/* -- hole -- */
+};
+
+struct iw_handler_def libertas_handler_def = {
+	.num_standard	= sizeof(wlan_handler) / sizeof(iw_handler),
+	.num_private	= sizeof(wlan_private_handler) / sizeof(iw_handler),
+	.num_private_args = sizeof(wlan_private_args) /
+		sizeof(struct iw_priv_args),
+	.standard	= (iw_handler *) wlan_handler,
+	.private	= (iw_handler *) wlan_private_handler,
+	.private_args	= (struct iw_priv_args *)wlan_private_args,
+	.get_wireless_stats = wlan_get_wireless_stats,
+};
diff -Nur -p linux-2.6-orig/drivers/net/wireless/libertas/wlan_wext.h linux-2.6-libertas/drivers/net/wireless/libertas/wlan_wext.h
--- linux-2.6-orig/drivers/net/wireless/libertas/wlan_wext.h	1969-12-31 21:00:00.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/libertas/wlan_wext.h	2006-08-22 01:37:03.000000000 -0300
@@ -0,0 +1,281 @@
+/** @file wlan_wext.h
+  * @brief This file contains definition for IOCTL call.
+  *  
+  * (c) Copyright © 2003-2006, Marvell International Ltd. 
+  * All Rights Reserved
+  *
+  * This software file (the "File") is distributed by Marvell International 
+  * Ltd. under the terms of the GNU General Public License Version 2, June 1991 
+  * (the "License").  You may use, redistribute and/or modify this File in 
+  * accordance with the terms and conditions of the License, a copy of which 
+  * is available along with the File in the license.txt file or by writing to 
+  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 
+  * 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
+  *
+  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE 
+  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE 
+  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about 
+  * this warranty disclaimer.
+  *
+  */
+/********************************************************
+Change log:
+	10/11/05: Add Doxygen format comments
+	12/19/05: Correct a typo in structure _wlan_ioctl_wmm_tspec
+	01/11/06: Change compile flag BULVERDE_SDIO to SD to support Monahans/Zylonite
+	01/11/06: Conditionalize new scan/join ioctls
+	04/10/06: Add hostcmd generic API
+	04/18/06: Remove old Subscrive Event and add new Subscribe Event
+		  implementation through generic hostcmd API
+********************************************************/
+
+#ifndef	_WLAN_WEXT_H_
+#define	_WLAN_WEXT_H_
+
+#define SUBCMD_OFFSET			4
+/** PRIVATE CMD ID */
+#define	WLANIOCTL			SIOCIWFIRSTPRIV
+
+#define WLANSETWPAIE			(WLANIOCTL + 0)
+#define WLANCISDUMP 			(WLANIOCTL + 1)
+#define	WLANREGRDWR			(WLANIOCTL + 3)
+#define MAX_EEPROM_DATA     			256
+#define	WLANHOSTCMD			(WLANIOCTL + 4)
+
+#define WLAN_SETINT_GETINT		(WLANIOCTL + 7)
+#define WLANNF					1
+#define WLANRSSI				2
+#define WLANENABLE11D				5
+#define WLANADHOCGRATE				6
+#define WLAN_SUBCMD_SET_PRESCAN			11
+
+#define WLAN_SETNONE_GETNONE	        (WLANIOCTL + 8)
+#define WLANDEAUTH                  		1
+#define WLANRADIOON                 		2
+#define WLANRADIOOFF                		3
+#define WLANREMOVEADHOCAES          		4
+#define WLANADHOCSTOP               		5
+#define WLANCIPHERTEST              		6
+#define WLANCRYPTOTEST				7
+#ifdef REASSOCIATION
+#define WLANREASSOCIATIONAUTO			8
+#define WLANREASSOCIATIONUSER			9
+#endif				/* REASSOCIATION */
+
+#define WLANWLANIDLEON				10
+#define WLANWLANIDLEOFF				11
+#define WLAN_SUBCMD_DFT_RESET			12
+#define WLAN_SUBCMD_BT_RESET			13
+
+#define WLANGETLOG                  	(WLANIOCTL + 9)
+#define WLAN_SETCONF_GETCONF		(WLANIOCTL + 10)
+
+#define GETLOG_BUFSIZE  300
+
+#define WLANSCAN_TYPE			(WLANIOCTL + 11)
+
+#define WLAN_SET_GET_2K         (WLANIOCTL + 13)
+#define WLAN_SET_USER_SCAN              1
+#define WLAN_GET_SCAN_TABLE             2
+
+#define WLAN_SETNONE_GETONEINT		(WLANIOCTL + 15)
+#define WLANGETREGION				1
+#define WLAN_GET_LISTEN_INTERVAL		2
+#define WLAN_GET_MULTIPLE_DTIM			3
+#define WLAN_GET_TX_RATE			4
+#define	WLANGETBCNAVG				5
+
+#define WLAN_GET_LINKMODE			6
+#define WLAN_GET_RADIOMODE			7
+#define WLAN_GET_DEBUGMODE			8
+
+#define WLAN_SETTENCHAR_GETNONE		(WLANIOCTL + 16)
+
+#define WLAN_SETNONE_GETTENCHAR		(WLANIOCTL + 17)
+
+#define WLANREGCFRDWR			(WLANIOCTL + 18)
+
+#define WLAN_SETNONE_GETTWELVE_CHAR (WLANIOCTL + 19)
+#define WLAN_SUBCMD_GETRXANTENNA    1
+#define WLAN_SUBCMD_GETTXANTENNA    2
+#define WLAN_GET_TSF                3
+
+#define WLAN_SETWORDCHAR_GETNONE	(WLANIOCTL + 20)
+#define WLANSETADHOCAES				1
+
+#define WLAN_SETNONE_GETWORDCHAR	(WLANIOCTL + 21)
+#define WLANGETADHOCAES				1
+#define WLANVERSION				2
+
+#define WLAN_SETONEINT_GETONEINT	(WLANIOCTL + 23)
+#define WLAN_BEACON_INTERVAL			1
+#define	WLAN_LISTENINTRVL			4
+
+#define WLAN_TXCONTROL				6
+#define WLAN_NULLPKTINTERVAL			7
+
+#define WLAN_SETONEINT_GETNONE		(WLANIOCTL + 24)
+#define WLAN_SUBCMD_SETRXANTENNA		1
+#define WLAN_SUBCMD_SETTXANTENNA		2
+#define WLANSETAUTHALG				5
+#define WLANSET8021XAUTHALG			6
+#define WLANSETENCRYPTIONMODE			7
+#define WLANSETREGION				8
+#define WLAN_SET_LISTEN_INTERVAL		9
+
+#define WLAN_SET_MULTIPLE_DTIM			10
+#define WLAN_SET_ATIM_WINDOW			11
+#define WLANSETBCNAVG				13
+#define WLANSETDATAAVG				14
+#define WLAN_SET_LINKMODE			15
+#define WLAN_SET_RADIOMODE			16
+#define WLAN_SET_DEBUGMODE			17
+
+#define WLAN_SET64CHAR_GET64CHAR	(WLANIOCTL + 25)
+#define WLANSLEEPPARAMS 			2
+#define WLANSCAN_MODE				6
+
+#define WLAN_GET_ADHOC_STATUS			9
+
+#define WLAN_SUBCMD_DFT_ADD			15
+#define WLAN_SUBCMD_DFT_DEL   			16
+#define WLAN_SUBCMD_DFT_LIST			17
+#define WLAN_SUBCMD_BT_ADD			18
+#define WLAN_SUBCMD_BT_DEL   			19
+#define WLAN_SUBCMD_BT_LIST			20
+
+#define WLANEXTSCAN			(WLANIOCTL + 26)
+
+#define WLAN_SET_GET_SIXTEEN_INT       (WLANIOCTL + 29)
+#define WLAN_TPCCFG                             1
+#define WLAN_POWERCFG                           2
+
+#define WLAN_AUTO_FREQ_SET			3
+#define WLAN_AUTO_FREQ_GET			4
+#define WLAN_LED_GPIO_CTRL			5
+#define WLAN_SCANPROBES 			6
+#define WLAN_SLEEP_PERIOD			7
+#define	WLAN_ADAPT_RATESET			8
+#define	WLAN_INACTIVITY_TIMEOUT			9
+#define WLANSNR					10
+#define WLAN_GET_RATE				11
+#define	WLAN_GET_RXINFO				12
+
+#define WLANCMD52RDWR			(WLANIOCTL + 30)
+#define WLANCMD53RDWR			(WLANIOCTL + 31)
+#define CMD53BUFLEN				32
+
+#define	REG_MAC					0x19
+#define	REG_BBP					0x1a
+#define	REG_RF					0x1b
+#define	REG_EEPROM				0x59
+#define WLAN_LINKMODE_802_3			0
+#define WLAN_LINKMODE_802_11			2
+#define WLAN_RADIOMODE_NONE    			0
+#define WLAN_RADIOMODE_RADIOTAP			2
+
+#define	CMD_DISABLED				0
+#define	CMD_ENABLED				1
+#define	CMD_GET					2
+#define SKIP_CMDNUM				4
+#define SKIP_TYPE				1
+#define SKIP_SIZE				2
+#define SKIP_ACTION				2
+#define SKIP_TYPE_SIZE			(SKIP_TYPE + SKIP_SIZE)
+#define SKIP_TYPE_ACTION		(SKIP_TYPE + SKIP_ACTION)
+
+/** wlan_ioctl */
+typedef struct _wlan_ioctl {
+	/** Command ID */
+	u16 command;
+	/** data length */
+	u16 len;
+	/** data pointer */
+	u8 *data;
+} wlan_ioctl;
+
+/** wlan_ioctl_rfantenna */
+typedef struct _wlan_ioctl_rfantenna {
+	u16 Action;
+	u16 AntennaMode;
+} wlan_ioctl_rfantenna;
+
+/** wlan_ioctl_regrdwr */
+typedef struct _wlan_ioctl_regrdwr {
+	/** Which register to access */
+	u16 WhichReg;
+	/** Read or Write */
+	u16 Action;
+	u32 Offset;
+	u16 NOB;
+	u32 Value;
+} wlan_ioctl_regrdwr;
+
+/** wlan_ioctl_cfregrdwr */
+typedef struct _wlan_ioctl_cfregrdwr {
+	/** Read or Write */
+	u8 Action;
+	/** register address */
+	u16 Offset;
+	/** register value */
+	u16 Value;
+} wlan_ioctl_cfregrdwr;
+
+/** wlan_ioctl_rdeeprom */
+typedef struct _wlan_ioctl_rdeeprom {
+	u16 WhichReg;
+	u16 Action;
+	u16 Offset;
+	u16 NOB;
+	u8 Value;
+} wlan_ioctl_rdeeprom;
+
+/** wlan_ioctl_adhoc_key_info */
+typedef struct _wlan_ioctl_adhoc_key_info {
+	u16 action;
+	u8 key[16];
+	u8 tkiptxmickey[16];
+	u8 tkiprxmickey[16];
+} wlan_ioctl_adhoc_key_info;
+
+#ifdef __KERNEL__
+extern struct iw_handler_def libertas_handler_def;
+int libertas_do_ioctl(struct net_device *dev, struct ifreq *req, int i);
+int wlan_radio_ioctl(wlan_private * priv, u8 option);
+/* this one should not be needed in do_ioctl */
+int wlan_set_encode(struct net_device *dev, struct iw_request_info *info,
+			   struct iw_point *dwrq, char *extra);
+#endif
+
+/** sleep_params */
+typedef struct _wlan_ioctl_sleep_params_config {
+	u16 Action;
+	u16 Error;
+	u16 Offset;
+	u16 StableTime;
+	u8 CalControl;
+	u8 ExtSleepClk;
+	u16 Reserved;
+} __attribute__ ((packed)) wlan_ioctl_sleep_params_config,
+    *pwlan_ioctl_sleep_params_config;
+
+/** BCA TIME SHARE */
+typedef struct _wlan_ioctl_bca_timeshare_config {
+	/** ACT_GET/ACT_SET */
+	u16 Action;
+	/** Type: WLAN, BT */
+	u16 TrafficType;
+	/** Interval: 20msec - 60000msec */
+	u32 TimeShareInterval;
+	/** PTA arbiter time in msec */
+	u32 BTTime;
+} __attribute__ ((packed)) wlan_ioctl_bca_timeshare_config,
+    *pwlan_ioctl_bca_timeshare_config;
+
+typedef struct _wlan_ioctl_reassociation_info {
+	u8 CurrentBSSID[6];
+	u8 DesiredBSSID[6];
+	char DesiredSSID[IW_ESSID_MAX_SIZE + 1];
+} __attribute__ ((packed)) wlan_ioctl_reassociation_info;
+
+#endif				/* _WLAN_WEXT_H_ */
diff -Nur -p linux-2.6-orig/drivers/net/wireless/Makefile linux-2.6-libertas/drivers/net/wireless/Makefile
--- linux-2.6-orig/drivers/net/wireless/Makefile	2006-08-06 15:20:11.000000000 -0300
+++ linux-2.6-libertas/drivers/net/wireless/Makefile	2006-08-22 01:37:03.000000000 -0300
@@ -36,7 +36,7 @@ obj-$(CONFIG_PRISM54)		+= prism54/
 
 obj-$(CONFIG_HOSTAP)		+= hostap/
 obj-$(CONFIG_BCM43XX)		+= bcm43xx/
-obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
+obj-$(CONFIG_LIBERTAS_USB)	+= libertas/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
diff -Nur -p linux-2.6-orig/include/net/ieee80211_radiotap.h linux-2.6-libertas/include/net/ieee80211_radiotap.h
--- linux-2.6-orig/include/net/ieee80211_radiotap.h	2006-08-06 15:20:11.000000000 -0300
+++ linux-2.6-libertas/include/net/ieee80211_radiotap.h	2006-08-22 01:37:03.000000000 -0300
@@ -168,6 +168,23 @@ struct ieee80211_radiotap_header {
  *      Unitless indication of the Rx/Tx antenna for this packet.
  *      The first antenna is antenna 0.
  *
+ * IEEE80211_RADIOTAP_RX_FLAGS          u_int16_t       bitmap
+ *
+ *     Properties of received frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_TX_FLAGS          u_int16_t       bitmap
+ *
+ *     Properties of transmitted frames. See flags defined below.
+ *
+ * IEEE80211_RADIOTAP_RTS_RETRIES       u_int8_t        data
+ *
+ *     Number of rts retries a transmitted frame used.
+ *
+ * IEEE80211_RADIOTAP_DATA_RETRIES      u_int8_t        data
+ *
+ *     Number of unicast retries a transmitted frame used.
+ *
+ *
  * IEEE80211_RADIOTAP_FCS           	u32       data
  *
  *	FCS from frame in network byte order.
@@ -187,7 +204,11 @@ enum ieee80211_radiotap_type {
 	IEEE80211_RADIOTAP_ANTENNA = 11,
 	IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12,
 	IEEE80211_RADIOTAP_DB_ANTNOISE = 13,
-	IEEE80211_RADIOTAP_EXT = 31,
+	IEEE80211_RADIOTAP_RX_FLAGS = 14,
+	IEEE80211_RADIOTAP_TX_FLAGS = 15,
+	IEEE80211_RADIOTAP_RTS_RETRIES = 16,
+	IEEE80211_RADIOTAP_DATA_RETRIES = 17,
+	IEEE80211_RADIOTAP_EXT = 31
 };
 
 /* Channel flags. */